diff options
author | Gregory Montoir | 2006-11-04 12:00:31 +0000 |
---|---|---|
committer | Gregory Montoir | 2006-11-04 12:00:31 +0000 |
commit | 5a902f8f7a40f2f2182a0b2149959f8889c468ef (patch) | |
tree | 4c388ea299b79dab8b781724f506d50ff6a35246 | |
parent | b8ed3bc87f5ddf397959d9ccc266a825f69cc059 (diff) | |
download | scummvm-rg350-5a902f8f7a40f2f2182a0b2149959f8889c468ef.tar.gz scummvm-rg350-5a902f8f7a40f2f2182a0b2149959f8889c468ef.tar.bz2 scummvm-rg350-5a902f8f7a40f2f2182a0b2149959f8889c468ef.zip |
rewrote FOTAQ game version detection code in a - if I didn't break anything - better way (no more duplicated code, more accurate game description in the launcher...)
svn-id: r24598
-rw-r--r-- | engines/queen/debug.cpp | 4 | ||||
-rw-r--r-- | engines/queen/journal.cpp | 2 | ||||
-rw-r--r-- | engines/queen/logic.cpp | 2 | ||||
-rw-r--r-- | engines/queen/queen.cpp | 77 | ||||
-rw-r--r-- | engines/queen/resource.cpp | 204 | ||||
-rw-r--r-- | engines/queen/resource.h | 94 |
6 files changed, 191 insertions, 192 deletions
diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp index 8f49753d17..508e6f077d 100644 --- a/engines/queen/debug.cpp +++ b/engines/queen/debug.cpp @@ -126,8 +126,8 @@ bool Debugger::Cmd_GameState(int argc, const char **argv) { } bool Debugger::Cmd_Info(int argc, const char **argv) { - DebugPrintf("Version: %s\n", _vm->resource()->JASVersion()); - DebugPrintf("Audio compression: %d\n", _vm->resource()->compression()); + DebugPrintf("Version: %s\n", _vm->resource()->getJASVersion()); + DebugPrintf("Audio compression: %d\n", _vm->resource()->getCompression()); return true; } diff --git a/engines/queen/journal.cpp b/engines/queen/journal.cpp index d763ae486f..b36b4bad31 100644 --- a/engines/queen/journal.cpp +++ b/engines/queen/journal.cpp @@ -457,7 +457,7 @@ void Journal::drawConfigPanel() { void Journal::drawInfoPanel() { showBob(BOB_INFO_BOX, 72, 221, FRAME_INFO_BOX); - const char *ver = _vm->resource()->JASVersion(); + const char *ver = _vm->resource()->getJASVersion(); switch (ver[0]) { case 'P': _vm->display()->setTextCentered(132, "PC Hard Drive", false); diff --git a/engines/queen/logic.cpp b/engines/queen/logic.cpp index b1675f38b3..91960fd8df 100644 --- a/engines/queen/logic.cpp +++ b/engines/queen/logic.cpp @@ -190,7 +190,7 @@ void Logic::initialise() { _currentRoom = _objectData[_entryObj].room; _entryObj = 0; - if (memcmp(ptr, _vm->resource()->JASVersion(), 5) != 0) { + if (memcmp(ptr, _vm->resource()->getJASVersion(), 5) != 0) { warning("Unexpected queen.jas file format"); } diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp index df7a3ef472..5bada63983 100644 --- a/engines/queen/queen.cpp +++ b/engines/queen/queen.cpp @@ -48,39 +48,21 @@ #include "sound/mididrv.h" -/* Flight of the Amazon Queen */ -static const PlainGameDescriptor queen_setting[] = { - { "queen", "Flight of the Amazon Queen" }, - { "queen", "Flight of the Amazon Queen (Demo)" }, - { "queen", "Flight of the Amazon Queen (Interview)" }, - { 0, 0 } +static const PlainGameDescriptor queenGameDescriptor = { + "queen", "Flight of the Amazon Queen" }; GameList Engine_QUEEN_gameIDList() { GameList games; - games.push_back(queen_setting[0]); + games.push_back(queenGameDescriptor); return games; } GameDescriptor Engine_QUEEN_findGameID(const char *gameid) { - if (0 == scumm_stricmp(gameid, queen_setting[0].gameid)) - return queen_setting[0]; - return GameDescriptor(); -} - -// FIXME/TODO: it would be nice to re-use the existing code of the -// Resource class to detect the FOTAQ version. -static GameDescriptor determineTarget(uint32 size) { - switch (size) { - case 3724538: //regular demo - case 3732177: - return queen_setting[1]; - case 1915913: //interview demo - return queen_setting[2]; - default: //non-demo - return queen_setting[0]; + if (0 == scumm_stricmp(gameid, queenGameDescriptor.gameid)) { + return queenGameDescriptor; } - return queen_setting[0]; + return GameDescriptor(); } DetectedGameList Engine_QUEEN_detectGames(const FSList &fslist) { @@ -88,32 +70,27 @@ DetectedGameList Engine_QUEEN_detectGames(const FSList &fslist) { // Iterate over all files in the given directory for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { - if (!file->isDirectory()) { - const char *fileName = file->name().c_str(); - - if (0 == scumm_stricmp("queen.1", fileName) || 0 == scumm_stricmp("queen.1c", fileName)) { - Common::File dataFile; - dataFile.open(*file); - assert(dataFile.isOpen()); - - if (0 == scumm_stricmp("queen.1", fileName)) { //an unmodified file - detectedGames.push_back(determineTarget(dataFile.size())); - } else if (0 == scumm_stricmp("queen.1c", fileName)) { //oh joy, it's a rebuilt file - char header[9]; - dataFile.read(header, 9); - if (0 == scumm_strnicmp("QTBL", header, 4)) { //check validity - uint8 version = 0; //default to full/normal version - - if (0 == scumm_strnicmp("PE100", header + 4, 5)) //One of the 2 regular demos - version = 1; - if (0 == scumm_strnicmp("PEint", header + 4, 5)) //Interview demo - version = 2; - - detectedGames.push_back(queen_setting[version]); - } + if (file->isDirectory()) { + continue; + } + if (file->name().equalsIgnoreCase("queen.1") || file->name().equalsIgnoreCase("queen.1c")) { + Common::File dataFile; + if (!dataFile.open(*file)) { + continue; + } + Queen::DetectedGameVersion version; + if (Queen::Resource::detectVersion(&version, &dataFile)) { + DetectedGame dg(queenGameDescriptor.gameid, queenGameDescriptor.description, version.language, Common::kPlatformPC); + if (version.features & Queen::GF_DEMO) { + dg.updateDesc("Demo"); + } else if (version.features & Queen::GF_INTERVIEW) { + dg.updateDesc("Interview"); + } else if (version.features & Queen::GF_FLOPPY) { + dg.updateDesc("Floppy"); + } else if (version.features & Queen::GF_TALKIE) { + dg.updateDesc("Talkie"); } - - dataFile.close(); + detectedGames.push_back(dg); break; } } @@ -421,7 +398,7 @@ int QueenEngine::init() { _music = new Music(driver, this); _music->hasNativeMT32(native_mt32); - _sound = Sound::giveSound(_mixer, this, _resource->compression()); + _sound = Sound::giveSound(_mixer, this, _resource->getCompression()); _walk = new Walk(this); //_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0; diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp index eee279fae5..e51f641287 100644 --- a/engines/queen/resource.cpp +++ b/engines/queen/resource.cpp @@ -21,6 +21,7 @@ */ #include "common/stdafx.h" +#include "common/endian.h" #include "common/config-manager.h" #include "queen/resource.h" @@ -32,7 +33,7 @@ static ResourceEntry *_resourceTablePEM10; const char *Resource::_tableFilename = "queen.tbl"; -const GameVersion Resource::_gameVersions[] = { +const RetailGameVersion Resource::_gameVersions[] = { { "PEM10", 0x00000008, 22677657 }, { "CEM10", 0x0000584E, 190787021 }, { "PFM10", 0x0002CD93, 22157304 }, @@ -56,16 +57,29 @@ static int compareResourceEntry(const void *a, const void *b) { Resource::Resource() : _resourceEntries(0), _resourceTable(NULL) { - _resourceFile = new Common::File(); - if (!findCompressedVersion() && !findNormalVersion()) - error("Could not open resource file '%s'", "queen.1"); + memset(&_version, 0, sizeof(_version)); + + if (!_resourceFile.open("queen.1c")) { + if (!_resourceFile.open("queen.1")) { + error("Could not open resource file 'queen.1[c]'"); + } + } + if (!detectVersion(&_version, &_resourceFile)) { + error("Unable to detect game version"); + } + + if (_version.features & GF_REBUILT) { + readTableEntries(&_resourceFile); + } else { + readTableFile(_version.tableOffset); + } + checkJASVersion(); - debug(5, "Detected game version: %s, which has %d resource entries", _versionString, _resourceEntries); + debug(5, "Detected game version: %s, which has %d resource entries", _version.str, _resourceEntries); } Resource::~Resource() { - _resourceFile->close(); - delete _resourceFile; + _resourceFile.close(); if (_resourceTable != _resourceTablePEM10) delete[] _resourceTable; @@ -74,22 +88,17 @@ Resource::~Resource() { ResourceEntry *Resource::resourceEntry(const char *filename) const { assert(filename[0] && strlen(filename) < 14); - char entryName[14]; - char *ptr = entryName; - - strcpy(entryName, filename); - do - *ptr = toupper(*ptr); - while (*ptr++); + Common::String entryName(filename); + entryName.toUppercase(); ResourceEntry *re = NULL; #ifndef PALMOS_MODE - re = (ResourceEntry *)bsearch(entryName, _resourceTable, _resourceEntries, sizeof(ResourceEntry), compareResourceEntry); + re = (ResourceEntry *)bsearch(entryName.c_str(), _resourceTable, _resourceEntries, sizeof(ResourceEntry), compareResourceEntry); #else // PALMOS FIXME (?) : still doesn't work for me (????) use this instead uint32 cur = 0; do { - if (!strcmp(entryName, _resourceTable[cur].filename)) { + if (!strcmp(entryName.c_str(), _resourceTable[cur].filename)) { re = &_resourceTable[cur]; break; } @@ -113,44 +122,78 @@ uint8 *Resource::loadFile(const char *filename, uint32 skipBytes, uint32 *size, dstBuf = new byte[sz]; } - _resourceFile->seek(re->offset + skipBytes); - _resourceFile->read(dstBuf, sz); + _resourceFile.seek(re->offset + skipBytes); + _resourceFile.read(dstBuf, sz); return dstBuf; } -bool Resource::findNormalVersion() { - _resourceFile->open("queen.1"); - if (!_resourceFile->isOpen()) { - return false; - } - - _compression = COMPRESSION_NONE; +bool Resource::detectVersion(DetectedGameVersion *ver, Common::File *f) { + memset(ver, 0, sizeof(DetectedGameVersion)); - // detect game version based on resource file size ; we try to - // verify that it is indeed the version we think it is later on - const GameVersion *gameVersion = detectGameVersion(_resourceFile->size()); - if (gameVersion == NULL) - error("Unknown/unsupported FOTAQ version"); + char versionStr[6]; + if (f->readUint32BE() == MKID_BE('QTBL')) { + f->read(versionStr, 6); + f->skip(2); + ver->compression = f->readByte(); + ver->features = GF_REBUILT; + ver->tableOffset = 0; + } else { + const RetailGameVersion *gameVersion = detectGameVersionFromSize(f->size()); + if (gameVersion == NULL) { + warning("Unknown/unsupported FOTAQ version"); + return false; + } + strcpy(versionStr, gameVersion->str); + ver->compression = COMPRESSION_NONE; + ver->features = 0; + ver->tableOffset = gameVersion->tableOffset; + } - strcpy(_versionString, gameVersion->versionString); - if (!readTableFile(gameVersion)) { - // check if it is the english floppy version, for which we have a hardcoded version of the table - if (!strcmp(gameVersion->versionString, _gameVersions[VER_ENG_FLOPPY].versionString)) { - _resourceEntries = 1076; - _resourceTable = _resourceTablePEM10; + switch (versionStr[1]) { + case 'E': + if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) { + ver->language = Common::RU_RUS; } else { - error("Could not find tablefile '%s'", _tableFilename); + ver->language = Common::EN_ANY; } + break; + case 'G': + ver->language = Common::DE_DEU; + break; + case 'F': + ver->language = Common::FR_FRA; + break; + case 'I': + ver->language = Common::IT_ITA; + break; + case 'S': + ver->language = Common::ES_ESP; + break; + case 'H': + ver->language = Common::HB_ISR; + break; + default: + warning("Unknown language id '%c', defaulting to English", versionStr[1]); + ver->language = Common::EN_ANY; + break; + } + + switch (versionStr[0]) { + case 'P': + ver->features |= GF_FLOPPY; + break; + case 'C': + ver->features |= GF_TALKIE; + break; } - return true; -} -bool Resource::findCompressedVersion() { - _resourceFile->open("queen.1c"); - if (!_resourceFile->isOpen()) { - return false; + if (strcmp(versionStr, "PE100") == 0) { + ver->features |= GF_DEMO; + } else if (strcmp(versionStr, "PEint") == 0) { + ver->features |= GF_INTERVIEW; } - readTableCompResource(); + + strcpy(ver->str, versionStr); return true; } @@ -164,58 +207,32 @@ void Resource::checkJASVersion() { offset += JAS_VERSION_OFFSET_INTV; else offset += JAS_VERSION_OFFSET_PC; - _resourceFile->seek(offset); + _resourceFile.seek(offset); char versionStr[6]; - _resourceFile->read(versionStr, 6); - if (strcmp(_versionString, versionStr)) - error("Verifying game version failed! (expected: '%s', found: '%s')", _versionString, versionStr); -} - -Common::Language Resource::getLanguage() const { - switch (_versionString[1]) { - case 'E': - if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) - return Common::RU_RUS; - return Common::EN_ANY; - case 'G': - return Common::DE_DEU; - case 'F': - return Common::FR_FRA; - case 'I': - return Common::IT_ITA; - case 'S': - return Common::ES_ESP; - case 'H': - return Common::HB_ISR; - default: - warning("Unknown language id '%c', defaulting to English", _versionString[1]); - return Common::EN_ANY; - } + _resourceFile.read(versionStr, 6); + if (strcmp(_version.str, versionStr)) + error("Verifying game version failed! (expected: '%s', found: '%s')", _version.str, versionStr); } -bool Resource::readTableFile(const GameVersion *gameVersion) { +void Resource::readTableFile(uint32 offset) { Common::File tableFile; tableFile.open(_tableFilename); - if (tableFile.isOpen() && tableFile.readUint32BE() == 'QTBL') { - if (tableFile.readUint32BE() != CURRENT_TBL_VERSION) + if (tableFile.isOpen() && tableFile.readUint32BE() == MKID_BE('QTBL')) { + if (tableFile.readUint32BE() != CURRENT_TBL_VERSION) { warning("Incorrect version of queen.tbl, please update it"); - tableFile.seek(gameVersion->tableOffset); + } + tableFile.seek(offset); readTableEntries(&tableFile); - return true; + } else { + // check if it is the english floppy version, for which we have a hardcoded version of the table + if (strcmp(_version.str, _gameVersions[VER_ENG_FLOPPY].str) == 0) { + _resourceEntries = 1076; + _resourceTable = _resourceTablePEM10; + } else { + error("Could not find tablefile '%s'", _tableFilename); + } } - return false; -} - -void Resource::readTableCompResource() { - if (_resourceFile->readUint32BE() != 'QTBL') - error("Invalid table header"); - - _resourceFile->read(_versionString, 6); - _resourceFile->skip(2); // obsolete - _compression = _resourceFile->readByte(); - - readTableEntries(_resourceFile); } void Resource::readTableEntries(Common::File *file) { @@ -231,11 +248,10 @@ void Resource::readTableEntries(Common::File *file) { } } -const GameVersion *Resource::detectGameVersion(uint32 size) const { - const GameVersion *pgv = _gameVersions; - for (int i = 0; i < VER_COUNT; ++i, ++pgv) { - if (pgv->dataFileSize == size) { - return pgv; +const RetailGameVersion *Resource::detectGameVersionFromSize(uint32 size) { + for (int i = 0; i < VER_COUNT; ++i) { + if (_gameVersions[i].dataFileSize == size) { + return &_gameVersions[i]; } } return NULL; @@ -249,8 +265,8 @@ Common::File *Resource::giveCompressedSound(const char *filename, uint32 *size) if (size != NULL) { *size = re->size; } - _resourceFile->seek(re->offset); - f = _resourceFile; + _resourceFile.seek(re->offset); + f = &_resourceFile; } return f; } diff --git a/engines/queen/resource.h b/engines/queen/resource.h index cb2851d27e..d01dc83859 100644 --- a/engines/queen/resource.h +++ b/engines/queen/resource.h @@ -29,31 +29,33 @@ namespace Queen { -struct ResourceEntry { - char filename[13]; - uint8 bundle; - uint32 offset; - uint32 size; +enum GameFeatures { + GF_DEMO = 1 << 0, // demo + GF_TALKIE = 1 << 1, // equivalent to cdrom version check + GF_FLOPPY = 1 << 2, // floppy, ie. non-talkie version + GF_INTERVIEW = 1 << 3, // interview demo + GF_REBUILT = 1 << 4 // version rebuilt with the 'compression_queen' tool }; -struct GameVersion { - char versionString[6]; +struct RetailGameVersion { + char str[6]; uint32 tableOffset; uint32 dataFileSize; }; -class LineReader { -public: - - LineReader(char *buffer, uint32 bufsize); - ~LineReader(); - char *nextLine(); - -private: +struct DetectedGameVersion { + Common::Language language; + uint8 features; + uint8 compression; + char str[6]; + uint32 tableOffset; +}; - char *_buffer; - uint32 _bufSize; - int _current; +struct ResourceEntry { + char filename[13]; + uint8 bundle; + uint32 offset; + uint32 size; }; class Resource { @@ -71,19 +73,22 @@ public: //! returns a reference to a sound file Common::File *giveCompressedSound(const char *filename, uint32 *size); - bool isDemo() const { return !strcmp(_versionString, "PE100"); } - bool isInterview() const { return !strcmp(_versionString, "PEint"); } - bool isFloppy() const { return _versionString[0] == 'P'; } - bool isCD() const { return _versionString[0] == 'C'; } + bool isDemo() const { return _version.features & GF_DEMO; } + bool isInterview() const { return _version.features & GF_INTERVIEW; } + bool isFloppy() const { return _version.features & GF_FLOPPY; } + bool isCD() const { return _version.features & GF_TALKIE; } //! returns compression type for audio files - uint8 compression() const { return _compression; } + uint8 getCompression() const { return _version.compression; } //! returns JAS version string (contains language, platform and version information) - const char *JASVersion() const { return _versionString; } + const char *getJASVersion() const { return _version.str; } + + //! returns the language of the game + Common::Language getLanguage() const { return _version.language; } - //! returns language of the game - Common::Language getLanguage() const; + //! detect game version + static bool detectVersion(DetectedGameVersion *ver, Common::File *f); enum Version { VER_ENG_FLOPPY = 0, @@ -115,25 +120,15 @@ public: protected: - Common::File *_resourceFile; + Common::File _resourceFile; - //! compression type for audio files - uint8 _compression; - - //! JAS version string of the game - char _versionString[6]; + DetectedGameVersion _version; //! number of entries in resource table uint32 _resourceEntries; ResourceEntry *_resourceTable; - //! look for a normal queen version (ie. queen.1) - bool findNormalVersion(); - - //! look for a compressed/rebuilt queen version (ie. queen.1c) - bool findCompressedVersion(); - //! verify the version of the selected game void checkJASVersion(); @@ -141,22 +136,19 @@ protected: ResourceEntry *resourceEntry(const char *filename) const; //! extarct the resource table for the specified game version - bool readTableFile(const GameVersion *gameVersion); - - //! reads the resource table from a rebuilt datafile (ie. queen.1c) - void readTableCompResource(); + void readTableFile(uint32 offset); //! read the resource table from the specified file void readTableEntries(Common::File *file); //! detect game version based on queen.1 datafile size - const GameVersion *detectGameVersion(uint32 size) const; + static const RetailGameVersion *detectGameVersionFromSize(uint32 size); //! resource table filename (queen.tbl) static const char *_tableFilename; //! known FOTAQ versions - static const GameVersion _gameVersions[]; + static const RetailGameVersion _gameVersions[]; #ifndef PALMOS_68K //! resource table for english floppy version @@ -164,6 +156,20 @@ protected: #endif }; +class LineReader { +public: + + LineReader(char *buffer, uint32 bufsize); + ~LineReader(); + char *nextLine(); + +private: + + char *_buffer; + uint32 _bufSize; + int _current; +}; + } // End of namespace Queen #endif |