diff options
-rw-r--r-- | dists/engine-data/kyra.dat | bin | 331978 -> 344846 bytes | |||
-rw-r--r-- | engines/kyra/resource.h | 15 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 368 | ||||
-rw-r--r-- | tools/create_kyradat/create_kyradat.cpp | 91 | ||||
-rw-r--r-- | tools/create_kyradat/create_kyradat.h | 4 |
5 files changed, 127 insertions, 351 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat Binary files differindex 0574553fd4..f96675f74f 100644 --- a/dists/engine-data/kyra.dat +++ b/dists/engine-data/kyra.dat diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 294cb932f7..81987306e0 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -103,7 +103,7 @@ enum KyraResources { kLoadAll = -1, // This list has to match orderwise (and thus value wise) the static data list of "tools/create_kyradat/create_kyradat.h"! - k1ForestSeq, + k1ForestSeq = 1, k1KallakWritingSeq, k1KyrandiaLogoSeq, k1KallakMalcolmSeq, @@ -348,7 +348,7 @@ class StaticResource { public: static const Common::String staticDataFilename() { return "KYRA.DAT"; } - StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _dataTable(0) {} + StaticResource(KyraEngine_v1 *vm) : _vm(vm), _resList(), _fileLoader(0), _dataTable() {} ~StaticResource() { deinit(); } bool loadStaticResourceFile(); @@ -469,7 +469,16 @@ private: Common::List<ResData> _resList; const FileType *_fileLoader; - const int *_dataTable; + + struct DataDescriptor { + DataDescriptor() : filename(0), type(0) {} + DataDescriptor(uint32 f, uint8 t) : filename(f), type(t) {} + + uint32 filename; + uint8 type; + }; + typedef Common::HashMap<uint16, DataDescriptor> DataMap; + DataMap _dataTable; }; } // End of namespace Kyra diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 918df6fc7d..0b3979f570 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -45,7 +45,7 @@ namespace Kyra { -#define RESFILE_VERSION 68 +#define RESFILE_VERSION 69 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -91,12 +91,12 @@ byte getGameID(const GameFlags &flags) { } const IndexTable iLanguageTable[] = { - { Common::EN_ANY, 0 }, - { Common::FR_FRA, 1 }, - { Common::DE_DEU, 2 }, - { Common::ES_ESP, 3 }, - { Common::IT_ITA, 4 }, - { Common::JA_JPN, 5 }, + { Common::EN_ANY, 1 }, + { Common::FR_FRA, 2 }, + { Common::DE_DEU, 3 }, + { Common::ES_ESP, 4 }, + { Common::IT_ITA, 5 }, + { Common::JA_JPN, 6 }, { -1, -1 } }; @@ -192,9 +192,13 @@ bool StaticResource::tryKyraDatLoad() { return false; } - const uint16 gameDef = ((getGameID(_vm->gameFlags()) & 0xF) << 12) | - ((getPlatformID(_vm->gameFlags()) & 0xF) << 8) | - ((getSpecialID(_vm->gameFlags()) & 0xF) << 4); + const GameFlags &flags = _vm->gameFlags(); + const byte game = getGameID(flags) & 0xF; + const byte platform = getPlatformID(flags) & 0xF; + const byte special = getSpecialID(flags) & 0xF; + const byte lang = getLanguageID(flags) & 0xF; + + const uint16 gameDef = (game << 12) | (platform << 8) | (special << 4) | (lang << 0); bool found = false; for (uint32 i = 0; i < includedGames; ++i) { @@ -210,6 +214,26 @@ bool StaticResource::tryKyraDatLoad() { if (!found) return false; + // load the ID map for our game + const Common::String filenamePattern = Common::String::printf("0%01X%01X%01X%03X%01X", game, platform, special, 0, lang); + Common::SeekableReadStream *idMap = _vm->resource()->createReadStream(filenamePattern); + if (!idMap) + return false; + + uint16 numIDs = idMap->readUint16BE(); + while (numIDs--) { + uint16 id = idMap->readUint16BE(); + uint8 type = idMap->readByte(); + uint32 filename = idMap->readUint32BE(); + + _dataTable[id] = DataDescriptor(filename, type); + } + + const bool fileError = idMap->err(); + delete idMap; + if (fileError) + return false; + // load all tables for now if (!prefetchId(-1)) return false; @@ -245,288 +269,6 @@ bool StaticResource::init() { #undef proc _fileLoader = fileTypeTable; - // Kyrandia 1 Filenames - static const int kyra1StaticRes[] = { - // INTRO / OUTRO sequences - k1ForestSeq, - k1KallakWritingSeq, - k1KyrandiaLogoSeq, - k1KallakMalcolmSeq, - k1MalcolmTreeSeq, - k1WestwoodLogoSeq, - k1Demo1Seq, - k1Demo2Seq, - k1Demo3Seq, - k1Demo4Seq, - k1OutroReunionSeq, - - // INTRO / OUTRO strings - k1IntroCPSStrings, - k1IntroCOLStrings, - k1IntroWSAStrings, - k1IntroStrings, - k1OutroHomeString, - - // INGAME strings - k1ItemNames, - k1TakenStrings, - k1PlacedStrings, - k1DroppedStrings, - k1NoDropStrings, - k1PutDownString, - k1WaitAmuletString, - k1BlackJewelString, - k1PoisonGoneString, - k1HealingTipString, - k1ThePoisonStrings, - k1FluteStrings, - k1WispJewelStrings, - k1MagicJewelStrings, - k1FlaskFullString, - k1FullFlaskString, - k1VeryCleverString, - k1NewGameString, - - // GUI strings table - k1GUIStrings, - k1ConfigStrings, - - // ROOM table/filenames - k1RoomList, - k1RoomFilenames, - - // SHAPE tables - k1DefaultShapes, - k1Healing1Shapes, - k1Healing2Shapes, - k1PoisonDeathShapes, - k1FluteShapes, - k1Winter1Shapes, - k1Winter2Shapes, - k1Winter3Shapes, - k1DrinkShapes, - k1WispShapes, - k1MagicAnimShapes, - k1BranStoneShapes, - - // IMAGE filename table - k1CharacterImageFilenames, - - // AMULET anim - k1AmuleteAnimSeq, - - // PALETTE table - k1SpecialPalette1, - k1SpecialPalette2, - k1SpecialPalette3, - k1SpecialPalette4, - k1SpecialPalette5, - k1SpecialPalette6, - k1SpecialPalette7, - k1SpecialPalette8, - k1SpecialPalette9, - k1SpecialPalette10, - k1SpecialPalette11, - k1SpecialPalette12, - k1SpecialPalette13, - k1SpecialPalette14, - k1SpecialPalette15, - k1SpecialPalette16, - k1SpecialPalette17, - k1SpecialPalette18, - k1SpecialPalette19, - k1SpecialPalette20, - k1SpecialPalette21, - k1SpecialPalette22, - k1SpecialPalette23, - k1SpecialPalette24, - k1SpecialPalette25, - k1SpecialPalette26, - k1SpecialPalette27, - k1SpecialPalette28, - k1SpecialPalette29, - k1SpecialPalette30, - k1SpecialPalette31, - k1SpecialPalette32, - k1SpecialPalette33, - - // AUDIO files - k1AudioTracks, - k1AudioTracksIntro, - - // FM-TOWNS specific - k1TownsSFXwdTable, - k1TownsSFXbtTable, - k1TownsCDATable, - - // PC98 specific - k1PC98StoryStrings, - k1PC98IntroSfx, - - // CREDITS (used in FM-TOWNS and AMIGA) - k1CreditsStrings, - - // AMIGA specific - k1AmigaIntroSFXTable, - k1AmigaGameSFXTable, - - -1 - }; - - static const int kyra2StaticRes[] = { - // Sequence Player - k2SeqplayPakFiles, - k2SeqplayCredits, - k2SeqplayCreditsSpecial, - k2SeqplayStrings, - k2SeqplaySfxFiles, - k2SeqplayTlkFiles, - k2SeqplaySeqData, - k2SeqplayIntroTracks, - k2SeqplayFinaleTracks, - k2SeqplayIntroCDA, - k2SeqplayFinaleCDA, - k2SeqplayShapeAnimData, - - // Ingame - k2IngamePakFiles, - k2IngameSfxFiles, - k2IngameSfxIndex, - k2IngameTracks, - k2IngameCDA, - k2IngameTalkObjIndex, - k2IngameTimJpStrings, - k2IngameShapeAnimData, - k2IngameTlkDemoStrings, - - -1 - }; - - static const int kyra3StaticRes[] = { - k3MainMenuStrings, - k3MusicFiles, - k3ScoreTable, - k3SfxFiles, - k3SfxMap, - k3ItemAnimData, - k3ItemMagicTable, - k3ItemStringMap, - - -1 - }; - -#ifdef ENABLE_LOL - static const int kLolStaticRes[] = { - // Demo Sequence Player - k2SeqplayPakFiles, - k2SeqplayStrings, - k2SeqplaySfxFiles, - k2SeqplaySeqData, - k2SeqplayIntroTracks, - - // Ingame - kLolIngamePakFiles, - - kLolCharacterDefs, - kLolIngameSfxFiles, - kLolIngameSfxIndex, - kLolMusicTrackMap, - kLolIngameGMSfxIndex, - kLolIngameMT32SfxIndex, - kLolIngamePcSpkSfxIndex, - kLolSpellProperties, - kLolGameShapeMap, - kLolSceneItemOffs, - kLolCharInvIndex, - kLolCharInvDefs, - kLolCharDefsMan, - kLolCharDefsWoman, - kLolCharDefsKieran, - kLolCharDefsAkshel, - kLolExpRequirements, - kLolMonsterModifiers, - kLolMonsterShiftOffsets, - kLolMonsterDirFlags, - kLolMonsterScaleY, - kLolMonsterScaleX, - kLolMonsterScaleWH, - kLolFlyingObjectShp, - kLolInventoryDesc, - - kLolLevelShpList, - kLolLevelDatList, - kLolCompassDefs, - kLolItemPrices, - kLolStashSetup, - - kLolDscUnk1, - kLolDscShapeIndex, - kLolDscOvlMap, - kLolDscScaleWidthData, - kLolDscScaleHeightData, - kLolDscX, - kLolDscY, - kLolDscTileIndex, - kLolDscUnk2, - kLolDscDoorShapeIndex, - kLolDscDimData1, - kLolDscDimData2, - kLolDscBlockMap, - kLolDscDimMap, - kLolDscDoorScale, - kLolDscDoor4, - kLolDscOvlIndex, - kLolDscBlockIndex, - kLolDscDoor1, - kLolDscDoorX, - kLolDscDoorY, - - kLolScrollXTop, - kLolScrollYTop, - kLolScrollXBottom, - kLolScrollYBottom, - - kLolButtonDefs, - kLolButtonList1, - kLolButtonList2, - kLolButtonList3, - kLolButtonList4, - kLolButtonList5, - kLolButtonList6, - kLolButtonList7, - kLolButtonList8, - - kLolLegendData, - kLolMapCursorOvl, - kLolMapStringId, - - kLolSpellbookAnim, - kLolSpellbookCoords, - kLolHealShapeFrames, - kLolLightningDefs, - kLolFireballCoords, - - kLolCredits, - - kLolHistory, - - -1 - }; -#endif // ENABLE_LOL - - if (_vm->game() == GI_KYRA1) - _dataTable = kyra1StaticRes; - else if (_vm->game() == GI_KYRA2) - _dataTable = kyra2StaticRes; - else if (_vm->game() == GI_KYRA3) - _dataTable = kyra3StaticRes; -#ifdef ENABLE_LOL - else if (_vm->game() == GI_LOL) - _dataTable = kLolStaticRes; -#endif // ENABLE_LOL - else - error("StaticResource: Unknown game ID"); - return loadStaticResourceFile(); } @@ -598,8 +340,10 @@ const ButtonDef *StaticResource::loadButtonDefs(int id, int &entries) { bool StaticResource::prefetchId(int id) { if (id == -1) { - for (int i = 0; _dataTable[i] != -1; ++i) - prefetchId(_dataTable[i]); + for (DataMap::const_iterator i = _dataTable.begin(); i != _dataTable.end(); ++i) { + if (!prefetchId(i->_key)) + return false; + } return true; } @@ -609,44 +353,18 @@ bool StaticResource::prefetchId(int id) { if (checkResList(id, type, ptr, size)) return true; - const GameFlags &flags = _vm->gameFlags(); - byte game = getGameID(flags); - byte platform = getPlatformID(flags); - byte special = getSpecialID(flags); - byte lang = getLanguageID(flags); - - Common::ArchiveMemberList fileCandidates; - - const Common::String filenamePattern = Common::String::printf("%01X%01X%01X??%03X", game, platform, special, id); - const Common::String langFilenamePattern = filenamePattern + Common::String::printf("%01X", lang); - - // We assume the order of "fileCandidates" never changes across these calls. This means: - // The filenames matching "filenamePattern" will be added after the ones matching - // "langFilenamePattern". - _vm->resource()->listFiles(langFilenamePattern.c_str(), fileCandidates); - _vm->resource()->listFiles(filenamePattern.c_str(), fileCandidates); - - if (fileCandidates.empty()) + DataMap::const_iterator dDesc = _dataTable.find(id); + if (dDesc == _dataTable.end()) return false; - // First entry in the list should be the one we want - Common::ArchiveMemberPtr file = *fileCandidates.begin(); - fileCandidates.clear(); - - unsigned int rType = (unsigned int)-1; - if (sscanf(file->getDisplayName().c_str(), "%*01X%*01X%*01X%02X%*03X", &rType) != 1) { - warning("Failed to parse filename from kyra.dat: \"%s\"", file->getDisplayName().c_str()); - return false; - } - - const FileType *filetype = getFiletype(rType); + const FileType *filetype = getFiletype(dDesc->_value.type); if (!filetype) return false; ResData data; data.id = id; - data.type = rType; - Common::SeekableReadStream *fileStream = file->createReadStream(); + data.type = dDesc->_value.type; + Common::SeekableReadStream *fileStream = _vm->resource()->createReadStream(Common::String::printf("%08X", dDesc->_value.filename)); if (!fileStream) return false; diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp index f6b768ec43..ae498992c2 100644 --- a/tools/create_kyradat/create_kyradat.cpp +++ b/tools/create_kyradat/create_kyradat.cpp @@ -42,10 +42,13 @@ #include <map> enum { - kKyraDatVersion = 68 + kKyraDatVersion = 69 }; const ExtractFilename extractFilenames[] = { + // GENERIC ID MAP + { kIdMap, -1, true }, + // INTRO / OUTRO sequences { k1ForestSeq, kTypeRawData, false }, { k1KallakWritingSeq, kTypeRawData, false }, @@ -327,12 +330,13 @@ byte getGameID(int game) { } const TypeTable languageTable[] = { - { EN_ANY, 0 }, - { FR_FRA, 1 }, - { DE_DEU, 2 }, - { ES_ESP, 3 }, - { IT_ITA, 4 }, - { JA_JPN, 5 }, + { UNK_LANG, 0 }, + { EN_ANY, 1 }, + { FR_FRA, 2 }, + { DE_DEU, 3 }, + { ES_ESP, 4 }, + { IT_ITA, 5 }, + { JA_JPN, 6 }, { -1, -1 } }; @@ -367,17 +371,23 @@ byte getSpecialID(int special) { // filename processing -bool getFilename(char *dstFilename, const ExtractInformation *info, const int id) { - const ExtractFilename *i = getFilenameDesc(id); +uint32 getFilename(const ExtractInformation *info, const int id) { + const ExtractFilename *fDesc = getFilenameDesc(id); - if (!i) - return false; + if (!fDesc) + return 0; + + // GAME, PLATFORM, SPECIAL, ID, LANG + return ((getGameID(info->game) & 0xF) << 24) | + ((getPlatformID(info->platform) & 0xF) << 20) | + ((getSpecialID(info->special) & 0xF) << 16) | + ((id & 0xFFF) << 4) | + ((getLanguageID(fDesc->langSpecific ? info->lang : UNK_LANG) & 0xF) << 0); +} - // GAME, PLATFORM, SPECIAL, TYPE, ID[, LANG] - if (i->langSpecific) - sprintf(dstFilename, "%01X%01X%01X%02X%03X%01X", getGameID(info->game), getPlatformID(info->platform), getSpecialID(info->special), getTypeID(i->type), id, getLanguageID(info->lang)); - else - sprintf(dstFilename, "%01X%01X%01X%02X%03X", getGameID(info->game), getPlatformID(info->platform), getSpecialID(info->special), getTypeID(i->type), id); +// TODO: Get rid of this +bool getFilename(char *dstFilename, const ExtractInformation *info, const int id) { + sprintf(dstFilename, "%08X", getFilename(info, id)); return true; } @@ -388,7 +398,8 @@ typedef uint16 GameDef; GameDef createGameDef(const ExtractInformation *eI) { return ((getGameID(eI->game) & 0xF) << 12) | ((getPlatformID(eI->platform) & 0xF) << 8) | - ((getSpecialID(eI->special) & 0xF) << 4); + ((getSpecialID(eI->special) & 0xF) << 4) | + ((getLanguageID(eI->lang) & 0xF) << 0); } struct Index { @@ -1127,6 +1138,8 @@ typedef std::multimap<int, ExtractData> ExtractMap; bool getExtractionData(const Game *g, Search &search, ExtractMap &map); +bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList); + bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { char filename[128]; @@ -1149,6 +1162,7 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { for (ExtractMap::const_iterator i = ids.begin(); i != ids.end(); ++i) { const int id = i->first; + extractInfo.lang = i->second.desc.lang; const ExtractFilename *fDesc = getFilenameDesc(id); @@ -1157,11 +1171,6 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { return false; } - if (fDesc->langSpecific) - extractInfo.lang = i->second.desc.lang; - else - extractInfo.lang = UNK_LANG; - filename[0] = 0; if (!getFilename(filename, &extractInfo, id)) { fprintf(stderr, "ERROR: couldn't get filename for id %d/%s\n", id, getIdString(id)); @@ -1190,6 +1199,9 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { continue; extractInfo.lang = g->lang[i]; + if (!createIDMap(out, &extractInfo, needList)) + return false; + if (!updateIndex(out, &extractInfo)) { error("couldn't update INDEX file, stop processing of all files"); return false; @@ -1199,6 +1211,41 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) { return true; } +bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList) { + int dataEntries = 0; + // Count entries in the need list + for (const int *n = needList; *n != -1; ++n) + ++dataEntries; + + const int mapSize = 2 + dataEntries * (2 + 1 + 4); + uint8 *map = new uint8[mapSize]; + uint8 *dst = map; + + WRITE_BE_UINT16(dst, dataEntries); dst += 2; + for (const int *id = needList; *id != -1; ++id) { + WRITE_BE_UINT16(dst, *id); dst += 2; + const ExtractFilename *fDesc = getFilenameDesc(*id); + if (!fDesc) + return false; + *dst++ = getTypeID(fDesc->type); + WRITE_BE_UINT32(dst, getFilename(eI, *id)); dst += 4; + } + + char filename[12]; + if (!getFilename(filename, eI, 0)) { + fprintf(stderr, "ERROR: Could not create ID map for game\n"); + return false; + } + + out.removeFile(filename); + if (!out.addFile(filename, map, mapSize)) { + fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename); + return false; + } + + return true; +} + // Uncomment this to get various debug information about the detection table entries. //#define DEBUG_EXTRACTION_TABLES diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h index 93e03d40b6..c247846b93 100644 --- a/tools/create_kyradat/create_kyradat.h +++ b/tools/create_kyradat/create_kyradat.h @@ -27,7 +27,9 @@ // This list has to match orderwise (and thus value wise) the static data list of "engines/kyra/resource.h"! enum kExtractID { - k1ForestSeq = 0, + kIdMap = 0, + + k1ForestSeq = 1, k1KallakWritingSeq, k1KyrandiaLogoSeq, k1KallakMalcolmSeq, |