CRYOMNI3D: Completely rework file accesses

The previous assumption that all files were identical is wrong.
Use full paths to make it work properly.
This commit is contained in:
Le Philousophe 2023-02-26 18:32:55 +01:00
parent 7dd03c4bc7
commit 4c55d7ae3f
22 changed files with 612 additions and 411 deletions

View File

@ -96,45 +96,8 @@ DATSeekableStream *CryOmni3DEngine::getStaticData(uint32 gameId, uint16 version)
return gameStream;
}
Common::String CryOmni3DEngine::prepareFileName(const Common::String &baseName,
const char *const *extensions) const {
Common::String fname(baseName);
int lastDotPos = fname.size() - 1;
for (; lastDotPos >= 0; --lastDotPos) {
if (fname[lastDotPos] == '.') {
break;
}
}
int extBegin;
if (lastDotPos > -1) {
extBegin = lastDotPos + 1;
fname.erase(extBegin);
} else {
fname += ".";
extBegin = fname.size();
}
while (*extensions != nullptr) {
fname += *extensions;
debug("Trying file %s", fname.c_str());
if (Common::File::exists(fname)) {
return fname;
}
fname.erase(extBegin);
extensions++;
}
fname.deleteLastChar();
warning("Failed to find file %s/%s", baseName.c_str(), fname.c_str());
return baseName;
}
void CryOmni3DEngine::playHNM(const Common::String &filename, Audio::Mixer::SoundType soundType,
void CryOmni3DEngine::playHNM(const Common::Path &filepath, Audio::Mixer::SoundType soundType,
HNMCallback beforeDraw, HNMCallback afterDraw) {
const char *const extensions[] = { "hns", "hnm", "ubb", nullptr };
Common::String fname(prepareFileName(filename, extensions));
Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
byte *currentPalette = nullptr;
if (screenFormat.bytesPerPixel == 1) {
@ -146,8 +109,8 @@ void CryOmni3DEngine::playHNM(const Common::String &filename, Audio::Mixer::Soun
Video::VideoDecoder *videoDecoder = new Video::HNMDecoder(screenFormat, false, currentPalette);
videoDecoder->setSoundType(soundType);
if (!videoDecoder->loadFile(fname)) {
warning("Failed to open movie file %s/%s", filename.c_str(), fname.c_str());
if (!videoDecoder->loadFile(filepath)) {
warning("Failed to open movie file %s", filepath.toString().c_str());
delete videoDecoder;
return;
}
@ -200,20 +163,18 @@ void CryOmni3DEngine::playHNM(const Common::String &filename, Audio::Mixer::Soun
delete videoDecoder;
}
Image::ImageDecoder *CryOmni3DEngine::loadHLZ(const Common::String &filename) {
Common::String fname(prepareFileName(filename, "hlz"));
Image::ImageDecoder *CryOmni3DEngine::loadHLZ(const Common::Path &filepath) {
Common::File file;
if (!file.open(fname)) {
warning("Failed to open hlz file %s/%s", filename.c_str(), fname.c_str());
if (!file.open(filepath)) {
warning("Failed to open hlz file %s", filepath.toString().c_str());
return nullptr;
}
Image::ImageDecoder *imageDecoder = new Image::HLZFileDecoder();
if (!imageDecoder->loadStream(file)) {
warning("Failed to open hlz file %s", fname.c_str());
warning("Failed to load hlz file %s", filepath.toString().c_str());
delete imageDecoder;
imageDecoder = nullptr;
return nullptr;
@ -222,8 +183,8 @@ Image::ImageDecoder *CryOmni3DEngine::loadHLZ(const Common::String &filename) {
return imageDecoder;
}
bool CryOmni3DEngine::displayHLZ(const Common::String &filename, uint32 timeout) {
Image::ImageDecoder *imageDecoder = loadHLZ(filename);
bool CryOmni3DEngine::displayHLZ(const Common::Path &filepath, uint32 timeout) {
Image::ImageDecoder *imageDecoder = loadHLZ(filepath);
if (!imageDecoder) {
return false;

View File

@ -104,7 +104,7 @@ private:
void pauseEngineIntern(bool) override;
public:
Image::ImageDecoder *loadHLZ(const Common::String &filename);
Image::ImageDecoder *loadHLZ(const Common::Path &filepath);
void fillSurface(byte color);
/* We use CursorMan because it avoids problems with cursors in GMM */
@ -112,10 +112,10 @@ public:
void setCursor(uint cursorId) const;
bool showMouse(bool visible) { return CursorMan.showMouse(visible); }
typedef void (CryOmni3DEngine::*HNMCallback)(uint frameNum);
void playHNM(const Common::String &filename,
void playHNM(const Common::Path &filepath,
Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType,
HNMCallback beforeDraw = nullptr, HNMCallback afterDraw = nullptr);
bool displayHLZ(const Common::String &filename, uint32 timeout = uint(-1));
bool displayHLZ(const Common::Path &filepath, uint32 timeout = uint(-1));
bool pollEvents();
Common::Point getMousePos();
@ -129,13 +129,6 @@ public:
void setAutoRepeatClick(uint millis);
DragStatus getDragStatus() { return _dragStatus; }
Common::String prepareFileName(const Common::String &baseName, const char *extension) const {
const char *const extensions[] = { extension, nullptr };
return prepareFileName(baseName, extensions);
}
virtual Common::String prepareFileName(const Common::String &baseName,
const char *const *extensions) const;
virtual bool displayToolbar(const Graphics::Surface *original) = 0;
virtual bool hasPlaceDocumentation() = 0;
virtual bool displayPlaceDocumentation() = 0;

View File

@ -30,10 +30,10 @@ DialogsManager::~DialogsManager() {
delete[] _gtoBuffer;
}
void DialogsManager::loadGTO(const Common::String &gtoFileName) {
void DialogsManager::loadGTO(const Common::Path &gtoFilePath) {
Common::File gtoFile;
if (!gtoFile.open(gtoFileName)) {
error("Can't open GTO file '%s'", gtoFileName.c_str());
if (!gtoFile.open(gtoFilePath)) {
error("Can't open GTO file '%s'", gtoFilePath.toString().c_str());
}
_labels.clear();

View File

@ -48,7 +48,7 @@ public:
virtual ~DialogsManager();
void init(uint arraySize, const Common::String &endOfConversationText) { _dialogsVariables.resize(arraySize); _endOfConversationText = endOfConversationText; }
void loadGTO(const Common::String &gtoFile);
void loadGTO(const Common::Path &gtoFilePath);
void setupVariable(uint id, const Common::String &variable) { _dialogsVariables[id] = DialogVariable(variable, 'N'); }
void reinitVariables();

View File

@ -69,7 +69,7 @@ void ZonFixedImage::run(const CallbackFunctor *callback) {
}
// Just pass a const char * for zone because it's for workarounds and constructing a null String at almost each load call is inefficient
void ZonFixedImage::load(const Common::String &image, const char *zone) {
void ZonFixedImage::load(const Common::Path &image, const char *zone) {
_imageSurface = nullptr;
delete _imageDecoder;
_imageDecoder = nullptr;
@ -80,8 +80,8 @@ void ZonFixedImage::load(const Common::String &image, const char *zone) {
}
_imageSurface = _imageDecoder->getSurface();
const Common::String &zoneFName = zone == nullptr ? image : zone;
loadZones(zoneFName);
Common::Path zonePath(zone ? image.getParent().appendComponent(zone) : image);
loadZones(zonePath);
#if 0
// This is not correct but to debug zones I think it's OK
@ -115,14 +115,20 @@ void ZonFixedImage::display() const {
g_system->updateScreen();
}
void ZonFixedImage::loadZones(const Common::String &image) {
void ZonFixedImage::loadZones(const Common::Path &image) {
_zones.clear();
Common::String fname(_engine.prepareFileName(image, "zon"));
Common::String fname(image.getLastComponent().toString());
int lastDotPos = fname.findLastOf('.');
assert(lastDotPos > -1);
fname.erase(lastDotPos + 1);
fname += "zon";
Common::Path zonPath = image.getParent().appendComponent(fname);
Common::File zonFile;
if (!zonFile.open(fname)) {
error("Can't open ZON file '%s'", fname.c_str());
if (!zonFile.open(zonPath)) {
error("Can't open ZON file '%s'", zonPath.toString().c_str());
}
int32 zonesNumber = zonFile.size() / 26;

View File

@ -68,7 +68,7 @@ public:
void display() const;
/* These functions and attributes are used in image handler */
void load(const Common::String &image, const char *zone = nullptr);
void load(const Common::Path &image, const char *zone = nullptr);
void manage();
void updateSurface(const Graphics::Surface *newSurface);
const Graphics::Surface *surface() const { return _imageSurface; }
@ -109,7 +109,7 @@ protected:
bool valid;
};
void loadZones(const Common::String &image);
void loadZones(const Common::Path &image);
void handleMouseZones(const Common::Array<Zone>::const_iterator &currentZone);
Image::ImageDecoder *_imageDecoder;

View File

@ -54,7 +54,7 @@ FontManager::~FontManager() {
}
}
void FontManager::loadFonts(const Common::Array<Common::String> &fontFiles,
void FontManager::loadFonts(const Common::Array<Common::Path> &fontFiles,
Common::CodePage codepage) {
assert(codepage != Common::kCodePageInvalid);
_codepage = codepage;
@ -66,9 +66,10 @@ void FontManager::loadFonts(const Common::Array<Common::String> &fontFiles,
_fonts.clear();
_fonts.reserve(fontFiles.size());
Common::HashMap<Common::String, Graphics::Font *> fontsCache;
Common::HashMap<Common::Path, Graphics::Font *,
Common::Path::IgnoreCaseAndMac_Hash, Common::Path::IgnoreCaseAndMac_EqualsTo> fontsCache;
for (Common::Array<Common::String>::const_iterator it = fontFiles.begin(); it != fontFiles.end();
for (Common::Array<Common::Path>::const_iterator it = fontFiles.begin(); it != fontFiles.end();
it++) {
Graphics::Font *fontEntry = nullptr;
if (fontsCache.tryGetVal(*it, fontEntry)) {
@ -93,7 +94,7 @@ void FontManager::loadFonts(const Common::Array<Common::String> &fontFiles,
}
}
void FontManager::loadTTFList(const Common::String &ttfList, Common::CodePage codepage) {
void FontManager::loadTTFList(const Common::Path &ttfList, Common::CodePage codepage) {
#ifdef USE_FREETYPE2
assert(codepage != Common::kCodePageInvalid);
_codepage = codepage;
@ -107,9 +108,11 @@ void FontManager::loadTTFList(const Common::String &ttfList, Common::CodePage co
Common::File list;
if (!list.open(ttfList)) {
error("can't open file %s", ttfList.c_str());
error("can't open file %s", ttfList.toString().c_str());
}
Common::Path ttfParentDir(ttfList.getParent());
Common::String line = list.readLine();
uint32 num = atoi(line.c_str());
@ -141,6 +144,7 @@ void FontManager::loadTTFList(const Common::String &ttfList, Common::CodePage co
Common::Array<Common::String> fontFiles;
fontFiles.push_back(fontFile);
fontFiles.push_back(ttfParentDir.appendComponent(fontFile).toString());
// Use 96 dpi as it's the default under Windows
Graphics::Font *font = Graphics::findTTFace(fontFiles, uniFontFace, bold, italic, -(int)size,

View File

@ -41,8 +41,8 @@ public:
FontManager();
virtual ~FontManager();
void loadFonts(const Common::Array<Common::String> &fontFiles, Common::CodePage codepage);
void loadTTFList(const Common::String &listFile, Common::CodePage codepage);
void loadFonts(const Common::Array<Common::Path> &fontFiles, Common::CodePage codepage);
void loadTTFList(const Common::Path &listFile, Common::CodePage codepage);
void setCurrentFont(int currentFont);
uint getCurrentFont() { return _currentFontId; }
void setTransparentBackground(bool transparent) { _transparentBackground = transparent; }

View File

@ -31,7 +31,7 @@ CryoExtFont::~CryoExtFont() {
delete _crf;
}
void CryoExtFont::load(const Common::String &fontFile, Common::CodePage codepage) {
void CryoExtFont::load(const Common::Path &fontFile, Common::CodePage codepage) {
// For now only CP950 is supported
assert(codepage == Common::kWindows950);
@ -40,7 +40,7 @@ void CryoExtFont::load(const Common::String &fontFile, Common::CodePage codepage
Common::File *crf = new Common::File();
if (!crf->open(fontFile)) {
error("can't open file %s", fontFile.c_str());
error("can't open file %s", fontFile.toString().c_str());
}
_crf = crf;
@ -63,16 +63,16 @@ void CryoExtFont::load(const Common::String &fontFile, Common::CodePage codepage
_crf->read(_comment, sizeof(_comment));
//debug("Comment %s", _comment);
Common::String offsetsFile = fontFile;
Common::String offsetsFile = fontFile.getLastComponent().toString();
offsetsFile.setChar('I', offsetsFile.size() - 1);
loadOffsets(offsetsFile);
loadOffsets(fontFile.getParent().appendComponent(offsetsFile));
}
void CryoExtFont::loadOffsets(const Common::String &offsetsFile) {
void CryoExtFont::loadOffsets(const Common::Path &offsetsFile) {
Common::File cri;
if (!cri.open(offsetsFile)) {
error("can't open file %s", offsetsFile.c_str());
error("can't open file %s", offsetsFile.toString().c_str());
}
uint32 counts = cri.size() / sizeof(uint32);

View File

@ -38,7 +38,7 @@ public:
CryoExtFont() : _height(0), _maxAdvance(0), _crf(nullptr), _codepage(Common::kCodePageInvalid) { }
virtual ~CryoExtFont();
void load(const Common::String &fontFile, Common::CodePage encoding);
void load(const Common::Path &fontFile, Common::CodePage encoding);
virtual int getFontHeight() const { return _height; }
virtual int getMaxCharWidth() const { return _maxAdvance; }
@ -50,7 +50,7 @@ public:
virtual void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const;
private:
void loadOffsets(const Common::String &offsetsFile);
void loadOffsets(const Common::Path &offsetsFile);
void assureCached(uint32 chr) const;
uint32 mapGlyph(uint32 chr) const;

View File

@ -27,11 +27,11 @@
namespace CryOmni3D {
void CryoFont::load(const Common::String &fontFile) {
void CryoFont::load(const Common::Path &fontFile) {
Common::File crf;
if (!crf.open(fontFile)) {
error("can't open file %s", fontFile.c_str());
error("can't open file %s", fontFile.toString().c_str());
}
byte magic[8];

View File

@ -37,7 +37,7 @@ class CryoFont : public Graphics::Font {
public:
CryoFont() : _height(0), _maxAdvance(0) { }
void load(const Common::String &fontFile);
void load(const Common::Path &fontFile);
virtual int getFontHeight() const { return _height; }
virtual int getMaxCharWidth() const { return _maxAdvance; }

View File

@ -33,7 +33,7 @@ bool CryOmni3DEngine_Versailles::preprocessDialog(const Common::String &sequence
}
if (_currentLevel == 1 && _currentPlaceId == 3) {
playInGameVideo("11D_LEB1");
playInGameAnimVideo("11D_LEB1");
}
_dialogsMan["{JOUEUR-VU-MEMORANDUM-DANS-LUSTRE-DU-SALON-DE-LA-GUERRE}"] = 'N';
@ -119,7 +119,7 @@ void CryOmni3DEngine_Versailles::postprocessDialog(const Common::String &sequenc
}
if (!_gameVariables[GameVariables::kGotMedalsSolution] &&
_dialogsMan["MONSIEUR-DONNE-SOLUTION-MEDAILLES"] == 'Y') {
playInGameVideo("32M_MR2");
playInGameAnimVideo("32M_MR2");
_gameVariables[GameVariables::kGotMedalsSolution] = 1;
}
if (!_gameVariables[GameVariables::kDecipherScore] &&
@ -293,7 +293,7 @@ void CryOmni3DEngine_Versailles::dialogShowBontempsGivesKey() {
}
void CryOmni3DEngine_Versailles::dialogShowDuMaineLeaves() {
playInGameVideo("62S_DUC1");
playInGameAnimVideo("62S_DUC1");
_inventory.removeByNameID(144);
setPlaceState(19, 1);
}
@ -312,7 +312,7 @@ void CryOmni3DEngine_Versailles::dialogShowLeBrunGives() {
}
void CryOmni3DEngine_Versailles::dialogShowLeBrunLeave() {
playInGameVideo("11D_LEB3");
playInGameAnimVideo("11D_LEB3");
setGameTime(2, 1);
}

View File

@ -93,28 +93,27 @@ void Versailles_DialogsManager::executeShow(const Common::String &show) {
void Versailles_DialogsManager::playDialog(const Common::String &video, const Common::String &sound,
const Common::String &text, const SubtitlesSettings &settings) {
// Don't look for HNS file here
Common::String videoFName(_engine->prepareFileName(video, "hnm"));
Common::String soundFName(sound);
if (_padAudioFileName) {
while (soundFName.size() < 8) {
soundFName += '_';
}
}
soundFName = _engine->prepareFileName(soundFName, "wav");
Common::Path videoPath(_engine->getFilePath(kFileTypeDialAnim, video));
Common::Path soundPath(_engine->getFilePath(kFileTypeDialSound, soundFName));
Video::HNMDecoder *videoDecoder = new Video::HNMDecoder(g_system->getScreenFormat(), true);
if (!videoDecoder->loadFile(videoFName)) {
warning("Failed to open movie file %s/%s", video.c_str(), videoFName.c_str());
if (!videoDecoder->loadFile(videoPath)) {
warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString().c_str());
delete videoDecoder;
return;
}
Common::File *audioFile = new Common::File();
if (!audioFile->open(soundFName)) {
warning("Failed to open sound file %s/%s", sound.c_str(), soundFName.c_str());
if (!audioFile->open(soundPath)) {
warning("Failed to open sound file %s/%s", sound.c_str(), soundPath.toString().c_str());
delete videoDecoder;
delete audioFile;
return;
@ -353,12 +352,12 @@ uint Versailles_DialogsManager::askPlayerQuestions(const Common::String &video,
}
void Versailles_DialogsManager::loadFrame(const Common::String &video) {
Common::String videoFName(_engine->prepareFileName(video, "hnm"));
Common::Path videoPath(_engine->getFilePath(kFileTypeDialAnim, video));
Video::HNMDecoder *videoDecoder = new Video::HNMDecoder(g_system->getScreenFormat());
if (!videoDecoder->loadFile(videoFName)) {
warning("Failed to open movie file %s/%s", video.c_str(), videoFName.c_str());
if (!videoDecoder->loadFile(videoPath)) {
warning("Failed to open movie file %s/%s", video.c_str(), videoPath.toString().c_str());
delete videoDecoder;
return;
}

View File

@ -81,14 +81,14 @@ const Versailles_Documentation::TimelineEntry Versailles_Documentation::kTimelin
};
void Versailles_Documentation::init(const Sprites *sprites, FontManager *fontManager,
const Common::StringArray *messages, CryOmni3DEngine *engine,
const Common::String &allDocsFileName, const Common::String &linksDocsFileName) {
const Common::StringArray *messages, CryOmni3DEngine_Versailles *engine,
const Common::Path &allDocsFilePath, const Common::Path &linksDocsFilePath) {
_sprites = sprites;
_fontManager = fontManager;
_messages = messages;
_engine = engine;
_allDocsFileName = allDocsFileName;
_linksDocsFileName = linksDocsFileName;
_allDocsFilePath = allDocsFilePath;
_linksDocsFilePath = linksDocsFilePath;
// Japanese version of Versailles handles records attributes with multilines
_multilineAttributes = (_engine->getLanguage() == Common::JA_JPN);
@ -96,8 +96,8 @@ void Versailles_Documentation::init(const Sprites *sprites, FontManager *fontMan
// Build list of records
Common::File allDocsFile;
if (!allDocsFile.open(_allDocsFileName)) {
error("Can't open %s", _allDocsFileName.c_str());
if (!allDocsFile.open(_allDocsFilePath)) {
error("Can't open %s", _allDocsFilePath.toString().c_str());
}
uint allDocsSize = allDocsFile.size();
@ -283,7 +283,7 @@ Common::String Versailles_Documentation::docAreaHandleSummary() {
Image::BitmapDecoder bmpDecoder;
Common::File file;
Image::ImageDecoder *imageDecoder = _engine->loadHLZ("SOM1.HLZ");
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(_engine->getFilePath(kFileTypeDocBg, "SOM1.HLZ"));
if (!imageDecoder) {
return "";
}
@ -294,7 +294,7 @@ Common::String Versailles_Documentation::docAreaHandleSummary() {
// No BMP to load
continue;
}
if (!file.open(categories[i].bmp)) {
if (!file.open(_engine->getFilePath(kFileTypeSpriteBmp, categories[i].bmp))) {
error("Failed to open BMP file: %s", categories[i].bmp);
}
if (!bmpDecoder.loadStream(file)) {
@ -428,7 +428,7 @@ Common::String Versailles_Documentation::docAreaHandleSummary() {
}
Common::String Versailles_Documentation::docAreaHandleTimeline() {
Image::ImageDecoder *imageDecoder = _engine->loadHLZ("chrono1.HLZ");
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(_engine->getFilePath(kFileTypeDocBg, "chrono1.HLZ"));
if (!imageDecoder) {
return "";
}
@ -913,7 +913,7 @@ Common::String Versailles_Documentation::docAreaHandleGeneralMap() {
Image::BitmapDecoder bmpDecoder;
Common::File file;
Image::ImageDecoder *imageDecoder = _engine->loadHLZ("PLANGR.HLZ");
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(_engine->getFilePath(kFileTypeDocBg, "PLANGR.HLZ"));
if (!imageDecoder) {
return "";
}
@ -921,7 +921,7 @@ Common::String Versailles_Documentation::docAreaHandleGeneralMap() {
for (uint i = 0; i < ARRAYSIZE(areas); i++) {
if (areas[i].bmp) {
if (!file.open(areas[i].bmp)) {
if (!file.open(_engine->getFilePath(kFileTypeSpriteBmp, areas[i].bmp))) {
error("Failed to open BMP file: %s", areas[i].bmp);
}
if (!bmpDecoder.loadStream(file)) {
@ -1167,7 +1167,7 @@ Common::String Versailles_Documentation::docAreaHandleCastleMap() {
boxes.setupBox(ARRAYSIZE(areas), 639 - _sprites->getCursor(105).getWidth(),
479 - _sprites->getCursor(105).getHeight(), 640, 480);
Image::ImageDecoder *imageDecoder = _engine->loadHLZ("PLAN.HLZ");
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(_engine->getFilePath(kFileTypeDocBg, "PLAN.HLZ"));
if (!imageDecoder) {
return "";
}
@ -1464,15 +1464,13 @@ void Versailles_Documentation::drawRecordData(Graphics::ManagedSurface &surface,
} else {
background = _currentRecord;
}
background = _engine->prepareFileName(background, "hlz");
Common::File backgroundFl;
if (!backgroundFl.open(background)) {
Common::Path backgroundPath = _engine->getFilePath(kFileTypeDocBg, background);
if (!Common::File::exists(backgroundPath)) {
background = _currentMapLayout ? "pas_fonP.hlz" : "pas_fond.hlz";
} else {
backgroundFl.close();
backgroundPath = _engine->getFilePath(kFileTypeDocBg, background);
}
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(background);
Image::ImageDecoder *imageDecoder = _engine->loadHLZ(backgroundPath);
const Graphics::Surface *bgFrame = imageDecoder->getSurface();
_engine->setupPalette(imageDecoder->getPalette(), imageDecoder->getPaletteStartIndex(),
@ -1973,8 +1971,8 @@ Common::String Versailles_Documentation::getRecordTitle(const Common::String &re
const RecordInfo &recordInfo = it->_value;
Common::File allDocsFile;
if (!allDocsFile.open(_allDocsFileName)) {
error("Can't open %s", _allDocsFileName.c_str());
if (!allDocsFile.open(_allDocsFilePath)) {
error("Can't open %s", _allDocsFilePath.toString().c_str());
}
allDocsFile.seek(recordInfo.position);
@ -2002,8 +2000,8 @@ Common::String Versailles_Documentation::getRecordData(const Common::String &rec
const RecordInfo &recordInfo = it->_value;
Common::File allDocsFile;
if (!allDocsFile.open(_allDocsFileName)) {
error("Can't open %s", _allDocsFileName.c_str());
if (!allDocsFile.open(_allDocsFilePath)) {
error("Can't open %s", _allDocsFilePath.toString().c_str());
}
allDocsFile.seek(recordInfo.position);
@ -2056,8 +2054,8 @@ void Versailles_Documentation::loadLinksFile() {
}
Common::File linksFile;
if (!linksFile.open(_linksDocsFileName)) {
error("Can't open links file: %s", _linksDocsFileName.c_str());
if (!linksFile.open(_linksDocsFilePath)) {
error("Can't open links file: %s", _linksDocsFilePath.toString().c_str());
}
_linksSize = linksFile.size();

View File

@ -33,9 +33,9 @@ class FontManager;
class MouseBoxes;
class Sprites;
class CryOmni3DEngine;
namespace Versailles {
class CryOmni3DEngine_Versailles;
class Versailles_Documentation {
public:
Versailles_Documentation() : _engine(nullptr), _fontManager(nullptr), _sprites(nullptr),
@ -44,8 +44,8 @@ public:
~Versailles_Documentation() { delete [] _linksData; }
void init(const Sprites *sprites, FontManager *fontManager, const Common::StringArray *messages,
CryOmni3DEngine *engine, const Common::String &allDocsFileName,
const Common::String &linksDocsFileName);
CryOmni3DEngine_Versailles *engine, const Common::Path &allDocsFilePath,
const Common::Path &linksDocsFilePath);
void handleDocArea();
void handleDocInGame(const Common::String &record);
@ -110,12 +110,12 @@ private:
void loadLinksFile();
void getLinks(const Common::String &record, Common::Array<LinkInfo> &links);
Common::String _allDocsFileName;
Common::String _linksDocsFileName;
Common::Path _allDocsFilePath;
Common::Path _linksDocsFilePath;
static const uint kPopupMenuMargin = 5;
CryOmni3DEngine *_engine;
CryOmni3DEngine_Versailles *_engine;
FontManager *_fontManager;
const Sprites *_sprites;
const Common::StringArray *_messages;

View File

@ -79,10 +79,36 @@ bool CryOmni3DEngine_Versailles::hasFeature(EngineFeature f) const {
}
void CryOmni3DEngine_Versailles::initializePath(const Common::FSNode &gamePath) {
// All files are named uniquely so just add the main directory with a large enough depth and in flat mode
// That should do it
SearchMan.setIgnoreClashes(true);
SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 5, true);
// This works if the user has installed the game as required in the Wiki
SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 4, false);
// CDs/DVD path
SearchMan.addSubDirectoryMatching(gamePath, "datas_v", 0, 4, false);
// If user has copied CDs in different directories
SearchMan.addSubDirectoryMatching(gamePath, "datas_v1", 0, 4, false);
SearchMan.addSubDirectoryMatching(gamePath, "datas_v2", 0, 4, false);
// Default hard-drive path location on CD
if (getPlatform() == Common::kPlatformMacintosh) {
switch (getLanguage()) {
case Common::DE_DEU:
SearchMan.addSubDirectoryMatching(gamePath, "versailles ordner/datav_hd", 0, 3, false);
break;
case Common::EN_ANY:
SearchMan.addSubDirectoryMatching(gamePath, "versailles folder/datav_hd", 0, 3, false);
break;
case Common::FR_FRA:
SearchMan.addSubDirectoryMatching(gamePath, "dossier versailles/datav_hd", 0, 3, false);
break;
default:
// We don't know any other variant but don't error out
break;
}
} else {
SearchMan.addSubDirectoryMatching(gamePath, "install/data", 0, 3, false);
SearchMan.addSubDirectoryMatching(gamePath, "install/datas_v", 0, 3, false);
}
}
Common::Error CryOmni3DEngine_Versailles::run() {
@ -96,7 +122,7 @@ Common::Error CryOmni3DEngine_Versailles::run() {
_gameVariables.resize(GameVariables::kMax);
_omni3dMan.init(75. / 180. * M_PI);
_dialogsMan.loadGTO(_localizedFilenames[LocalizedFilenames::kDialogs]);
_dialogsMan.loadGTO(getFilePath(kFileTypeGTO, _localizedFilenames[LocalizedFilenames::kDialogs]));
setupDialogVariables();
setupDialogShows();
@ -130,10 +156,10 @@ Common::Error CryOmni3DEngine_Versailles::run() {
// Documentation is needed by noone at init time, let's do it last
initDocPeopleRecord();
_docManager.init(&_sprites, &_fontManager, &_messages, this,
_localizedFilenames[LocalizedFilenames::kAllDocs],
getFeatures() & GF_VERSAILLES_LINK_LOCALIZED ?
getFilePath(kFileTypeText, _localizedFilenames[LocalizedFilenames::kAllDocs]),
getFilePath(kFileTypeText, getFeatures() & GF_VERSAILLES_LINK_LOCALIZED ?
_localizedFilenames[LocalizedFilenames::kLinksDocs] :
"lien_doc.txt");
"lien_doc.txt"));
_countdownSurface.create(40, 15, Graphics::PixelFormat::createFormatCLUT8());
@ -256,47 +282,231 @@ bool CryOmni3DEngine_Versailles::shouldAbort() {
return _isPlaying && _abortCommand != kAbortNoAbort;
}
Common::String CryOmni3DEngine_Versailles::prepareFileName(const Common::String &baseName,
const char *const *extensions) const {
static bool checkFilePath(const Common::Path &basePath, Common::String &baseName, const char * const *extensions, Common::Path &fullPath) {
if (!extensions) {
fullPath = basePath.appendComponent(baseName);
debug(3, "Trying file %s", fullPath.toString().c_str());
return Common::File::exists(fullPath);
}
int extBegin = baseName.size();
while (*extensions != nullptr) {
baseName += *extensions;
fullPath = basePath.appendComponent(baseName);
debug(3, "Trying file %s", fullPath.toString().c_str());
if (Common::File::exists(fullPath)) {
return true;
}
baseName.erase(extBegin);
extensions++;
}
return false;
}
Common::Path CryOmni3DEngine_Versailles::getFilePath(FileType fileType,
const Common::String &baseName) const {
const char **extensions = nullptr;
bool hasLevel = false;
const char *baseDir = nullptr;
switch (fileType) {
case kFileTypeAnimacti:
case kFileTypeDialAnim:
case kFileTypeWarpHNM: {
static const char *extensions_[] = { "hnm", nullptr };
extensions = extensions_;
break;
}
case kFileTypeTransScene: {
static const char *extensions_[] = { "hns", "hnm", nullptr };
extensions = extensions_;
break;
}
case kFileTypeDocBg:
case kFileTypeFixedImg:
case kFileTypeMenu:
case kFileTypeObject:
case kFileTypeTransSceneI:
case kFileTypeWarpCyclo: {
static const char *extensions_[] = { "hlz", nullptr };
extensions = extensions_;
break;
}
case kFileTypeDialSound:
case kFileTypeMusic:
case kFileTypeSound: {
static const char *extensions_[] = { "wav", nullptr };
extensions = extensions_;
break;
}
case kFileTypeFont:
case kFileTypeGTO:
case kFileTypeSaveGameVisit:
case kFileTypeSprite:
case kFileTypeSpriteBmp:
case kFileTypeText:
case kFileTypeWAM:
break;
default:
error("Invalid file type");
}
switch (fileType) {
case kFileTypeAnimacti:
baseDir = "animacti/level%d";
hasLevel = true;
break;
case kFileTypeDocBg:
baseDir = "basedoc/fonds";
break;
case kFileTypeDialAnim:
baseDir = "dial/flc_dial";
break;
case kFileTypeDialSound:
baseDir = "dial/voix";
break;
case kFileTypeFixedImg:
baseDir = "img_fix/level%d";
hasLevel = true;
break;
case kFileTypeFont:
baseDir = "fonts";
break;
case kFileTypeGTO:
baseDir = "gto";
break;
case kFileTypeMenu:
baseDir = "menu";
break;
case kFileTypeMusic:
baseDir = "music";
break;
case kFileTypeObject:
baseDir = "objets";
break;
case kFileTypeSaveGameVisit:
baseDir = "savegame/visite";
break;
case kFileTypeTransSceneI:
case kFileTypeTransScene:
baseDir = "sc_trans";
break;
case kFileTypeSound:
baseDir = "sound";
break;
case kFileTypeSprite:
baseDir = "spr8col";
break;
case kFileTypeSpriteBmp:
baseDir = "spr8col/bmpOK";
break;
case kFileTypeText:
baseDir = "textes";
break;
case kFileTypeWAM:
baseDir = "wam";
break;
case kFileTypeWarpCyclo:
baseDir = "warp/level%d/cyclo";
hasLevel = true;
break;
case kFileTypeWarpHNM:
baseDir = "warp/level%d/hnm";
hasLevel = true;
break;
default:
error("Invalid file type");
}
Common::String baseName_(baseName);
if (getPlatform() != Common::kPlatformMacintosh) {
// Replace dashes by underscores for PC versions
if ((getPlatform() != Common::kPlatformMacintosh) ||
(getLanguage() != Common::FR_FRA)) {
// Replace dashes by underscores for all versions except Mac FR
char *p = baseName_.begin();
while ((p = strchr(p, '-')) != nullptr) {
*p = '_';
p++;
}
}
return CryOmni3DEngine::prepareFileName(baseName_, extensions);
if (extensions) {
// We will rewrite the extension: strip the provided one
// or append the extension dot
int lastDotPos = baseName_.findLastOf('.');
if (lastDotPos > -1) {
baseName_.erase(lastDotPos + 1);
} else {
baseName_ += ".";
}
}
// We are ready, build path and check
Common::Path basePath;
if (hasLevel) {
basePath = Common::String::format(baseDir, _currentLevel);
} else {
basePath = baseDir;
}
Common::Path fullPath;
if (checkFilePath(basePath, baseName_, extensions, fullPath)) {
return fullPath;
}
if (!hasLevel) {
warning("Failed to find file %s in %s", baseName.c_str(), baseDir);
return baseName;
}
assert(baseName_.size() > 0);
if (baseName_[0] < '1' ||
baseName_[0] > '7' ||
uint(baseName_[0] - '0') == _currentLevel) {
warning("Failed to find file %s in %s (level %d)", baseName.c_str(), baseDir, _currentLevel);
return baseName;
}
int fileLevel = baseName_[0] - '0';
basePath = Common::String::format(baseDir, fileLevel);
if (checkFilePath(basePath, baseName_, extensions, fullPath)) {
return fullPath;
}
warning("Failed to find file %s in %s (levels %d and %d)", baseName.c_str(), baseDir, _currentLevel, fileLevel);
return baseName;
}
void CryOmni3DEngine_Versailles::setupFonts() {
Common::Array<Common::String> fonts;
Common::Array<Common::Path> fonts;
// Explainations below are based on original binaries, debug is not used in this engine
// Fonts loaded are not always the same: FR Mac and EN DOS don't use the same font for debug doc/unused
// The important is that the loaded one is present in all versions
#define ADD_FONT(f) fonts.push_back(getFilePath(kFileTypeFont, f))
if (getLanguage() == Common::ZH_TWN) {
fonts.push_back("tw13.CRF"); // 0: Doc titles
fonts.push_back("tw18.CRF"); // 1: Menu and T0 in credits
fonts.push_back("tw13.CRF"); // 2: T1 and T3 in credits
fonts.push_back("tw12.CRF"); // 3: Menu title, options messages boxes buttons
fonts.push_back("tw12.CRF"); // 4: T2 in credits, text in docs
fonts.push_back("tw12.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
fonts.push_back("tw12.CRF"); // 6: T5 in credits, doc subtitle
fonts.push_back("tw12.CRF"); // 7: dialogs texts
fonts.push_back("tw12.CRF"); // 8: unused
fonts.push_back("tw12.CRF"); // 9: Warp messages texts
fonts.push_back("tw12.CRF"); // 10: debug
ADD_FONT("tw13.CRF"); // 0: Doc titles
ADD_FONT("tw18.CRF"); // 1: Menu and T0 in credits
ADD_FONT("tw13.CRF"); // 2: T1 and T3 in credits
ADD_FONT("tw12.CRF"); // 3: Menu title, options messages boxes buttons
ADD_FONT("tw12.CRF"); // 4: T2 in credits, text in docs
ADD_FONT("tw12.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
ADD_FONT("tw12.CRF"); // 6: T5 in credits, doc subtitle
ADD_FONT("tw12.CRF"); // 7: dialogs texts
ADD_FONT("tw12.CRF"); // 8: unused
ADD_FONT("tw12.CRF"); // 9: Warp messages texts
ADD_FONT("tw12.CRF"); // 10: debug
_fontManager.loadFonts(fonts, Common::kWindows950);
return;
} else if (getLanguage() == Common::JA_JPN) {
_fontManager.loadTTFList("FONTS_JP.LST", Common::kWindows932);
_fontManager.loadTTFList(getFilePath(kFileTypeFont, "FONTS_JP.LST"), Common::kWindows932);
return;
} else if (getLanguage() == Common::KO_KOR) {
_fontManager.loadTTFList("FONTS_KR.LST", Common::kWindows949);
_fontManager.loadTTFList(getFilePath(kFileTypeFont, "FONTS_KR.LST"), Common::kWindows949);
return;
}
@ -304,79 +514,81 @@ void CryOmni3DEngine_Versailles::setupFonts() {
uint8 fontsSet = getFeatures() & GF_VERSAILLES_FONTS_MASK;
switch (fontsSet) {
case GF_VERSAILLES_FONTS_NUMERIC:
fonts.push_back("font01.CRF"); // 0: Doc titles
fonts.push_back("font02.CRF"); // 1: Menu and T0 in credits
fonts.push_back("font03.CRF"); // 2: T1 and T3 in credits
fonts.push_back("font04.CRF"); // 3: Menu title, options messages boxes buttons
fonts.push_back("font05.CRF"); // 4: T2 in credits, text in docs
fonts.push_back("font06.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
fonts.push_back("font07.CRF"); // 6: T5 in credits, doc subtitle
fonts.push_back("font08.CRF"); // 7: dialogs texts
fonts.push_back("font09.CRF"); // 8: unused
fonts.push_back("font10.CRF"); // 9: Warp messages texts
fonts.push_back("font11.CRF"); // 10: debug
ADD_FONT("font01.CRF"); // 0: Doc titles
ADD_FONT("font02.CRF"); // 1: Menu and T0 in credits
ADD_FONT("font03.CRF"); // 2: T1 and T3 in credits
ADD_FONT("font04.CRF"); // 3: Menu title, options messages boxes buttons
ADD_FONT("font05.CRF"); // 4: T2 in credits, text in docs
ADD_FONT("font06.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
ADD_FONT("font07.CRF"); // 6: T5 in credits, doc subtitle
ADD_FONT("font08.CRF"); // 7: dialogs texts
ADD_FONT("font09.CRF"); // 8: unused
ADD_FONT("font10.CRF"); // 9: Warp messages texts
ADD_FONT("font11.CRF"); // 10: debug
break;
case GF_VERSAILLES_FONTS_SET_A:
fonts.push_back("garamB18.CRF"); // 0: Doc titles
fonts.push_back("garamB22.CRF"); // 1: Menu and T0 in credits
//fonts.push_back("geneva15.CRF");
fonts.push_back("geneva14.CRF"); // 3: T1 and T3 in credits
fonts.push_back("geneva13.CRF"); // 4: Menu title, options messages boxes buttons
fonts.push_back("geneva12.CRF"); // 5: T2 in credits, text in docs
fonts.push_back("geneva10.CRF"); // 6: objects description in toolbar, options messages boxes text, T4 in credits
fonts.push_back("geneva9.CRF"); // 7: T5 in credits, doc subtitle
//fonts.push_back("helvet24.CRF");
fonts.push_back("helvet16.CRF"); // 9: dialogs texts
//fonts.push_back("helvet14.CRF");
//fonts.push_back("helvet13.CRF");
//fonts.push_back("helvet12.CRF");
//fonts.push_back("helvet11.CRF");
//fonts.push_back("helvet9.CRF");
//fonts.push_back("fruitL9.CRF");
fonts.push_back("fruitL10.CRF"); // 16: debug doc
//fonts.push_back("fruitL11.CRF");
//fonts.push_back("fruitL12.CRF");
//fonts.push_back("fruitL13.CRF");
//fonts.push_back("fruitL14.CRF");
//fonts.push_back("fruitL16.CRF");
fonts.push_back("fruitL18.CRF"); // 22: Warp messages texts
//fonts.push_back("arial11.CRF");
fonts.push_back("MPW12.CRF"); // 24: debug
//fonts.push_back("MPW9.CRF");
ADD_FONT("garamB18.CRF"); // 0: Doc titles
ADD_FONT("garamB22.CRF"); // 1: Menu and T0 in credits
//ADD_FONT("geneva15.CRF");
ADD_FONT("geneva14.CRF"); // 3: T1 and T3 in credits
ADD_FONT("geneva13.CRF"); // 4: Menu title, options messages boxes buttons
ADD_FONT("geneva12.CRF"); // 5: T2 in credits, text in docs
ADD_FONT("geneva10.CRF"); // 6: objects description in toolbar, options messages boxes text, T4 in credits
ADD_FONT("geneva9.CRF"); // 7: T5 in credits, doc subtitle
//ADD_FONT("helvet24.CRF");
ADD_FONT("helvet16.CRF"); // 9: dialogs texts
//ADD_FONT("helvet14.CRF");
//ADD_FONT("helvet13.CRF");
//ADD_FONT("helvet12.CRF");
//ADD_FONT("helvet11.CRF");
//ADD_FONT("helvet9.CRF");
//ADD_FONT("fruitL9.CRF");
ADD_FONT("fruitL10.CRF"); // 16: debug doc
//ADD_FONT("fruitL11.CRF");
//ADD_FONT("fruitL12.CRF");
//ADD_FONT("fruitL13.CRF");
//ADD_FONT("fruitL14.CRF");
//ADD_FONT("fruitL16.CRF");
ADD_FONT("fruitL18.CRF"); // 22: Warp messages texts
//ADD_FONT("arial11.CRF");
ADD_FONT("MPW12.CRF"); // 24: debug
//ADD_FONT("MPW9.CRF");
// This file isn't even loaded by MacOS executable
//fonts.push_back("garamB20.CRF");
//ADD_FONT("garamB20.CRF");
break;
case GF_VERSAILLES_FONTS_SET_B:
fonts.push_back("garamB18.CRF"); // 0: Doc titles
fonts.push_back("garamB22.CRF"); // 1: Menu and T0 in credits
fonts.push_back("geneva14.CRF"); // 2: T1 and T3 in credits
fonts.push_back("geneva13.CRF"); // 3: Menu title, options messages boxes buttons
fonts.push_back("geneva12.CRF"); // 4: T2 in credits, text in docs
fonts.push_back("geneva10.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
fonts.push_back("geneva9.CRF"); // 6: T5 in credits, doc subtitle
fonts.push_back("helvet16.CRF"); // 7: dialogs texts
fonts.push_back("helvet12.CRF"); // 8: debug doc
fonts.push_back("fruitL18.CRF"); // 9: Warp messages texts
fonts.push_back("MPW12.CRF"); // 10: debug
ADD_FONT("garamB18.CRF"); // 0: Doc titles
ADD_FONT("garamB22.CRF"); // 1: Menu and T0 in credits
ADD_FONT("geneva14.CRF"); // 2: T1 and T3 in credits
ADD_FONT("geneva13.CRF"); // 3: Menu title, options messages boxes buttons
ADD_FONT("geneva12.CRF"); // 4: T2 in credits, text in docs
ADD_FONT("geneva10.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
ADD_FONT("geneva9.CRF"); // 6: T5 in credits, doc subtitle
ADD_FONT("helvet16.CRF"); // 7: dialogs texts
ADD_FONT("helvet12.CRF"); // 8: debug doc
ADD_FONT("fruitL18.CRF"); // 9: Warp messages texts
ADD_FONT("MPW12.CRF"); // 10: debug
break;
case GF_VERSAILLES_FONTS_SET_C:
fonts.push_back("garamB18.CRF"); // 0: Doc titles
fonts.push_back("garamB22.CRF"); // 1: Menu and T0 in credits
fonts.push_back("geneva14.CRF"); // 2: T1 and T3 in credits
fonts.push_back("geneva13.CRF"); // 3: Menu title, options messages boxes buttons
fonts.push_back("helvet12.CRF"); // 4: T2 in credits, text in docs
fonts.push_back("geneva10.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
fonts.push_back("geneva9.CRF"); // 6: T5 in credits, doc subtitle
fonts.push_back("helvet16.CRF"); // 7: dialogs texts
fonts.push_back("helvet12.CRF"); // 8: debug doc
fonts.push_back("fruitL18.CRF"); // 9: Warp messages texts
fonts.push_back("MPW12.CRF"); // 10: debug
ADD_FONT("garamB18.CRF"); // 0: Doc titles
ADD_FONT("garamB22.CRF"); // 1: Menu and T0 in credits
ADD_FONT("geneva14.CRF"); // 2: T1 and T3 in credits
ADD_FONT("geneva13.CRF"); // 3: Menu title, options messages boxes buttons
ADD_FONT("helvet12.CRF"); // 4: T2 in credits, text in docs
ADD_FONT("geneva10.CRF"); // 5: objects description in toolbar, options messages boxes text, T4 in credits
ADD_FONT("geneva9.CRF"); // 6: T5 in credits, doc subtitle
ADD_FONT("helvet16.CRF"); // 7: dialogs texts
ADD_FONT("helvet12.CRF"); // 8: debug doc
ADD_FONT("fruitL18.CRF"); // 9: Warp messages texts
ADD_FONT("MPW12.CRF"); // 10: debug
break;
default:
error("Font set invalid");
}
#undef ADD_FONT
// Use a SBCS codepage as a placeholder, we won't convert characters anyway
_fontManager.loadFonts(fonts, Common::kWindows1250);
}
@ -384,9 +596,9 @@ void CryOmni3DEngine_Versailles::setupFonts() {
void CryOmni3DEngine_Versailles::setupSprites() {
Common::File file;
Common::String fName = getLanguage() == Common::ZH_TWN ? "allsprtw.bin" : "all_spr.bin";
Common::String fName = (getLanguage() == Common::ZH_TWN ? "allsprtw.bin" : "all_spr.bin");
if (!file.open(fName)) {
if (!file.open(getFilePath(kFileTypeSprite, fName))) {
error("Failed to open all_spr.bin file");
}
_sprites.loadSprites(file);
@ -423,7 +635,7 @@ void CryOmni3DEngine_Versailles::loadCursorsPalette() {
Common::File file;
if (!file.open("bou1_cA.bmp")) {
if (!file.open(getFilePath(kFileTypeSpriteBmp, "bou1_cA.bmp"))) {
error("Failed to open BMP file");
}
@ -661,10 +873,11 @@ void CryOmni3DEngine_Versailles::playTransitionEndLevel(int level) {
// In original game the HNM player just doesn't render the cursor
bool cursorWasVisible = showMouse(false);
if (level == -2) {
if (getLanguage() == Common::DE_DEU && Common::File::exists("RAVENSBG.HLZ")) {
if (level == -2 && getLanguage() == Common::DE_DEU) {
Common::Path ravensbgPath(getFilePath(kFileTypeTransSceneI, "RAVENSBG"));
if (Common::File::exists(ravensbgPath)) {
// Display one more copyright
if (displayHLZ("RAVENSBG", 5000)) {
if (displayHLZ(ravensbgPath, 5000)) {
clearKeys();
fadeOutPalette();
if (shouldAbort()) {
@ -691,10 +904,11 @@ void CryOmni3DEngine_Versailles::playTransitionEndLevel(int level) {
return;
}
if (level == -2) {
if (getLanguage() == Common::JA_JPN && Common::File::exists("jvclogo.hnm")) {
if (level == -2 && getLanguage() == Common::JA_JPN) {
Common::Path jvcPath(getFilePath(kFileTypeTransScene, "jvclogo.hnm"));
if (Common::File::exists(jvcPath)) {
// Display one more copyright
playHNM("jvclogo.hnm", Audio::Mixer::kMusicSoundType);
playHNM(jvcPath, Audio::Mixer::kMusicSoundType);
clearKeys();
if (shouldAbort()) {
return;
@ -771,9 +985,9 @@ void CryOmni3DEngine_Versailles::initNewLevel(int level) {
void CryOmni3DEngine_Versailles::setupLevelWarps(int level) {
Common::File wamFile;
Common::String wamFName = Common::String::format("level%d.wam", level);
if (!wamFile.open(wamFName)) {
error("Can't open WAM file '%s'", wamFName.c_str());
Common::Path wamPath = getFilePath(kFileTypeWAM, Common::String::format("level%d.wam", level));
if (!wamFile.open(wamPath)) {
error("Can't open WAM file '%s'", wamPath.toString().c_str());
}
_wam.loadStream(wamFile);
@ -945,9 +1159,9 @@ void CryOmni3DEngine_Versailles::doGameOver() {
fillSurface(0);
// This test is not really relevant because it's for 2CDs edition but let's follow the code
if (_currentLevel < 4) {
playInGameVideo("1gameove");
playInGameAnimVideo("1gameove");
} else {
playInGameVideo("4gameove");
playInGameAnimVideo("4gameove");
}
fillSurface(0);
_abortCommand = kAbortGameOver;
@ -977,7 +1191,7 @@ void CryOmni3DEngine_Versailles::doPlaceChange() {
delete _currentWarpImage;
}
debug("Loading warp %s", warpFile.c_str());
_currentWarpImage = loadHLZ(warpFile);
_currentWarpImage = loadHLZ(getFilePath(kFileTypeWarpCyclo, warpFile));
if (!_currentWarpImage) {
error("Can't load warp %s", warpFile.c_str());
}
@ -1053,7 +1267,7 @@ void CryOmni3DEngine_Versailles::executeTransition(uint nextPlaceId) {
} else if (animation != "") {
_fadedPalette = false;
// Normally transitions don't overwrite the cursors colors and game doesn't restore palette
playInGameVideo(animation, false);
playInGameVideo(getFilePath(kFileTypeWarpHNM, animation), false);
}
_omni3dMan.setAlpha(transition->dstAlpha);
@ -1095,7 +1309,7 @@ void CryOmni3DEngine_Versailles::executeTransition(uint nextPlaceId) {
} else if (animation != "") {
_fadedPalette = false;
// Normally transitions don't overwrite the cursors colors and game doesn't restore palette
playInGameVideo(animation, false);
playInGameVideo(getFilePath(kFileTypeWarpHNM, animation), false);
}
_nextPlaceId = nextNextPlaceId;
@ -1500,7 +1714,7 @@ void CryOmni3DEngine_Versailles::collectObject(Object *obj, const ZonFixedImage
void CryOmni3DEngine_Versailles::displayObject(const Common::String &imgName,
DisplayObjectHook hook) {
Image::ImageDecoder *imageDecoder = loadHLZ(imgName);
Image::ImageDecoder *imageDecoder = loadHLZ(getFilePath(kFileTypeObject, imgName));
if (!imageDecoder) {
error("Can't display object");
}
@ -1621,7 +1835,7 @@ uint CryOmni3DEngine_Versailles::getFakeTransition(uint actionId) const {
return 0;
}
void CryOmni3DEngine_Versailles::playInGameVideo(const Common::String &filename,
void CryOmni3DEngine_Versailles::playInGameVideo(const Common::Path &filename,
bool restoreCursorPalette) {
if (!_isPlaying) {
return;
@ -1653,7 +1867,7 @@ void CryOmni3DEngine_Versailles::playSubtitledVideo(const Common::String &filena
it->_value.size() == 0) {
// No subtitle, don't try to handle them frame by frame
// Videos are like music because if you mute music in game it will mute videos soundtracks
playHNM(filename, Audio::Mixer::kMusicSoundType);
playHNM(getFilePath(kFileTypeTransScene, filename), Audio::Mixer::kMusicSoundType);
return;
}
@ -1673,7 +1887,7 @@ void CryOmni3DEngine_Versailles::playSubtitledVideo(const Common::String &filena
_fontManager.setCharSpacing(1);
// Videos are like music because if you mute music in game it will mute videos soundtracks
playHNM(filename, Audio::Mixer::kMusicSoundType,
playHNM(getFilePath(kFileTypeTransScene, filename), Audio::Mixer::kMusicSoundType,
static_cast<HNMCallback>(&CryOmni3DEngine_Versailles::drawVideoSubtitles), nullptr);
clearKeys();
@ -1726,13 +1940,13 @@ void CryOmni3DEngine_Versailles::loadBMPs(const char *pattern, Graphics::Surface
Common::File file;
for (uint i = 0; i < count; i++) {
Common::String bmp = Common::String::format(pattern, i);
Common::Path bmp = getFilePath(kFileTypeSpriteBmp, Common::String::format(pattern, i));
if (!file.open(bmp)) {
error("Failed to open BMP file: %s", bmp.c_str());
error("Failed to open BMP file: %s", bmp.toString().c_str());
}
if (!bmpDecoder.loadStream(file)) {
error("Failed to load BMP file: %s", bmp.c_str());
error("Failed to load BMP file: %s", bmp.toString().c_str());
}
bmps[i].copyFrom(*bmpDecoder.getSurface());
bmpDecoder.destroy();

View File

@ -179,6 +179,29 @@ struct LocalizedFilenames {
};
};
enum FileType {
kFileTypeAnimacti,
kFileTypeDocBg,
kFileTypeDialAnim,
kFileTypeDialSound,
kFileTypeFont,
kFileTypeGTO,
kFileTypeFixedImg,
kFileTypeMenu,
kFileTypeMusic,
kFileTypeObject,
kFileTypeSaveGameVisit,
kFileTypeTransScene,
kFileTypeTransSceneI,
kFileTypeSound,
kFileTypeSprite,
kFileTypeSpriteBmp,
kFileTypeText,
kFileTypeWAM,
kFileTypeWarpCyclo,
kFileTypeWarpHNM
};
struct PlaceState {
typedef void (CryOmni3DEngine_Versailles::*InitFunc)();
typedef bool (CryOmni3DEngine_Versailles::*FilterEventFunc)(uint *event);
@ -240,12 +263,7 @@ public:
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
Common::String getSaveStateName(int slot) const override;
Common::String prepareFileName(const Common::String &baseName, const char *extension) const {
const char *const extensions[] = { extension, nullptr };
return prepareFileName(baseName, extensions);
}
Common::String prepareFileName(const Common::String &baseName,
const char *const *extensions) const override;
Common::Path getFilePath(FileType fileType, const Common::String &baseName) const;
void setupPalette(const byte *colors, uint start, uint num) override { setupPalette(colors, start, num, true); }
void makeTranslucent(Graphics::Surface &dst, const Graphics::Surface &src) const override;
@ -346,7 +364,10 @@ private:
bool showSubtitles() const;
void playInGameVideo(const Common::String &filename, bool restoreCursorPalette = true);
void playInGameAnimVideo(const Common::String &filename) {
playInGameVideo(getFilePath(kFileTypeAnimacti, filename));
}
void playInGameVideo(const Common::Path &filename, bool restoreCursorPalette = true);
void playSubtitledVideo(const Common::String &filename);
void loadBMPs(const char *pattern, Graphics::Surface *bmps, uint count);

File diff suppressed because it is too large Load Diff

View File

@ -127,7 +127,7 @@ uint CryOmni3DEngine_Versailles::displayOptions() {
byte volumeForeColor = 243;
Graphics::ManagedSurface optionsSurface;
Image::ImageDecoder *imageDecoder = loadHLZ("option.hlz");
Image::ImageDecoder *imageDecoder = loadHLZ(getFilePath(kFileTypeMenu, "option.hlz"));
const Graphics::Surface *bgFrame = imageDecoder->getSurface();
optionsSurface.create(bgFrame->w, bgFrame->h, bgFrame->format);
@ -300,9 +300,10 @@ uint CryOmni3DEngine_Versailles::displayOptions() {
// Finished dragging
_mixer->stopID(SoundIds::kOrgue);
do {
Common::Path orguePath(getFilePath(kFileTypeSound, "ORGUE.WAV"));
Common::File *audioFile = new Common::File();
if (!audioFile->open("ORGUE.WAV")) {
warning("Failed to open sound file %s", "ORGUE.WAV");
if (!audioFile->open(orguePath)) {
warning("Failed to open sound file %s", orguePath.toString().c_str());
delete audioFile;
break;
}
@ -1001,7 +1002,7 @@ void CryOmni3DEngine_Versailles::displayCredits() {
waitMouseRelease();
Graphics::ManagedSurface creditsSurface;
Image::ImageDecoder *imageDecoder = loadHLZ("credits.hlz");
Image::ImageDecoder *imageDecoder = loadHLZ(getFilePath(kFileTypeMenu, "credits.hlz"));
if (!imageDecoder) {
return;
}
@ -1025,8 +1026,9 @@ void CryOmni3DEngine_Versailles::displayCredits() {
_fontManager.setCharSpacing(1);
_fontManager.setSurface(&creditsSurface);
Common::Path creditsPath(getFilePath(kFileTypeText, _localizedFilenames[LocalizedFilenames::kCredits]));
Common::File creditsFile;
if (!creditsFile.open(_localizedFilenames[LocalizedFilenames::kCredits])) {
if (!creditsFile.open(creditsPath)) {
warning("Failed to open credits file: %s",
_localizedFilenames[LocalizedFilenames::kCredits].c_str());
delete imageDecoder;

View File

@ -67,11 +67,11 @@ void CryOmni3DEngine_Versailles::musicUpdate() {
// New file, stop the old one first
musicStop();
Common::String musicFName(prepareFileName(musicBName, "wav"));
Common::Path musicPath(getFilePath(kFileTypeMusic, musicBName));
Common::File *musicFile = new Common::File();
if (!musicFile->open(musicFName)) {
warning("Failed to open music file %s/%s", musicBName, musicFName.c_str());
if (!musicFile->open(musicPath)) {
warning("Failed to open music file %s/%s", musicBName, musicPath.toString().c_str());
delete musicFile;
return;
}
@ -81,7 +81,7 @@ void CryOmni3DEngine_Versailles::musicUpdate() {
musicFile = nullptr;
if (!musicDecoder) {
warning("Failed to decode music file %s/%s", musicBName, musicFName.c_str());
warning("Failed to decode music file %s/%s", musicBName, musicPath.toString().c_str());
return;
}

View File

@ -49,7 +49,7 @@ Common::String CryOmni3DEngine_Versailles::getSaveStateName(int slot) const {
}
bool CryOmni3DEngine_Versailles::canVisit() const {
return Common::File::exists("game0001.sav");
return Common::File::exists(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"));
}
void CryOmni3DEngine_Versailles::getSavesList(bool visit, Common::StringArray &saveNames,
@ -73,11 +73,9 @@ void CryOmni3DEngine_Versailles::getSavesList(bool visit, Common::StringArray &s
if (visit) {
// Add bootstrap visit
if (Common::File::exists("game0001.sav")) {
Common::File visitFile;
if (!visitFile.open("game0001.sav")) {
error("Can't load visit file");
}
Common::Path visitPath(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"));
Common::File visitFile;
if (visitFile.open(visitPath)) {
visitFile.read(saveName, kSaveDescriptionLen);
saveNames.push_back(saveName);
} else {
@ -233,7 +231,7 @@ bool CryOmni3DEngine_Versailles::loadGame(bool visit, uint saveNum) {
if (visit && saveNum == 1) {
// Load bootstrap visit
Common::File *visitFile = new Common::File();
if (!visitFile->open("game0001.sav")) {
if (!visitFile->open(getFilePath(kFileTypeSaveGameVisit, "game0001.sav"))) {
delete visitFile;
error("Can't load visit file");
}