diff options
Diffstat (limited to 'devtools/create_kyradat')
-rw-r--r-- | devtools/create_kyradat/create_kyradat.cpp | 1439 | ||||
-rw-r--r-- | devtools/create_kyradat/create_kyradat.h | 315 | ||||
-rw-r--r-- | devtools/create_kyradat/extract.cpp | 987 | ||||
-rw-r--r-- | devtools/create_kyradat/extract.h | 78 | ||||
-rw-r--r-- | devtools/create_kyradat/games.cpp | 990 | ||||
-rw-r--r-- | devtools/create_kyradat/md5.cpp | 267 | ||||
-rw-r--r-- | devtools/create_kyradat/md5.h | 43 | ||||
-rw-r--r-- | devtools/create_kyradat/module.mk | 20 | ||||
-rw-r--r-- | devtools/create_kyradat/pak.cpp | 250 | ||||
-rw-r--r-- | devtools/create_kyradat/pak.h | 110 | ||||
-rw-r--r-- | devtools/create_kyradat/search.cpp | 219 | ||||
-rw-r--r-- | devtools/create_kyradat/search.h | 120 | ||||
-rw-r--r-- | devtools/create_kyradat/tables.cpp | 1968 | ||||
-rw-r--r-- | devtools/create_kyradat/tables.h | 45 | ||||
-rw-r--r-- | devtools/create_kyradat/util.cpp | 143 | ||||
-rw-r--r-- | devtools/create_kyradat/util.h | 59 |
16 files changed, 7053 insertions, 0 deletions
diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp new file mode 100644 index 0000000000..7a4b8d73a1 --- /dev/null +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -0,0 +1,1439 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// HACK to allow building with the SDL backend on MinGW +// see bug #1800764 "TOOLS: MinGW tools building broken" +#ifdef main +#undef main +#endif // main + +#include "create_kyradat.h" + +#include "search.h" +#include "pak.h" + +#include "tables.h" +#include "extract.h" + +#include "md5.h" + +#include <string> +#include <map> +#include <algorithm> +#include <map> + +enum { + kKyraDatVersion = 73 +}; + +const ExtractFilename extractFilenames[] = { + // GENERIC ID MAP + { kIdMap, -1, true }, + + // INTRO / OUTRO sequences + { k1ForestSeq, kTypeForestSeqData, false }, + { k1KallakWritingSeq, kTypeRawData, false }, + { k1KyrandiaLogoSeq, kTypeRawData, false }, + { k1KallakMalcolmSeq, kTypeRawData, false }, + { k1MalcolmTreeSeq, kTypeRawData, false }, + { k1WestwoodLogoSeq, kTypeRawData, false }, + { k1Demo1Seq, kTypeRawData, false }, + { k1Demo2Seq, kTypeRawData, false }, + { k1Demo3Seq, kTypeRawData, false }, + { k1Demo4Seq, kTypeRawData, false }, + { k1OutroReunionSeq, kTypeRawData, false }, + + // INTRO / OUTRO strings + { k1IntroCPSStrings, kTypeStringList, false }, + { k1IntroCOLStrings, kTypeStringList, false }, + { k1IntroWSAStrings, kTypeStringList, false }, + { k1IntroStrings, kTypeStringList, true }, + { k1OutroHomeString, kTypeStringList, true }, + + // INGAME strings + { k1ItemNames, kTypeStringList, true }, + { k1TakenStrings, kTypeStringList, true }, + { k1PlacedStrings, kTypeStringList, true }, + { k1DroppedStrings, kTypeStringList, true }, + { k1NoDropStrings, kTypeStringList, true }, + { k1PutDownString, kTypeStringList, true }, + { k1WaitAmuletString, kTypeStringList, true }, + { k1BlackJewelString, kTypeStringList, true }, + { k1PoisonGoneString, kTypeStringList, true }, + { k1HealingTipString, kTypeStringList, true }, + { k1ThePoisonStrings, kTypeStringList, true }, + { k1FluteStrings, kTypeStringList, true }, + { k1WispJewelStrings, kTypeStringList, true }, + { k1MagicJewelStrings, kTypeStringList, true }, + { k1FlaskFullString, kTypeStringList, true }, + { k1FullFlaskString, kTypeStringList, true }, + { k1VeryCleverString, kTypeStringList, true }, + { k1NewGameString, kTypeStringList, true }, + + // GUI strings table + { k1GUIStrings, kTypeStringList, true }, + { k1ConfigStrings, kTypeStringList, true }, + + // ROOM table/filenames + { k1RoomList, kTypeRoomList, false }, + { k1RoomFilenames, kTypeStringList, false }, + + // SHAPE tables + { k1DefaultShapes, kTypeShapeList, false }, + { k1Healing1Shapes, kTypeShapeList, false }, + { k1Healing2Shapes, kTypeShapeList, false }, + { k1PoisonDeathShapes, kTypeShapeList, false }, + { k1FluteShapes, kTypeShapeList, false }, + { k1Winter1Shapes, kTypeShapeList, false }, + { k1Winter2Shapes, kTypeShapeList, false }, + { k1Winter3Shapes, kTypeShapeList, false }, + { k1DrinkShapes, kTypeShapeList, false }, + { k1WispShapes, kTypeShapeList, false }, + { k1MagicAnimShapes, kTypeShapeList, false }, + { k1BranStoneShapes, kTypeShapeList, false }, + + // IMAGE filename table + { k1CharacterImageFilenames, kTypeStringList, false }, + + // AUDIO filename table + { k1AudioTracks, kTypeStringList, false }, + { k1AudioTracksIntro, kTypeStringList, false }, + + // AMULET anim + { k1AmuleteAnimSeq, kTypeRawData, false }, + + // PALETTE table + { k1SpecialPalette1, kTypeRawData, false }, + { k1SpecialPalette2, kTypeRawData, false }, + { k1SpecialPalette3, kTypeRawData, false }, + { k1SpecialPalette4, kTypeRawData, false }, + { k1SpecialPalette5, kTypeRawData, false }, + { k1SpecialPalette6, kTypeRawData, false }, + { k1SpecialPalette7, kTypeRawData, false }, + { k1SpecialPalette8, kTypeRawData, false }, + { k1SpecialPalette9, kTypeRawData, false }, + { k1SpecialPalette10, kTypeRawData, false }, + { k1SpecialPalette11, kTypeRawData, false }, + { k1SpecialPalette12, kTypeRawData, false }, + { k1SpecialPalette13, kTypeRawData, false }, + { k1SpecialPalette14, kTypeRawData, false }, + { k1SpecialPalette15, kTypeRawData, false }, + { k1SpecialPalette16, kTypeRawData, false }, + { k1SpecialPalette17, kTypeRawData, false }, + { k1SpecialPalette18, kTypeRawData, false }, + { k1SpecialPalette19, kTypeRawData, false }, + { k1SpecialPalette20, kTypeRawData, false }, + { k1SpecialPalette21, kTypeRawData, false }, + { k1SpecialPalette22, kTypeRawData, false }, + { k1SpecialPalette23, kTypeRawData, false }, + { k1SpecialPalette24, kTypeRawData, false }, + { k1SpecialPalette25, kTypeRawData, false }, + { k1SpecialPalette26, kTypeRawData, false }, + { k1SpecialPalette27, kTypeRawData, false }, + { k1SpecialPalette28, kTypeRawData, false }, + { k1SpecialPalette29, kTypeRawData, false }, + { k1SpecialPalette30, kTypeRawData, false }, + { k1SpecialPalette31, kTypeRawData, false }, + { k1SpecialPalette32, kTypeRawData, false }, + { k1SpecialPalette33, kTypeRawData, false }, + + // CREDITS (used in FM-TOWNS and AMIGA) + { k1CreditsStrings, kTypeRawData, true }, + + // FM-TOWNS specific + { k1TownsMusicFadeTable, k3TypeRaw16to8, false }, + { k1TownsSFXwdTable, kTypeTownsWDSfxTable, false }, + { k1TownsSFXbtTable, kTypeRawData, false }, + { k1TownsCDATable, kTypeRawData, false }, + + // PC98 specific + { k1PC98StoryStrings, kTypeStringList, true }, + { k1PC98IntroSfx, kTypeRawData, false }, + + // AMIGA specific + { k1AmigaIntroSFXTable, kTypeAmigaSfxTable, false }, + { k1AmigaGameSFXTable, kTypeAmigaSfxTable, false }, + + // HAND OF FATE + + // Sequence Player + { k2SeqplayPakFiles, kTypeStringList, false }, + { k2SeqplayCredits, kTypeRawData, false }, + { k2SeqplayCreditsSpecial, kTypeStringList, false }, + { k2SeqplayStrings, kTypeStringList, true }, + { k2SeqplaySfxFiles, k2TypeSoundList, false }, + { k2SeqplayTlkFiles, k2TypeLangSoundList, true }, + { k2SeqplaySeqData, k2TypeSeqData, false }, + { k2SeqplayIntroTracks, kTypeStringList, false }, + { k2SeqplayFinaleTracks, kTypeStringList, false }, + { k2SeqplayIntroCDA, kTypeRawData, false }, + { k2SeqplayFinaleCDA, kTypeRawData, false }, + { k2SeqplayShapeAnimData, k2TypeShpDataV1, false }, + + // Ingame + { k2IngamePakFiles, kTypeStringList, false }, + { k2IngameSfxFiles, k2TypeSize10StringList, false }, + { k2IngameSfxIndex, kTypeRawData, false }, + { k2IngameTracks, kTypeStringList, false }, + { k2IngameCDA, kTypeRawData, false }, + { k2IngameTalkObjIndex, kTypeRawData, false }, + { k2IngameTimJpStrings, kTypeStringList, false }, + { k2IngameShapeAnimData, k2TypeShpDataV2, false }, + { k2IngameTlkDemoStrings, kTypeStringList, true }, + + + // MALCOLM'S REVENGE + { k3MainMenuStrings, kTypeStringList, false }, + { k3MusicFiles, k2TypeSoundList, false }, + { k3ScoreTable, kTypeRawData, false }, + { k3SfxFiles, k2TypeSfxList, false }, + { k3SfxMap, k3TypeRaw16to8, false }, + { k3ItemAnimData, k3TypeShpData, false }, + { k3ItemMagicTable, k3TypeRaw16to8, false }, + { k3ItemStringMap, kTypeRawData, false }, + + // LANDS OF LORE + + // Ingame + { kLolIngamePakFiles, kTypeStringList, false }, + + { kLolCharacterDefs, kLolTypeCharData, false }, + { kLolIngameSfxFiles, k2TypeSfxList, false }, + { kLolIngameSfxIndex, kTypeRawData, false }, + { kLolMusicTrackMap, kTypeRawData, false }, + { kLolIngameGMSfxIndex, kTypeRawData, false }, + { kLolIngameMT32SfxIndex, kTypeRawData, false }, + { kLolIngamePcSpkSfxIndex, kTypeRawData, false }, + { kLolSpellProperties, kLolTypeSpellData, false }, + { kLolGameShapeMap, kTypeRawData, false }, + { kLolSceneItemOffs, kTypeRawData, false }, + { kLolCharInvIndex, k3TypeRaw16to8, false }, + { kLolCharInvDefs, kTypeRawData, false }, + { kLolCharDefsMan, kLolTypeRaw16, false }, + { kLolCharDefsWoman, kLolTypeRaw16, false }, + { kLolCharDefsKieran, kLolTypeRaw16, false }, + { kLolCharDefsAkshel, kLolTypeRaw16, false }, + { kLolExpRequirements, kLolTypeRaw32, false }, + { kLolMonsterModifiers, kLolTypeRaw16, false }, + { kLolMonsterShiftOffsets, kTypeRawData, false }, + { kLolMonsterDirFlags, kTypeRawData, false }, + { kLolMonsterScaleY, kTypeRawData, false }, + { kLolMonsterScaleX, kTypeRawData, false }, + { kLolMonsterScaleWH, kLolTypeRaw16, false }, + { kLolFlyingObjectShp, kLolTypeFlightShpData, false }, + { kLolInventoryDesc, kLolTypeRaw16, false }, + { kLolLevelShpList, kTypeStringList, false }, + { kLolLevelDatList, kTypeStringList, false }, + { kLolCompassDefs, kLolTypeCompassData, false }, + { kLolItemPrices, kLolTypeRaw16, false }, + { kLolStashSetup, kTypeRawData, false }, + + { kLolDscUnk1, kTypeRawData, false }, + { kLolDscShapeIndex, kTypeRawData, false }, + { kLolDscOvlMap, kTypeRawData, false }, + { kLolDscScaleWidthData, kLolTypeRaw16, false }, + { kLolDscScaleHeightData, kLolTypeRaw16, false }, + { kLolDscX, kLolTypeRaw16, false }, + { kLolDscY, kTypeRawData, false }, + { kLolDscTileIndex, kTypeRawData, false }, + { kLolDscUnk2, kTypeRawData, false }, + { kLolDscDoorShapeIndex, kTypeRawData, false }, + { kLolDscDimData1, kTypeRawData, false }, + { kLolDscDimData2, kTypeRawData, false }, + { kLolDscBlockMap, kTypeRawData, false }, + { kLolDscDimMap, kTypeRawData, false }, + { kLolDscDoorScale, kLolTypeRaw16, false }, + { kLolDscOvlIndex, k3TypeRaw16to8, false }, + { kLolDscBlockIndex, kTypeRawData, false }, + { kLolDscDoor4, kLolTypeRaw16, false }, + { kLolDscDoor1, kTypeRawData, false }, + { kLolDscDoorX, kLolTypeRaw16, false }, + { kLolDscDoorY, kLolTypeRaw16, false }, + + { kLolScrollXTop, k3TypeRaw16to8, false }, + { kLolScrollYTop, k3TypeRaw16to8, false }, + { kLolScrollXBottom, k3TypeRaw16to8, false }, + { kLolScrollYBottom, k3TypeRaw16to8, false }, + + { kLolButtonDefs, kLolTypeButtonDef, false }, + { kLolButtonList1, kLolTypeRaw16, false }, + { kLolButtonList2, kLolTypeRaw16, false }, + { kLolButtonList3, kLolTypeRaw16, false }, + { kLolButtonList4, kLolTypeRaw16, false }, + { kLolButtonList5, kLolTypeRaw16, false }, + { kLolButtonList6, kLolTypeRaw16, false }, + { kLolButtonList7, kLolTypeRaw16, false }, + { kLolButtonList8, kLolTypeRaw16, false }, + + { kLolLegendData, kTypeRawData, false }, + { kLolMapCursorOvl, kTypeRawData, false }, + { kLolMapStringId, kLolTypeRaw16, false }, + + { kLolSpellbookAnim, k3TypeRaw16to8, false }, + { kLolSpellbookCoords, k3TypeRaw16to8, false }, + { kLolHealShapeFrames, kTypeRawData, false }, + { kLolLightningDefs, kTypeRawData, false }, + { kLolFireballCoords, kLolTypeRaw16, false }, + + { kLolCredits, kTypeRawData, false }, + + { kLolHistory, kTypeRawData, false }, + + { -1, 0, 0 } +}; + +const ExtractFilename *getFilenameDesc(const int id) { + for (const ExtractFilename *i = extractFilenames; i->id != -1; ++i) { + if (i->id == id) + return i; + } + return 0; +} + +bool isLangSpecific(const int id) { + const ExtractFilename *desc = getFilenameDesc(id); + if (!desc) + return false; + return desc->langSpecific; +} + +// misc tables + +const TypeTable gameTable[] = { + { kKyra1, 0 }, + { kKyra2, 1 }, + { kKyra3, 2 }, + { kLol, 3 }, + { -1, -1 } +}; + +byte getGameID(int game) { + return std::find(gameTable, gameTable + ARRAYSIZE(gameTable) - 1, game)->value; +} + +const TypeTable languageTable[] = { + { UNK_LANG, 0 }, + { EN_ANY, 1 }, + { FR_FRA, 2 }, + { DE_DEU, 3 }, + { ES_ESP, 4 }, + { IT_ITA, 5 }, + { JA_JPN, 6 }, + { -1, -1 } +}; + +byte getLanguageID(int lang) { + return std::find(languageTable, languageTable + ARRAYSIZE(languageTable) - 1, lang)->value; +} + +const TypeTable platformTable[] = { + { kPlatformPC, 0 }, + { kPlatformAmiga, 1 }, + { kPlatformFMTowns, 2 }, + { kPlatformPC98, 3 }, + { kPlatformMacintosh, 4 }, + { -1, -1 } +}; + +byte getPlatformID(int platform) { + return std::find(platformTable, platformTable + ARRAYSIZE(platformTable) - 1, platform)->value; +} + +const TypeTable specialTable[] = { + { kNoSpecial, 0 }, + { kTalkieVersion, 1 }, + { kDemoVersion, 2 }, + { kTalkieDemoVersion, 3 }, + { -1, -1 } +}; + +byte getSpecialID(int special) { + return std::find(specialTable, specialTable + ARRAYSIZE(specialTable) - 1, special)->value; +} + +// filename processing + +uint32 getFilename(const ExtractInformation *info, const int id) { + const ExtractFilename *fDesc = getFilenameDesc(id); + + 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); +} + +// TODO: Get rid of this +bool getFilename(char *dstFilename, const ExtractInformation *info, const int id) { + sprintf(dstFilename, "%08X", getFilename(info, id)); + return true; +} + +// index generation + +typedef uint16 GameDef; + +GameDef createGameDef(const ExtractInformation *eI) { + return ((getGameID(eI->game) & 0xF) << 12) | + ((getPlatformID(eI->platform) & 0xF) << 8) | + ((getSpecialID(eI->special) & 0xF) << 4) | + ((getLanguageID(eI->lang) & 0xF) << 0); +} + +struct Index { + Index() : version(0), includedGames(0), gameList() {} + + uint32 version; + uint32 includedGames; + + typedef std::list<GameDef> GameList; + GameList gameList; +}; + +Index parseIndex(const uint8 *data, uint32 size) { + Index result; + + if (size < 8) + return result; + + result.version = READ_BE_UINT32(data); data += 4; + result.includedGames = READ_BE_UINT32(data); data += 4; + + if (result.includedGames * 2 + 8 != size) { + result.version = result.includedGames = 0; + return result; + } + + for (uint32 i = 0; i < result.includedGames; ++i) { + GameDef game = READ_BE_UINT16(data); data += 2; + result.gameList.push_back(game); + } + + return result; +} + +bool updateIndex(PAKFile &out, const ExtractInformation *eI) { + uint32 size = 0; + const uint8 *data = out.getFileData("INDEX", &size); + + Index index; + if (data) + index = parseIndex(data, size); + + GameDef gameDef = createGameDef(eI); + if (index.version == kKyraDatVersion) { + if (std::find(index.gameList.begin(), index.gameList.end(), gameDef) == index.gameList.end()) { + ++index.includedGames; + index.gameList.push_back(gameDef); + } else { + // Already included in the game list, thus we do not need any further processing here. + return true; + } + } else { + index.version = kKyraDatVersion; + index.includedGames = 1; + index.gameList.push_back(gameDef); + } + + const uint32 indexBufferSize = 8 + index.includedGames * 2; + uint8 *indexBuffer = new uint8[indexBufferSize]; + assert(indexBuffer); + uint8 *dst = indexBuffer; + WRITE_BE_UINT32(dst, index.version); dst += 4; + WRITE_BE_UINT32(dst, index.includedGames); dst += 4; + for (Index::GameList::const_iterator i = index.gameList.begin(); i != index.gameList.end(); ++i) { + WRITE_BE_UINT16(dst, *i); dst += 2; + } + + out.removeFile("INDEX"); + if (!out.addFile("INDEX", indexBuffer, indexBufferSize)) { + fprintf(stderr, "ERROR: couldn't update kyra.dat INDEX\n"); + delete[] indexBuffer; + return false; + } + + return true; +} + +bool checkIndex(PAKFile &file) { + uint32 size = 0; + const uint8 *data = file.getFileData("INDEX", &size); + if (!data) + return false; + + Index index = parseIndex(data, size); + + if (index.version != kKyraDatVersion) + return false; + if (index.includedGames * 2 + 8 != size) + return false; + + return true; +} + +// main processing + +void printHelp(const char *f) { + printf("Usage:\n"); + printf("%s output inputfiles ...\n", f); +} + +bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size); +const Game *findGame(const byte *buffer, const uint32 size); + +typedef std::map<std::string, std::string> MD5Map; +MD5Map createMD5Sums(int files, const char * const *filenames); + +struct File { + File() : data(0), size(0) {} + File(uint8 *d, uint32 s) : data(d), size(s) {} + + uint8 *data; + uint32 size; +}; +typedef std::map<const Game *, File> GameMap; +GameMap createGameMap(const MD5Map &map); + +int main(int argc, char *argv[]) { + if (argc < 3) { + printHelp(argv[0]); + return -1; + } + + // Special case for developer mode of this tool: + // With "--create filename offset size" the tool will output + // a search entry for the specifed data in the specified file. + if (!strcmp(argv[1], "--create")) { + if (argc < 5) { + printf("Developer usage: %s --create input_file hex_offset hex_size\n", argv[0]); + return -1; + } + + uint32 offset, size; + sscanf(argv[3], "%x", &offset); + sscanf(argv[4], "%x", &size); + + FILE *input = fopen(argv[2], "rb"); + if (!input) + error("Couldn't open file '%s'", argv[2]); + + byte *buffer = new byte[size]; + fseek(input, offset, SEEK_SET); + if (fread(buffer, 1, size, input) != size) { + delete[] buffer; + error("Couldn't read from file '%s'", argv[2]); + } + + fclose(input); + + SearchData d = SearchCreator::create(buffer, size); + delete[] buffer; + + printf("{ 0x%.08X, 0x%.08X, { {", d.size, d.byteSum); + for (int j = 0; j < 16; ++j) { + printf(" 0x%.2X", d.hash.digest[j]); + if (j != 15) + printf(","); + else + printf(" } } }\n"); + } + + return 0; + } + + PAKFile out; + out.loadFile(argv[1], false); + + // When the output file is no valid kyra.dat file, we will delete + // all the output. + if (!checkIndex(out)) + out.clearFile(); + + MD5Map inputFiles = createMD5Sums(argc - 2, &argv[2]); + + GameMap games = createGameMap(inputFiles); + + // Check for unused input files + MD5Map unusedFiles = inputFiles; + for (GameMap::const_iterator i = games.begin(); i != games.end(); ++i) { + unusedFiles.erase(i->first->md5[0]); + if (i->first->md5[1]) + unusedFiles.erase(i->first->md5[1]); + } + + for (MD5Map::const_iterator i = unusedFiles.begin(); i != unusedFiles.end(); ++i) + printf("Input file '%s' with md5 sum '%s' is not known.\n", i->second.c_str(), i->first.c_str()); + + unusedFiles.clear(); + + // Short circuit, in case no games are found. + if (games.empty()) { + printf("No games found. Exiting prematurely\n"); + return -1; + } + + // Process all games found + for (GameMap::const_iterator i = games.begin(); i != games.end(); ++i) { + MD5Map::const_iterator f1 = inputFiles.find(i->first->md5[0]); + MD5Map::const_iterator f2 = inputFiles.end(); + if (i->first->md5[1]) + f2 = inputFiles.find(i->first->md5[1]); + + if (f2 != inputFiles.end()) + printf("Processing files '%s' and '%s'...\n", f1->second.c_str(), f2->second.c_str()); + else + printf("Processing file '%s'...\n", f1->second.c_str()); + + if (!process(out, i->first, i->second.data, i->second.size)) + printf("FAILED\n"); + else + printf("OK\n"); + } + + // Free up memory + for (GameMap::iterator i = games.begin(); i != games.end(); ++i) + delete[] i->second.data; + games.clear(); + inputFiles.clear(); + + if (!out.saveFile(argv[1])) + error("couldn't save changes to '%s'", argv[1]); + + uint8 digest[16]; + if (!md5_file(argv[1], digest, 0)) + error("couldn't calc. md5 for file '%s'", argv[1]); + FILE *f = fopen(argv[1], "ab"); + if (!f) + error("couldn't open file '%s'", argv[1]); + if (fwrite(digest, 1, 16, f) != 16) + error("couldn't write md5sum to file '%s'", argv[1]); + fclose(f); + + return 0; +} + +MD5Map createMD5Sums(int files, const char * const *filenames) { + MD5Map result; + + while (files--) { + const char *inputFile = *filenames++; + FILE *input = fopen(inputFile, "rb"); + + uint32 size = fileSize(input); + fseek(input, 0, SEEK_SET); + + byte *buffer = new uint8[size]; + assert(buffer); + + if (fread(buffer, 1, size, input) != size) { + warning("couldn't read from file '%s', skipping it", inputFile); + delete[] buffer; + fclose(input); + continue; + } + fclose(input); + + md5_context ctx; + uint8 digest[16]; + char md5Str[33]; + + md5_starts(&ctx); + md5_update(&ctx, buffer, size); + md5_finish(&ctx, digest); + + for (int j = 0; j < 16; ++j) + sprintf(md5Str + j*2, "%02x", (int)digest[j]); + + delete[] buffer; + + result[md5Str] = inputFile; + } + + return result; +} + +GameMap createGameMap(const MD5Map &map) { + GameMap result; + + for (const Game * const *g = gameDescs; *g != 0; ++g) { + for (const Game *sub = *g; sub->game != -1; ++sub) { + MD5Map::const_iterator file1 = map.find(sub->md5[0]); + if (file1 == map.end()) + continue; + + MD5Map::const_iterator file2 = map.end(); + if (sub->md5[1] != 0) { + file2 = map.find(sub->md5[1]); + if (file2 == map.end()) + continue; + } + + FILE *f1 = fopen(file1->second.c_str(), "rb"); + FILE *f2 = 0; + + if (file2 != map.end()) + f2 = fopen(file2->second.c_str(), "rb"); + + uint32 file1Size = fileSize(f1); + uint32 file2Size = 0; + if (f2) + file2Size = fileSize(f2); + + uint8 *buffer = new uint8[file1Size + file2Size]; + assert(buffer); + + fread(buffer, 1, file1Size, f1); + if (f2) + fread(buffer + file1Size, 1, file2Size, f2); + + fclose(f1); + if (f2) + fclose(f2); + + result[sub] = File(buffer, file1Size + file2Size); + } + } + + return result; +} + +const char *getIdString(const int id) { + switch (id) { + case k1ForestSeq: + return "k1ForestSeq"; + case k1KallakWritingSeq: + return "k1KallakWritingSeq"; + case k1KyrandiaLogoSeq: + return "k1KyrandiaLogoSeq"; + case k1KallakMalcolmSeq: + return "k1KallakMalcolmSeq"; + case k1MalcolmTreeSeq: + return "k1MalcolmTreeSeq"; + case k1WestwoodLogoSeq: + return "k1WestwoodLogoSeq"; + case k1Demo1Seq: + return "k1Demo1Seq"; + case k1Demo2Seq: + return "k1Demo2Seq"; + case k1Demo3Seq: + return "k1Demo3Seq"; + case k1Demo4Seq: + return "k1Demo4Seq"; + case k1AmuleteAnimSeq: + return "k1AmuleteAnimSeq"; + case k1OutroReunionSeq: + return "k1OutroReunionSeq"; + case k1IntroCPSStrings: + return "k1IntroCPSStrings"; + case k1IntroCOLStrings: + return "k1IntroCOLStrings"; + case k1IntroWSAStrings: + return "k1IntroWSAStrings"; + case k1IntroStrings: + return "k1IntroStrings"; + case k1OutroHomeString: + return "k1OutroHomeString"; + case k1RoomFilenames: + return "k1RoomFilenames"; + case k1RoomList: + return "k1RoomList"; + case k1CharacterImageFilenames: + return "k1CharacterImageFilenames"; + case k1AudioTracks: + return "k1AudioTracks"; + case k1AudioTracksIntro: + return "k1AudioTracksIntro"; + case k1ItemNames: + return "k1ItemNames"; + case k1TakenStrings: + return "k1TakenStrings"; + case k1PlacedStrings: + return "k1PlacedStrings"; + case k1DroppedStrings: + return "k1DroppedStrings"; + case k1NoDropStrings: + return "k1NoDropStrings"; + case k1PutDownString: + return "k1PutDownString"; + case k1WaitAmuletString: + return "k1WaitAmuletString"; + case k1BlackJewelString: + return "k1BlackJewelString"; + case k1PoisonGoneString: + return "k1PoisonGoneString"; + case k1HealingTipString: + return "k1HealingTipString"; + case k1WispJewelStrings: + return "k1WispJewelStrings"; + case k1MagicJewelStrings: + return "k1MagicJewelStrings"; + case k1ThePoisonStrings: + return "k1ThePoisonStrings"; + case k1FluteStrings: + return "k1FluteStrings"; + case k1FlaskFullString: + return "k1FlaskFullString"; + case k1FullFlaskString: + return "k1FullFlaskString"; + case k1VeryCleverString: + return "k1VeryCleverString"; + case k1NewGameString: + return "k1NewGameString"; + case k1DefaultShapes: + return "k1DefaultShapes"; + case k1Healing1Shapes: + return "k1Healing1Shapes"; + case k1Healing2Shapes: + return "k1Healing2Shapes"; + case k1PoisonDeathShapes: + return "k1PoisonDeathShapes"; + case k1FluteShapes: + return "k1FluteShapes"; + case k1Winter1Shapes: + return "k1Winter1Shapes"; + case k1Winter2Shapes: + return "k1Winter2Shapes"; + case k1Winter3Shapes: + return "k1Winter3Shapes"; + case k1DrinkShapes: + return "k1DrinkShapes"; + case k1WispShapes: + return "k1WispShapes"; + case k1MagicAnimShapes: + return "k1MagicAnimShapes"; + case k1BranStoneShapes: + return "k1BranStoneShapes"; + case k1SpecialPalette1: + return "k1SpecialPalette1"; + case k1SpecialPalette2: + return "k1SpecialPalette2"; + case k1SpecialPalette3: + return "k1SpecialPalette3"; + case k1SpecialPalette4: + return "k1SpecialPalette4"; + case k1SpecialPalette5: + return "k1SpecialPalette5"; + case k1SpecialPalette6: + return "k1SpecialPalette6"; + case k1SpecialPalette7: + return "k1SpecialPalette7"; + case k1SpecialPalette8: + return "k1SpecialPalette8"; + case k1SpecialPalette9: + return "k1SpecialPalette9"; + case k1SpecialPalette10: + return "k1SpecialPalette10"; + case k1SpecialPalette11: + return "k1SpecialPalette11"; + case k1SpecialPalette12: + return "k1SpecialPalette12"; + case k1SpecialPalette13: + return "k1SpecialPalette13"; + case k1SpecialPalette14: + return "k1SpecialPalette14"; + case k1SpecialPalette15: + return "k1SpecialPalette15"; + case k1SpecialPalette16: + return "k1SpecialPalette16"; + case k1SpecialPalette17: + return "k1SpecialPalette17"; + case k1SpecialPalette18: + return "k1SpecialPalette18"; + case k1SpecialPalette19: + return "k1SpecialPalette19"; + case k1SpecialPalette20: + return "k1SpecialPalette20"; + case k1SpecialPalette21: + return "k1SpecialPalette21"; + case k1SpecialPalette22: + return "k1SpecialPalette22"; + case k1SpecialPalette23: + return "k1SpecialPalette23"; + case k1SpecialPalette24: + return "k1SpecialPalette24"; + case k1SpecialPalette25: + return "k1SpecialPalette25"; + case k1SpecialPalette26: + return "k1SpecialPalette26"; + case k1SpecialPalette27: + return "k1SpecialPalette27"; + case k1SpecialPalette28: + return "k1SpecialPalette28"; + case k1SpecialPalette29: + return "k1SpecialPalette29"; + case k1SpecialPalette30: + return "k1SpecialPalette30"; + case k1SpecialPalette31: + return "k1SpecialPalette31"; + case k1SpecialPalette32: + return "k1SpecialPalette32"; + case k1SpecialPalette33: + return "k1SpecialPalette33"; + case k1GUIStrings: + return "k1GUIStrings"; + case k1ConfigStrings: + return "k1ConfigStrings"; + case k1TownsMusicFadeTable: + return "k1TownsMusicFadeTable"; + case k1TownsSFXwdTable: + return "k1TownsSFXwdTable"; + case k1TownsSFXbtTable: + return "k1TownsSFXbtTable"; + case k1TownsCDATable: + return "k1TownsCDATable"; + case k1PC98StoryStrings: + return "k1PC98StoryStrings"; + case k1PC98IntroSfx: + return "k1PC98IntroSfx"; + case k1CreditsStrings: + return "k1CreditsStrings"; + case k1AmigaIntroSFXTable: + return "k1AmigaIntroSFXTable"; + case k1AmigaGameSFXTable: + return "k1AmigaGameSFXTable"; + case k2SeqplayPakFiles: + return "k2SeqplayPakFiles"; + case k2SeqplayStrings: + return "k2SeqplayStrings"; + case k2SeqplaySfxFiles: + return "k2SeqplaySfxFiles"; + case k2SeqplayTlkFiles: + return "k2SeqplayTlkFiles"; + case k2SeqplaySeqData: + return "k2SeqplaySeqData"; + case k2SeqplayCredits: + return "k2SeqplayCredits"; + case k2SeqplayCreditsSpecial: + return "k2SeqplayCreditsSpecial"; + case k2SeqplayIntroTracks: + return "k2SeqplayIntroTracks"; + case k2SeqplayFinaleTracks: + return "k2SeqplayFinaleTracks"; + case k2SeqplayIntroCDA: + return "k2SeqplayIntroCDA"; + case k2SeqplayFinaleCDA: + return "k2SeqplayFinaleCDA"; + case k2SeqplayShapeAnimData: + return "k2SeqplayShapeAnimData"; + case k2IngamePakFiles: + return "k2IngamePakFiles"; + case k2IngameSfxFiles: + return "k2IngameSfxFiles"; + case k2IngameSfxIndex: + return "k2IngameSfxIndex"; + case k2IngameTracks: + return "k2IngameTracks"; + case k2IngameCDA: + return "k2IngameCDA"; + case k2IngameTalkObjIndex: + return "k2IngameTalkObjIndex"; + case k2IngameTimJpStrings: + return "k2IngameTimJpStrings"; + case k2IngameShapeAnimData: + return "k2IngameShapeAnimData"; + case k2IngameTlkDemoStrings: + return "k2IngameTlkDemoStrings"; + case k3MainMenuStrings: + return "k3MainMenuStrings"; + case k3MusicFiles: + return "k3MusicFiles"; + case k3ScoreTable: + return "k3ScoreTable"; + case k3SfxFiles: + return "k3SfxFiles"; + case k3SfxMap: + return "k3SfxMap"; + case k3ItemAnimData: + return "k3ItemAnimData"; + case k3ItemMagicTable: + return "k3ItemMagicTable"; + case k3ItemStringMap: + return "k3ItemStringMap"; + case kLolIngamePakFiles: + return "kLolIngamePakFiles"; + case kLolCharacterDefs: + return "kLolCharacterDefs"; + case kLolIngameSfxFiles: + return "kLolIngameSfxFiles"; + case kLolIngameSfxIndex: + return "kLolIngameSfxIndex"; + case kLolMusicTrackMap: + return "kLolMusicTrackMap"; + case kLolIngameGMSfxIndex: + return "kLolIngameGMSfxIndex"; + case kLolIngameMT32SfxIndex: + return "kLolIngameMT32SfxIndex"; + case kLolIngamePcSpkSfxIndex: + return "kLolIngamePcSpkSfxIndex"; + case kLolSpellProperties: + return "kLolSpellProperties"; + case kLolGameShapeMap: + return "kLolGameShapeMap"; + case kLolSceneItemOffs: + return "kLolSceneItemOffs"; + case kLolCharInvIndex: + return "kLolCharInvIndex"; + case kLolCharInvDefs: + return "kLolCharInvDefs"; + case kLolCharDefsMan: + return "kLolCharDefsMan"; + case kLolCharDefsWoman: + return "kLolCharDefsWoman"; + case kLolCharDefsKieran: + return "kLolCharDefsKieran"; + case kLolCharDefsAkshel: + return "kLolCharDefsAkshel"; + case kLolExpRequirements: + return "kLolExpRequirements"; + case kLolMonsterModifiers: + return "kLolMonsterModifiers"; + case kLolMonsterShiftOffsets: + return "kLolMonsterShiftOffsets"; + case kLolMonsterDirFlags: + return "kLolMonsterDirFlags"; + case kLolMonsterScaleY: + return "kLolMonsterScaleY"; + case kLolMonsterScaleX: + return "kLolMonsterScaleX"; + case kLolMonsterScaleWH: + return "kLolMonsterScaleWH"; + case kLolFlyingObjectShp: + return "kLolFlyingObjectShp"; + case kLolInventoryDesc: + return "kLolInventoryDesc"; + case kLolLevelShpList: + return "kLolLevelShpList"; + case kLolLevelDatList: + return "kLolLevelDatList"; + case kLolCompassDefs: + return "kLolCompassDefs"; + case kLolItemPrices: + return "kLolItemPrices"; + case kLolStashSetup: + return "kLolStashSetup"; + case kLolDscUnk1: + return "kLolDscUnk1"; + case kLolDscShapeIndex: + return "kLolDscShapeIndex"; + case kLolDscOvlMap: + return "kLolDscOvlMap"; + case kLolDscScaleWidthData: + return "kLolDscScaleWidthData"; + case kLolDscScaleHeightData: + return "kLolDscScaleHeightData"; + case kLolDscX: + return "kLolDscX"; + case kLolDscY: + return "kLolDscY"; + case kLolDscTileIndex: + return "kLolDscTileIndex"; + case kLolDscUnk2: + return "kLolDscUnk2"; + case kLolDscDoorShapeIndex: + return "kLolDscDoorShapeIndex"; + case kLolDscDimData1: + return "kLolDscDimData1"; + case kLolDscDimData2: + return "kLolDscDimData2"; + case kLolDscBlockMap: + return "kLolDscBlockMap"; + case kLolDscDimMap: + return "kLolDscDimMap"; + case kLolDscOvlIndex: + return "kLolDscOvlIndex"; + case kLolDscBlockIndex: + return "kLolDscBlockIndex"; + case kLolDscDoor1: + return "kLolDscDoor1"; + case kLolDscDoorScale: + return "kLolDscDoorScale"; + case kLolDscDoor4: + return "kLolDscDoor4"; + case kLolDscDoorX: + return "kLolDscDoorX"; + case kLolDscDoorY: + return "kLolDscDoorY"; + case kLolScrollXTop: + return "kLolScrollXTop"; + case kLolScrollYTop: + return "kLolScrollYTop"; + case kLolScrollXBottom: + return "kLolScrollXBottom"; + case kLolScrollYBottom: + return "kLolScrollYBottom"; + case kLolButtonDefs: + return "kLolButtonDefs"; + case kLolButtonList1: + return "kLolButtonList1"; + case kLolButtonList2: + return "kLolButtonList2"; + case kLolButtonList3: + return "kLolButtonList3"; + case kLolButtonList4: + return "kLolButtonList4"; + case kLolButtonList5: + return "kLolButtonList5"; + case kLolButtonList6: + return "kLolButtonList6"; + case kLolButtonList7: + return "kLolButtonList7"; + case kLolButtonList8: + return "kLolButtonList8"; + case kLolLegendData: + return "kLolLegendData"; + case kLolMapCursorOvl: + return "kLolMapCursorOvl"; + case kLolMapStringId: + return "kLolMapStringId"; + case kLolSpellbookAnim: + return "kLolSpellbookAnim"; + case kLolSpellbookCoords: + return "kLolSpellbookCoords"; + case kLolHealShapeFrames: + return "kLolHealShapeFrames"; + case kLolLightningDefs: + return "kLolLightningDefs"; + case kLolFireballCoords: + return "kLolFireballCoords"; + case kLolHistory: + return "kLolHistory"; + default: + return "Unknown"; + } +} + +struct ExtractData { + ExtractData() : desc(), offset() {} + ExtractData(ExtractEntrySearchData d, uint32 o) : desc(d), offset(o) {} + + ExtractEntrySearchData desc; + uint32 offset; +}; + +typedef std::pair<int, ExtractEntrySearchData> SearchMapEntry; +typedef std::multimap<int, ExtractEntrySearchData> SearchMap; + +typedef std::pair<int, ExtractData> ExtractMapEntry; +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]; + + Search search(data, size); + ExtractMap ids; + + if (!getExtractionData(g, search, ids)) + return false; + + const int *needList = getNeedList(g); + if (!needList) { + fprintf(stderr, "ERROR: No entry need list available\n"); + return false; + } + + ExtractInformation extractInfo; + extractInfo.game = g->game; + extractInfo.platform = g->platform; + extractInfo.special = g->special; + + 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); + + if (!fDesc) { + fprintf(stderr, "ERROR: couldn't find file description for id %d/%s\n", id, getIdString(id)); + return false; + } + + filename[0] = 0; + if (!getFilename(filename, &extractInfo, id)) { + fprintf(stderr, "ERROR: couldn't get filename for id %d/%s\n", id, getIdString(id)); + return false; + } + + const ExtractType *tDesc = findExtractType(fDesc->type); + + if (!tDesc) { + fprintf(stderr, "ERROR: couldn't find type description for id %d/%s (%d)\n", id, getIdString(id), fDesc->type); + return false; + } + + PAKFile::cFileList *list = out.getFileList(); + if (list && list->findEntry(filename) != 0) + continue; + + if (!tDesc->extract(out, &extractInfo, data + i->second.offset, i->second.desc.hint.size, filename, id)) { + fprintf(stderr, "ERROR: couldn't extract id %d/%s\n", id, getIdString(id)); + return false; + } + } + + for (int i = 0; i < 3; ++i) { + if (g->lang[i] == -1) + 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; + } + } + + 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 + +bool setupSearch(const Game *g, const int *needList, Search &search, SearchMap &searchData) { + for (const int *entry = needList; *entry != -1; ++entry) { + ExtractEntryList providers = getProvidersForId(*entry); + + if (providers.empty()) { + fprintf(stderr, "ERROR: No provider for id %d/%s\n", *entry, getIdString(*entry)); + return false; + } else { + for (ExtractEntryList::const_iterator i = providers.begin(); i != providers.end(); ++i) { + // Only add generic or partly matching providers here. +#ifndef DEBUG_EXTRACTION_TABLES + if ((i->lang == UNK_LANG || i->lang == g->lang[0] || i->lang == g->lang[1] || i->lang == g->lang[2]) && + (i->platform == kPlatformUnknown || (i->platform == g->platform))) { +#endif + search.addData(i->hint); + searchData.insert(SearchMapEntry(*entry, *i)); +#ifndef DEBUG_EXTRACTION_TABLES + } +#endif + } + } + } + + return true; +} + +typedef std::list<ExtractMap::const_iterator> MatchList; +MatchList filterPlatformMatches(const Game *g, std::pair<ExtractMap::const_iterator, ExtractMap::const_iterator> range) { + bool hasPlatformMatch = false; + for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) { + if (i->second.desc.platform == g->platform) { + hasPlatformMatch = true; + break; + } + } + + MatchList result; + if (hasPlatformMatch) { + for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) { + if (i->second.desc.platform == g->platform) + result.push_back(i); + } + } else { + for (ExtractMap::const_iterator i = range.first; i != range.second; ++i) + result.push_back(i); + } + + return result; +} + +MatchList filterLanguageMatches(const int lang, const MatchList &input) { + std::list<ExtractMap::const_iterator> result; + + for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { + if ((*i)->second.desc.lang == lang) + result.push_back(*i); + } + + return result; +} + +MatchList::const_iterator filterOutBestMatch(const MatchList &input) { + MatchList::const_iterator result = input.begin(); + + if (input.size() > 1) + warning("Multiple entries found for id %d/%s", (*result)->first, getIdString((*result)->first)); + + for (MatchList::const_iterator i = input.begin(); i != input.end(); ++i) { + // Reduce all entries to one single entry. + // + // We use the following rules for this (in this order): + // - Prefer the entry with the higest size + // - Prefer the entry, which starts at the smallest offest + // + // TODO: These rules might not be safe for all games, but hopefully + // they will work fine. If there are any problems it should be rather + // easy to identify them, since we print out a warning for multiple + // entries found. + if ((*result)->second.desc.hint.size <= (*i)->second.desc.hint.size) { + if ((*result)->second.offset >= (*i)->second.offset) + result = i; + } + } + + return result; +} + +bool getExtractionData(const Game *g, Search &search, ExtractMap &map) { + SearchMap searchMap; + + const int *needList = getNeedList(g); + if (!needList) { + fprintf(stderr, "ERROR: No entry need list available\n"); + return false; + } + + if (!setupSearch(g, needList, search, searchMap)) + return false; + + // Process the data search + Search::ResultList results; + search.search(results); + + if (results.empty()) { + fprintf(stderr, "ERROR: Couldn't find any required data\n"); + return false; + } + + ExtractMap temporaryExtractMap; + for (const int *entry = needList; *entry != -1; ++entry) { + typedef std::pair<SearchMap::const_iterator, SearchMap::const_iterator> KeyRange; + KeyRange idRange = searchMap.equal_range(*entry); + + for (Search::ResultList::const_iterator i = results.begin(); i != results.end(); ++i) { + for (SearchMap::const_iterator j = idRange.first; j != idRange.second; ++j) { + if (j->second.hint == i->data) + temporaryExtractMap.insert(ExtractMapEntry(*entry, ExtractData(j->second, i->offset))); + } + } + } + + // Free up some memory + results.clear(); + searchMap.clear(); + + bool result = true; + + for (const int *entry = needList; *entry != -1; ++entry) { + MatchList possibleMatches = filterPlatformMatches(g, temporaryExtractMap.equal_range(*entry)); + + if (possibleMatches.empty()) { + fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); + result = false; + continue; + } + + if (isLangSpecific(*entry)) { + for (int i = 0; i < 3; ++i) { + if (g->lang[i] == -1) + continue; + + MatchList langMatches = filterLanguageMatches(g->lang[i], possibleMatches); + MatchList::const_iterator bestMatch = filterOutBestMatch(langMatches); + + if (bestMatch == langMatches.end()) { + // TODO: Add nice language name to output message. + fprintf(stderr, "ERROR: No entry found for id %d/%s for language %d\n", *entry, getIdString(*entry), g->lang[i]); + result = false; + continue; + } + +#ifdef DEBUG_EXTRACTION_TABLES + if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) + printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); +#endif + + map.insert(**bestMatch); + } + } else { + MatchList::const_iterator bestMatch = filterOutBestMatch(possibleMatches); + + if (bestMatch == possibleMatches.end()) { + fprintf(stderr, "ERROR: No entry found for id %d/%s\n", *entry, getIdString(*entry)); + result = false; + continue; + } + +#ifdef DEBUG_EXTRACTION_TABLES + if (((*bestMatch)->second.desc.platform != kPlatformUnknown && (*bestMatch)->second.desc.platform != g->platform)) + printf("%s: %.8X %.8X %d %d\n", getIdString(*entry), (*bestMatch)->second.desc.hint.size, (*bestMatch)->second.desc.hint.byteSum, (*bestMatch)->second.desc.lang, (*bestMatch)->second.desc.platform); +#endif + + map.insert(**bestMatch); + } + } + + return result; +} + diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h new file mode 100644 index 0000000000..d82e16fed0 --- /dev/null +++ b/devtools/create_kyradat/create_kyradat.h @@ -0,0 +1,315 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef CREATE_KYRADAT_CREATE_KYRADAT_H +#define CREATE_KYRADAT_CREATE_KYRADAT_H + +#include "util.h" + +// This list has to match orderwise (and thus value wise) the static data list of "engines/kyra/resource.h"! +enum kExtractID { + kIdMap = 0, + + k1ForestSeq = 1, + k1KallakWritingSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + + k1Demo1Seq, + k1Demo2Seq, + k1Demo3Seq, + k1Demo4Seq, + + k1AmuleteAnimSeq, + + k1OutroReunionSeq, + + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + + k1OutroHomeString, + + k1RoomFilenames, + k1RoomList, + + k1CharacterImageFilenames, + + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1PoisonGoneString, + k1HealingTipString, + k1WispJewelStrings, + k1MagicJewelStrings, + + k1ThePoisonStrings, + k1FluteStrings, + + k1FlaskFullString, + k1FullFlaskString, + + k1VeryCleverString, + k1NewGameString, + + k1DefaultShapes, + k1Healing1Shapes, + k1Healing2Shapes, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + + 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, + + k1GUIStrings, + k1ConfigStrings, + + k1AudioTracks, + k1AudioTracksIntro, + + k1CreditsStrings, + + k1TownsMusicFadeTable, + k1TownsSFXwdTable, + k1TownsSFXbtTable, + k1TownsCDATable, + + k1PC98StoryStrings, + k1PC98IntroSfx, + + k1AmigaIntroSFXTable, + k1AmigaGameSFXTable, + + k2SeqplayPakFiles, + k2SeqplayCredits, + k2SeqplayCreditsSpecial, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplayTlkFiles, + k2SeqplaySeqData, + k2SeqplayIntroTracks, + k2SeqplayFinaleTracks, + k2SeqplayIntroCDA, + k2SeqplayFinaleCDA, + k2SeqplayShapeAnimData, + + k2IngamePakFiles, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameTracks, + k2IngameCDA, + k2IngameTalkObjIndex, + k2IngameTimJpStrings, + k2IngameShapeAnimData, + k2IngameTlkDemoStrings, + + k3MainMenuStrings, + k3MusicFiles, + k3ScoreTable, + k3SfxFiles, + k3SfxMap, + k3ItemAnimData, + k3ItemMagicTable, + k3ItemStringMap, + + 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, + kLolDscDoor1, + kLolDscDoorScale, + kLolDscDoor4, + kLolDscDoorX, + kLolDscDoorY, + kLolDscOvlIndex, + kLolDscBlockIndex, + + kLolScrollXTop, + kLolScrollYTop, + kLolScrollXBottom, + kLolScrollYBottom, + + kLolButtonDefs, + kLolButtonList1, + kLolButtonList2, + kLolButtonList3, + kLolButtonList4, + kLolButtonList5, + kLolButtonList6, + kLolButtonList7, + kLolButtonList8, + + kLolLegendData, + kLolMapCursorOvl, + kLolMapStringId, + + kLolSpellbookAnim, + kLolSpellbookCoords, + kLolHealShapeFrames, + kLolLightningDefs, + kLolFireballCoords, + + kLolCredits, + + kLolHistory, + + kMaxResIDs +}; + +struct ExtractFilename { + int id; + int type; + bool langSpecific; +}; + +enum kSpecial { + kNoSpecial = 0, + kTalkieVersion, + kDemoVersion, + kTalkieDemoVersion +}; + +enum kGame { + kKyra1 = 0, + kKyra2, + kKyra3, + kLol +}; + +struct Game { + int game; + int lang[3]; + int platform; + int special; + + const char *md5[2]; +}; + +#define GAME_DUMMY_ENTRY { -1, { -1, -1, -1 }, -1, -1, { 0, 0 } } + +extern const Game * const gameDescs[]; + +const int *getNeedList(const Game *g); + +struct TypeTable { + int type; + int value; + + bool operator==(int t) const { + return (type == t); + } +}; + +#endif diff --git a/devtools/create_kyradat/extract.cpp b/devtools/create_kyradat/extract.cpp new file mode 100644 index 0000000000..6b801d14f9 --- /dev/null +++ b/devtools/create_kyradat/extract.cpp @@ -0,0 +1,987 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "extract.h" + +#include <algorithm> + +namespace { + +// Extraction function prototypes + +bool extractRaw(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractStrings(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractStrings10(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractRooms(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractShapes(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractKyraForestSeqData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractAmigaSfx(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractWdSfx(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); + +bool extractHofSeqData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractHofShapeAnimDataV1(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractHofShapeAnimDataV2(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); + +bool extractStringsWoSuffix(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractPaddedStrings(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractRaw16to8(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractMrShapeAnimData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractRaw16(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractRaw32(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +bool extractLolButtonDefs(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); + +// Extraction type table + +const ExtractType extractTypeTable[] = { + { kTypeStringList, extractStrings }, + { kTypeRoomList, extractRooms }, + { kTypeShapeList, extractShapes }, + { kTypeRawData, extractRaw }, + { kTypeForestSeqData, extractKyraForestSeqData }, + { kTypeAmigaSfxTable, extractAmigaSfx }, + { kTypeTownsWDSfxTable, extractWdSfx }, + + { k2TypeSeqData, extractHofSeqData }, + { k2TypeShpDataV1, extractHofShapeAnimDataV1 }, + { k2TypeShpDataV2, extractHofShapeAnimDataV2 }, + { k2TypeSoundList, extractStringsWoSuffix }, + { k2TypeLangSoundList, extractStringsWoSuffix }, + { k2TypeSize10StringList, extractStrings10 }, + { k2TypeSfxList, extractPaddedStrings }, + { k3TypeRaw16to8, extractRaw16to8 }, + { k3TypeShpData, extractMrShapeAnimData }, + + { kLolTypeCharData, extractRaw }, + { kLolTypeSpellData, extractRaw }, + { kLolTypeCompassData, extractRaw16to8 }, + { kLolTypeFlightShpData, extractRaw16to8 }, + { kLolTypeRaw16, extractRaw16 }, + { kLolTypeRaw32, extractRaw32 }, + { kLolTypeButtonDef, extractLolButtonDefs }, + + { -1, 0 } +}; + +// TODO: Clean up the mess of data types we have... it seems some special types +// we have (even in the main KYRA code, is just raw data access, but used specially +// to have a nice wrapper from inside StaticResource...). +const TypeTable typeTable[] = { + { kTypeStringList, 0 }, + { kTypeRawData, 1 }, + { kTypeRoomList, 2 }, + { kTypeShapeList, 3 }, + { kTypeForestSeqData, 1 }, + { kTypeAmigaSfxTable, 4 }, + { kTypeTownsWDSfxTable, 1 }, + { k2TypeSeqData, 5 }, + { k2TypeShpDataV1, 6 }, + { k2TypeShpDataV2, 7 }, + { k2TypeSoundList, 0 }, + { k2TypeLangSoundList, 0 }, + { k2TypeSize10StringList, 0 }, + { k2TypeSfxList, 0 }, + { k3TypeRaw16to8, 1 }, + { k3TypeShpData, 7 }, + { kLolTypeRaw16, 13 }, + { kLolTypeRaw32, 14 }, + { kLolTypeButtonDef, 12 }, + { kLolTypeCharData, 8 }, + { kLolTypeSpellData, 9 }, + { kLolTypeCompassData, 10 }, + { kLolTypeFlightShpData, 11 }, + { -1, 1 } +}; + +} // end of anonymous namespace + +// misc + +const ExtractType *findExtractType(const int type) { + for (const ExtractType *i = extractTypeTable; i->type != -1; ++i) { + if (i->type == type) + return i; + } + return 0; +} + +byte getTypeID(int type) { + return std::find(typeTable, typeTable + ARRAYSIZE(typeTable) - 1, type)->value; +} +// Extractor implementation + +namespace { + +bool extractRaw(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + uint8 *buffer = new uint8[size]; + assert(buffer); + memcpy(buffer, data, size); + + return out.addFile(filename, buffer, size); +} + +bool extractStrings(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int fmtPatch = 0; + // FM Towns files that need addional patches + if (info->platform == kPlatformFMTowns) { + if (id == k1TakenStrings || id == k1NoDropStrings || id == k1PoisonGoneString || + id == k1ThePoisonStrings || id == k1FluteStrings || id == k1WispJewelStrings) + fmtPatch = 1; + else if (id == k1IntroStrings) + fmtPatch = 2; + else if (id == k2SeqplayStrings) + fmtPatch = 3; + } else if (info->platform == kPlatformPC) { + if (id == k2IngamePakFiles) + fmtPatch = 4; + + // HACK + if (id == k2SeqplayIntroTracks && info->game == kLol) + return extractStringsWoSuffix(out, info, data, size, filename, id); + } + + uint32 entries = 0; + uint32 targetsize = size + 4; + for (uint32 i = 0; i < size; ++i) { + if (!data[i]) { + if (info->platform == kPlatformAmiga) { + if (i + 1 >= size) + ++entries; + else if (!data[i+1] && !(i & 1)) + continue; + else + ++entries; + } else { + ++entries; + } + + if (info->platform == kPlatformFMTowns) { + // prevents creation of empty entries (which we have mostly between all strings in the FM-TOWNS version) + while (!data[++i]) { + if (i == size) + break; + targetsize--; + } + if (fmtPatch == 1) { + // Here is the first step of the extra treatment for all FM-TOWNS string arrays that + // contain more than one string and which the original code + // addresses via stringname[boolJapanese]. + // We simply skip every other string + if (i == size) + continue; + uint32 len = strlen((const char*) data + i); + i += len; + + targetsize = targetsize - 1 - len; + + while (!data[++i]) { + if (i == len) + break; + targetsize--; + } + } + } + } + } + + if (fmtPatch == 2) { + if (info->lang == EN_ANY) { + targetsize--; + entries += 1; + } else if (info->lang == JA_JPN) { + targetsize += 2; + entries += 2; + } + } + + if (fmtPatch == 3) { + entries++; + targetsize++; + } + + if (fmtPatch == 4) { + targetsize -= 9; + } + + uint8 *buffer = new uint8[targetsize]; + assert(buffer); + memset(buffer, 0, targetsize); + uint8 *output = buffer; + const uint8 *input = (const uint8*) data; + + WRITE_BE_UINT32(output, entries); output += 4; + if (info->platform == kPlatformFMTowns) { + const byte *c = data + size; + do { + if (fmtPatch == 2 && input - data == 0x3C0 && input[0x10] == 0x32) { + memcpy(output, input, 0x0F); + input += 0x11; output += 0x0F; + } + + strcpy((char*) output, (const char*) input); + uint32 stringsize = strlen((const char*)output) + 1; + input += stringsize; output += stringsize; + // skip empty entries + while (!*input) { + // Write one empty string into intro strings file + if (fmtPatch == 2) { + if ((info->lang == EN_ANY && input - data == 0x260) || + (info->lang == JA_JPN && (input - data == 0x2BD || input - data == 0x2BE))) + *output++ = *input; + } + + // insert one dummy string at hof sequence strings position 59 + if (fmtPatch == 3) { + if ((info->lang == EN_ANY && input - data == 0x695) || + (info->lang == JA_JPN && input - data == 0x598)) + *output++ = *input; + } + + if (++input == c) + break; + } + + if (fmtPatch == 1) { + // Here is the extra treatment for all FM-TOWNS string arrays that + // contain more than one string and which the original code + // addresses via stringname[boolJapanese]. + // We simply skip every other string + if (input == c) + continue; + input += strlen((const char*)input); + while (!*input) { + if (++input == c) + break; + } + } + + } while (input < c); + } else if (info->platform == kPlatformAmiga) { + // we need to strip some aligment zeros out here + int dstPos = 0; + for (uint32 i = 0; i < size; ++i) { + if (!data[i] && !(i & 1)) { + if (i + 1 > size) + continue; + else if (i + 1 < size && !data[i+1]) + continue; + } + + *output++ = data[i]; + ++dstPos; + } + targetsize = dstPos + 4; + } else { + uint32 copySize = size; + if (fmtPatch == 4) { + memcpy(output, data, 44); + output += 44; + data += 44; + for (int t = 1; t != 10; t++) { + sprintf((char*) output, "COST%d_SH.PAK", t); + output += 13; + } + data += 126; + copySize -= 170; + } + memcpy(output, data, copySize); + } + + return out.addFile(filename, buffer, targetsize); +} + +bool extractStrings10(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + // HACK... + if (info->platform == kPlatformFMTowns && id == k2IngameSfxFiles) + return extractStringsWoSuffix(out, info, data, size, filename, id); + + const int strSize = 10; + uint32 entries = (size + (strSize - 1)) / strSize; + + uint8 *buffer = new uint8[size + 4]; + assert(buffer); + uint8 *output = buffer; + WRITE_BE_UINT32(output, entries); output += 4; + + for (uint32 i = 0; i < entries; ++i) { + const byte *src = data + i * strSize; + + while (*src) + *output++ = *src++; + *output++ = '\0'; + } + + return out.addFile(filename, buffer, output - buffer); +} + +bool extractRooms(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + // different entry size for the FM-TOWNS version + const int roomEntrySize = (info->platform == kPlatformFMTowns) ? (0x69) : ((info->platform == kPlatformAmiga) ? 0x52 : 0x51); + const int countRooms = size / roomEntrySize; + + uint8 *buffer = new uint8[countRooms * 9 + 4]; + assert(buffer); + uint8 *output = buffer; + + WRITE_BE_UINT32(output, countRooms); output += 4; + + const byte *src = data; + if (info->platform == kPlatformAmiga) { + for (int i = 0; i < countRooms; ++i) { + *output++ = *src++; assert(*src == 0); ++src; + memcpy(output, src, 8); output += 0x8; + src += roomEntrySize - 0x2; + } + } else { + for (int i = 0; i < countRooms; ++i) { + *output++ = *src++; + WRITE_BE_UINT16(output, READ_LE_UINT16(src)); output += 2; src += 2; + WRITE_BE_UINT16(output, READ_LE_UINT16(src)); output += 2; src += 2; + WRITE_BE_UINT16(output, READ_LE_UINT16(src)); output += 2; src += 2; + WRITE_BE_UINT16(output, READ_LE_UINT16(src)); output += 2; src += 2; + src += roomEntrySize - 0x9; + } + } + + return out.addFile(filename, buffer, countRooms * 9 + 4); +} + +bool extractShapes(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + byte *buffer = new byte[size + 1 * 4]; + assert(buffer); + byte *output = buffer; + + const int count = size / 0x07; + WRITE_BE_UINT32(output, count); output += 4; + memcpy(output, data, size); + + return out.addFile(filename, buffer, size + 1 * 4); +} + +bool extractKyraForestSeqData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + if (info->platform != kPlatformPC98) + return extractRaw(out, info, data, size, filename, id); + + struct PatchEntry { + uint16 pos; + uint8 val; + }; + + // This data has been taken from the FM-Towns version + static const PatchEntry patchData[] = { + { 0x0019, 0x06 }, { 0x001A, 0x09 }, { 0x001B, 0x00 }, { 0x002E, 0x06 }, { 0x002F, 0x09 }, { 0x0030, 0x00 }, + { 0x003D, 0x06 }, { 0x003E, 0x09 }, { 0x003F, 0x00 }, { 0x004C, 0x06 }, { 0x004D, 0x09 }, { 0x004E, 0x00 }, + { 0x005B, 0x06 }, { 0x005C, 0x09 }, { 0x005D, 0x00 }, { 0x0064, 0x06 }, { 0x0065, 0x09 }, { 0x0066, 0x00 }, + { 0x0079, 0x06 }, { 0x007A, 0x09 }, { 0x007B, 0x00 }, { 0x0088, 0x06 }, { 0x0089, 0x09 }, { 0x008A, 0x00 }, + { 0x0097, 0x06 }, { 0x0098, 0x09 }, { 0x0099, 0x00 }, { 0x00A6, 0x06 }, { 0x00A7, 0x09 }, { 0x00A8, 0x00 }, + { 0x00AD, 0x06 }, { 0x00AE, 0x09 }, { 0x00AF, 0x00 }, { 0x00B4, 0x06 }, { 0x00B5, 0x09 }, { 0x00B6, 0x00 }, + { 0x00C3, 0x06 }, { 0x00C4, 0x09 }, { 0x00C5, 0x00 }, { 0x00CA, 0x06 }, { 0x00CB, 0x09 }, { 0x00CC, 0x00 }, + { 0x00D1, 0x06 }, { 0x00D2, 0x09 }, { 0x00D3, 0x00 }, { 0x00E0, 0x06 }, { 0x00E1, 0x09 }, { 0x00E2, 0x00 }, + { 0x00E7, 0x06 }, { 0x00E8, 0x09 }, { 0x00E9, 0x00 }, { 0x00EE, 0x06 }, { 0x00EF, 0x09 }, { 0x00F0, 0x00 }, + { 0x00FD, 0x06 }, { 0x00FE, 0x09 }, { 0x00FF, 0x00 }, { 0x010A, 0x06 }, { 0x010B, 0x09 }, { 0x010C, 0x00 }, + { 0x011D, 0x06 }, { 0x011E, 0x09 }, { 0x011F, 0x00 }, { 0x012C, 0x06 }, { 0x012D, 0x09 }, { 0x012E, 0x00 }, + { 0x013D, 0x06 }, { 0x013E, 0x09 }, { 0x013F, 0x00 }, { 0x0148, 0x06 }, { 0x0149, 0x09 }, { 0x014A, 0x00 }, + { 0x0153, 0x06 }, { 0x0154, 0x09 }, { 0x0155, 0x00 }, { 0x015E, 0x06 }, { 0x015F, 0x09 }, { 0x0160, 0x00 }, + { 0x0169, 0x06 }, { 0x016A, 0x09 }, { 0x016B, 0x00 }, { 0x016C, 0x06 }, { 0x016D, 0x12 }, { 0x016E, 0x00 }, + { 0x017B, 0x06 }, { 0x017C, 0x09 }, { 0x017D, 0x00 }, { 0x0188, 0x06 }, { 0x0189, 0x09 }, { 0x018A, 0x00 }, + { 0x0190, 0x13 }, { 0x0000, 0x00 } + }; + + uint32 outsize = size + (ARRAYSIZE(patchData) - 1); + uint8 *buffer = new uint8[outsize]; + assert(buffer); + + const uint8 *src = data; + uint8 *dst = buffer; + const PatchEntry *patchPos = patchData; + + while (dst < (buffer + outsize)) { + if ((dst - buffer) == patchPos->pos) { + *dst++ = patchPos->val; + patchPos++; + } else { + *dst++ = *src++; + } + } + + return out.addFile(filename, buffer, outsize); +} + +bool extractAmigaSfx(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + const uint32 entries = size / 8; + byte *buffer = new byte[entries * 6 + 1 * 4]; + + byte *output = buffer; + WRITE_BE_UINT32(output, entries); output += 4; + + for (uint32 i = 0; i < entries; ++i) { + *output++ = *data++; // Note + *output++ = *data++; // Patch + data += 2; // Unused + WRITE_BE_UINT16(output, READ_BE_UINT16(data)); output += 2; data += 2; // Duration + *output++ = *data++; // Volume + *output++ = *data++; // Pan + } + + return out.addFile(filename, buffer, entries * 6 + 1 * 4); +} + +bool extractWdSfx(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + const int bufferSize = 0x12602; + + uint8 *buffer = new uint8[0x12602]; + assert(buffer); + memcpy(buffer, data, 0x7EE5); + memcpy(buffer + 0x7EE5, data + 0x7EE7, 0x7FFF); + memcpy(buffer + 0xFEE4, data + 0xFEE8, 0x271E); + + return out.addFile(filename, buffer, bufferSize); +} + +int extractHofSeqData_checkString(const void *ptr, uint8 checkSize); +int extractHofSeqData_isSequence(const void *ptr, const ExtractInformation *info, uint32 maxCheckSize); +int extractHofSeqData_isControl(const void *ptr, uint32 size); + +bool extractHofSeqData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int numSequences = 0; + int numNestedSequences = 0; + + uint16 headerSize = 50 * sizeof(uint16); + uint16 bufferSize = size + headerSize; + byte *buffer = new byte[bufferSize]; + assert(buffer); + memset(buffer, 0, bufferSize ); + uint16 *header = (uint16*) buffer; + byte *output = buffer + headerSize; + uint16 *hdout = header; + + //debug(1, "\nProcessing Hand of Fate sequence data:\n--------------------------------------\n"); + for (int cycle = 0; cycle < 2; cycle++) { + const byte *ptr = data; + hdout++; + + const byte *endOffs = (const byte *)(data + size); + + // detect sequence structs + while (ptr < endOffs) { + if (ptr[1]) { + error("invalid sequence data encountered"); + delete[] buffer; + return false; + } + + int v = extractHofSeqData_isSequence(ptr, info, endOffs - ptr); + + if (cycle == 0 && v == 1) { + if ((info->platform == kPlatformPC && info->special == kNoSpecial && *ptr == 5) || (info->special == kDemoVersion && (ptr - data == 312))) { + // patch for floppy version: skips invalid ferb sequence + // patch for demo: skips invalid title sequence + ptr += 54; + continue; + } + + numSequences++; + uint16 relOffs = (uint16) (output - buffer); + WRITE_BE_UINT16(hdout, relOffs); + hdout++; + + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); // flags + ptr += 2; + output += 2; + + memcpy(output, ptr, 28); // wsa and cps file names + ptr += 28; + output += 28; + + if (info->platform == kPlatformFMTowns) { // startupCommand + finalCommand + memcpy(output, ptr, 2); + ptr += 2; + output += 2; + } else { + *output++ = READ_LE_UINT16(ptr) & 0xff; + ptr += 2; + *output++ = READ_LE_UINT16(ptr) & 0xff; + ptr += 2; + } + + for (int w = 0; w < 7; w++) { //stringIndex1 to yPos + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + } + + ptr += 4; + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); // duration + ptr += 2; + output+= 2; + + } else if (cycle == 1 && v != 1 && v != -2) { + uint16 controlOffs = 0; + uint16 ctrSize = 0; + if (v) { + const byte *ctrStart = ptr; + while (v && v != -2) { + ptr++; + v = extractHofSeqData_isSequence(ptr, info, endOffs - ptr); + } + + if (v == -2) + break; + + ctrSize = (uint16)(ptr - ctrStart); + + if (info->special != kDemoVersion && + extractHofSeqData_isControl(ctrStart, ctrSize)) { + controlOffs = (uint16) (output - buffer); + *output++ = ctrSize >> 2; + + for (int cc = 0; cc < ctrSize; cc += 2) + WRITE_BE_UINT16(output + cc, READ_LE_UINT16(ctrStart + cc)); // frame control + output += ctrSize; + } + } + + numNestedSequences++; + uint16 relOffs = (uint16) (output - buffer); + WRITE_BE_UINT16(hdout, relOffs); + hdout++; + + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); // flags + ptr += 2; + output += 2; + + memcpy(output, ptr, 14); // wsa file name + ptr += 14; + output += 14; + + // startframe + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + + // endFrame + WRITE_BE_UINT16(output, (ctrSize && ((ctrSize >> 2) < READ_LE_UINT16(ptr))) ? (ctrSize >> 2) : READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + + // frameDelay + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + + ptr += 4; + + for (int w = 0; w < 2; w++) { //x, y + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + } + + if (!READ_LE_UINT32(ptr)) + controlOffs = 0; + + WRITE_BE_UINT16(output, controlOffs); + if (info->special != kDemoVersion) + ptr += 4; + output += 2; + + if (info->special != kDemoVersion) { + for (int w = 0; w < 2; w++) { //startupCommand, finalCommand + WRITE_BE_UINT16(output, READ_LE_UINT16(ptr)); + ptr += 2; + output += 2; + } + } else { + memset(output, 0, 4); + output += 4; + } + + if (info->platform == kPlatformFMTowns) + ptr += 2; + + } else if (cycle == 0) { + while (v != 1 && v != -2) { + ptr++; + v = extractHofSeqData_isSequence(ptr, info, endOffs - ptr); + } + + if (v == -2) + break; + + + } else if (cycle == 1) { + while (v == 1 && v != -2) { + ptr++; + v = extractHofSeqData_isSequence(ptr, info, endOffs - ptr); + } + + if (v == -2) + break; + } + } + } + + uint16 finHeaderSize = (2 + numSequences + numNestedSequences) * sizeof(uint16); + uint16 finBufferSize = ((output - buffer) - headerSize) + finHeaderSize; + byte *finBuffer = new byte[finBufferSize]; + assert(finBuffer); + uint16 diff = headerSize - finHeaderSize; + uint16 *finHeader = (uint16*) finBuffer; + + for (int i = 1; i < finHeaderSize; i++) + WRITE_BE_UINT16(&finHeader[i], (READ_BE_UINT16(&header[i]) - diff)); + WRITE_BE_UINT16(finHeader, numSequences); + WRITE_BE_UINT16(&finHeader[numSequences + 1], numNestedSequences); + memcpy (finBuffer + finHeaderSize, buffer + headerSize, finBufferSize - finHeaderSize); + delete[] buffer; + + finHeader = (uint16*) (finBuffer + ((numSequences + 2) * sizeof(uint16))); + for (int i = 0; i < numNestedSequences; i++) { + uint8 * offs = finBuffer + READ_BE_UINT16(finHeader++) + 26; + uint16 ctrl = READ_BE_UINT16(offs); + if (ctrl) + ctrl -= diff; + WRITE_BE_UINT16(offs, ctrl); + } + + return out.addFile(filename, finBuffer, finBufferSize); +} + +int extractHofSeqData_checkString(const void *ptr, uint8 checkSize) { + // return values: 1 = text; 0 = zero string; -1 = other + + int t = 0; + int c = checkSize; + const uint8 *s = (const uint8*)ptr; + + // check for character string + while (c--) { + if (*s > 31 && *s < 123) + t++; + s++; + } + + if (t == checkSize) + return 1; + + // check for zero string + c = checkSize; + uint32 sum = 0; + s = (const uint8*)ptr; + while (c--) + sum += *s++; + + return (sum) ? -1 : 0; +} + +int extractHofSeqData_isSequence(const void *ptr, const ExtractInformation *info, uint32 maxCheckSize) { + // return values: 1 = Sequence; 0 = Nested Sequence; -1 = other; -2 = overflow + + if (maxCheckSize < 30) + return -2; + + const uint8 * s = (const uint8*)ptr; + int c1 = extractHofSeqData_checkString(s + 2, 6); + int c2 = extractHofSeqData_checkString(s + 16, 6); + int c3 = extractHofSeqData_checkString(s + 2, 14); + int c4 = extractHofSeqData_checkString(s + 16, 14); + int c0 = s[1]; + int c5 = s[0]; + + if (c0 == 0 && c5 && ((c1 + c2) >= 1) && (!(c3 == 0 && c2 != 1)) && (!(c4 == 0 && c1 != 1))) { + if (maxCheckSize < 41) + return -2; + + if (info->platform == kPlatformFMTowns) { + if (!(s[37] | s[39]) && s[38] > s[36]) + return 1; + } else { + if (!(s[39] | s[41]) && s[40] > s[38]) + return 1; + } + } + + if (c0 == 0 && c5 == 4 && c3 == 0 && c4 == 0) { + if (maxCheckSize >= 41 && READ_LE_UINT32(s + 34) && !(s[39] | s[41]) && s[40] > s[38]) + return 1; + } + + if (c0 == 0 && c5 && c1 == 1 && c4 == -1 && s[20]) + return 0; + + return -1; +} + +int extractHofSeqData_isControl(const void *ptr, uint32 size) { + // return values: 1 = possible frame control data; 0 = definitely not frame control data + + const uint8 *s = (const uint8*)ptr; + for (uint32 i = 2; i < size; i += 4) { + if (!s[i]) + return 0; + } + + for (uint32 i = 1; i < size; i += 2) { + if (s[i]) + return 0; + } + return 1; +} + +bool extractHofShapeAnimDataV1(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = 1; + uint8 *buffer = new uint8[size + 1]; + const uint8 *src = data; + uint8 *dst = buffer + 1; + + for (int i = 0; i < 4; i++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; + dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 4; + dst += 2; + outsize += 4; + + for (int j = 0; j < 20; j++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; + dst += 2; + outsize += 2; + } + + }; + + *buffer = 4; // number of items + + return out.addFile(filename, buffer, outsize); +} + +bool extractHofShapeAnimDataV2(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = 1; + uint8 *buffer = new uint8[size + 1]; + const uint8 *src = data; + uint8 *dst = buffer + 1; + const uint8 *fin = data + size; + int count = 0; + + do { + if (READ_LE_UINT16(src) == 0xffff) + break; + + count++; + + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; + dst += 2; + + uint8 numFrames = *src; + *dst++ = numFrames; + src += 6; + outsize += 3; + + for (int i = 0; i < (numFrames << 1); i++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; + dst += 2; + outsize += 2; + } + + src += (48 - (numFrames << 2)); + + } while (src < fin); + + *buffer = count; // number of items + + return out.addFile(filename, buffer, outsize); +} + +bool extractStringsWoSuffix(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = size + 4; + uint8 *buffer = new uint8[outsize]; + const uint8 *src = data; + uint8 *dst = buffer + 4; + const uint8 *fin = src + size; + int entries = 0; + + while (src < fin) { + while (!*src && src < fin) + src++; + while (*src && *src != '.' && src < fin) + *dst++ = *src++; + + *dst++ = '\0'; + entries++; + + if (*src == '.') { + while (*src && src < fin) + src++; + } + } + + WRITE_BE_UINT32(buffer, entries); + outsize = dst - buffer; + + return out.addFile(filename, buffer, outsize); +} + +bool extractPaddedStrings(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = size + 4; + uint8 *buffer = new uint8[outsize]; + const uint8 *src = data; + uint8 *dst = buffer + 4; + const uint8 *fin = src + size; + int entries = 0; + + while (src < fin) { + while (!*src && src < fin) + src++; + while (*src && src < fin) + *dst++ = *src++; + + *dst++ = '\0'; + entries++; + } + + WRITE_BE_UINT32(buffer, entries); + outsize = dst - buffer; + + return out.addFile(filename, buffer, outsize); +} + +bool extractRaw16to8(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = size >> 1; + uint8 *buffer = new uint8[outsize]; + const uint8 *src = data; + uint8 *dst = buffer; + + for (int i = 0; i < outsize; i++) { + *dst++ = *src++; + src++; + } + + return out.addFile(filename, buffer, outsize); +} + +bool extractRaw16(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + uint8 *buffer = new uint8[size]; + const uint8 *src = data; + uint8 *dst = buffer; + + for (uint32 i = 0; i < (size >> 1); i++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; + dst += 2; + } + + return out.addFile(filename, buffer, size); +} + +bool extractRaw32(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + uint8 *buffer = new uint8[size]; + const uint8 *src = data; + uint8 *dst = buffer; + + for (uint32 i = 0; i < (size >> 2); i++) { + WRITE_BE_UINT32(dst, READ_LE_UINT32(src)); + src += 4; + dst += 4; + } + + return out.addFile(filename, buffer, size); +} + +bool extractLolButtonDefs(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int num = size / 22; + uint8 *buffer = new uint8[size]; + uint32 outsize = num * 18; + const uint8 *src = data; + uint8 *dst = buffer; + + for (int i = 0; i < num; i++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 6; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + WRITE_BE_UINT16(dst, READ_LE_UINT16(src)); + src += 2; dst += 2; + } + + return out.addFile(filename, buffer, outsize); +} + +bool extractMrShapeAnimData(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id) { + int outsize = 1; + uint8 *buffer = new uint8[size + 1]; + const uint8 *src2 = data; + const uint8 *src1 = data + 324; + uint8 *dst = buffer + 1; + const uint8 *fin = data + size; + int count = 0; + + do { + if (READ_LE_UINT16(src1) == 0xffff) + break; + + count++; + + WRITE_BE_UINT16(dst, READ_LE_UINT16(src1)); + src1 += 2; + dst += 2; + + uint8 numFrames = *src1; + *dst++ = numFrames; + src1 += 10; + outsize += 3; + + for (int i = 0; i < (numFrames << 1); i++) { + WRITE_BE_UINT16(dst, READ_LE_UINT16(src2)); + src2 += 2; + dst += 2; + outsize += 2; + } + } while (src1 < fin); + + *buffer = count; // number of items + + return out.addFile(filename, buffer, outsize); +} + +} // end of anonymous namespace + diff --git a/devtools/create_kyradat/extract.h b/devtools/create_kyradat/extract.h new file mode 100644 index 0000000000..0903852dd2 --- /dev/null +++ b/devtools/create_kyradat/extract.h @@ -0,0 +1,78 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef CREATE_KYRADAT_EXTRACT_H +#define CREATE_KYRADAT_EXTRACT_H + +#include "create_kyradat.h" +#include "pak.h" +#include "util.h" + +enum kExtractType { + kTypeStringList = 0, + kTypeRoomList, + kTypeShapeList, + kTypeRawData, + kTypeForestSeqData, + kTypeAmigaSfxTable, + kTypeTownsWDSfxTable, + + k2TypeSeqData, + k2TypeShpDataV1, + k2TypeShpDataV2, + k2TypeSoundList, + k2TypeLangSoundList, + k2TypeSize10StringList, + k2TypeSfxList, + + k3TypeRaw16to8, + k3TypeShpData, + + kLolTypeRaw16, + kLolTypeRaw32, + kLolTypeButtonDef, + kLolTypeCharData, + kLolTypeSpellData, + kLolTypeCompassData, + kLolTypeFlightShpData +}; + +struct ExtractInformation { + int game; + int platform; + int lang; + int special; +}; + +struct ExtractType { + int type; + bool (*extract)(PAKFile &out, const ExtractInformation *info, const byte *data, const uint32 size, const char *filename, int id); +}; + +const ExtractType *findExtractType(const int type); +byte getTypeID(int type); + +#endif + diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp new file mode 100644 index 0000000000..75a956cab0 --- /dev/null +++ b/devtools/create_kyradat/games.cpp @@ -0,0 +1,990 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "create_kyradat.h" + +// Game tables + +namespace { + +const Game kyra1Games[] = { + // Demos + { kKyra1, { EN_ANY, -1, -1 }, kPlatformPC, kDemoVersion, { "7b7504c8560ffc914d34c44c71b3094c", 0 } }, + { kKyra1, { EN_ANY, -1, -1 }, kPlatformPC, kTalkieDemoVersion, { "226fdba99cb11ef1047131d9a50e6292", 0 } }, + + // Amiga + { kKyra1, { EN_ANY, -1, -1 }, kPlatformAmiga, kNoSpecial, { "b620564b6b7e0787b053ca9e35bd9f52", 0 } }, + { kKyra1, { DE_DEU, -1, -1 }, kPlatformAmiga, kNoSpecial, { "ceddb4bd4df51698e3851e75106d117a", 0 } }, + + // Floppy + { kKyra1, { EN_ANY, -1, -1 }, kPlatformPC, kNoSpecial, { "76a4fc84e173cadb6369785787e1546e", 0 } }, + { kKyra1, { DE_DEU, -1, -1 }, kPlatformPC, kNoSpecial, { "9442d6f7db6a41f3dd4aa4de5d36e107", 0 } }, + { kKyra1, { FR_FRA, -1, -1 }, kPlatformPC, kNoSpecial, { "aa9d6d78d8b199deaf48efeca6d19af2", 0 } }, + { kKyra1, { IT_ITA, -1, -1 }, kPlatformPC, kNoSpecial, { "5d7550306b369a3492f9f3402702477c", 0 } }, + { kKyra1, { ES_ESP, -1, -1 }, kPlatformPC, kNoSpecial, { "9ff130d2558bcd674d4074849d93c362", 0 } }, + + // Talkie + { kKyra1, { EN_ANY, -1, -1 }, kPlatformPC, kTalkieVersion, { "1ebc18f3e7fbb72474a55cb0fa089ed4", 0 } }, + { kKyra1, { DE_DEU, -1, -1 }, kPlatformPC, kTalkieVersion, { "c65d381184f98ac26d9efd2d45baef51", 0 } }, + { kKyra1, { FR_FRA, -1, -1 }, kPlatformPC, kTalkieVersion, { "307c5d4a554d9068ac3d326e350ae4a6", 0 } }, + { kKyra1, { IT_ITA, -1, -1 }, kPlatformPC, kTalkieVersion, { "d0f1752098236083d81b9497bd2b6989", 0 } }, // Italian fan translation + + // FM-TOWNS + { kKyra1, { EN_ANY, JA_JPN, -1 }, kPlatformFMTowns, kNoSpecial, { "5a3ad60ccd0f2e29463e0368cd14a60d", 0 } }, + + // PC-98 + { kKyra1, { JA_JPN, -1, -1 }, kPlatformPC98, kNoSpecial, { "b9c06ac5177f5bf1f1acc0eea3937f6d", 0 } }, + + GAME_DUMMY_ENTRY +}; + +const Game kyra2Games[] = { + // demos + { kKyra2, { EN_ANY, -1, -1 }, kPlatformPC, kDemoVersion, { "a620a37579dd44ab0403482285e3897f", 0 } }, + + { kKyra2, { EN_ANY, FR_FRA, DE_DEU }, kPlatformPC, kTalkieDemoVersion, { "85bbc1cc6c4cef6ad31fc6ee79518efb", "fa54d8abfe05f9186c05f7de7eaf1480" } }, + + // floppy games + { kKyra2, { EN_ANY, -1, -1 }, kPlatformPC, kNoSpecial, { "9b0f5e57b5a2ed88b5b989cbb402b6c7", "7c3eadbe5122722cf2e5e1611e19dfb9" } }, + { kKyra2, { FR_FRA, -1, -1 }, kPlatformPC, kNoSpecial, { "df31cc9e37e1cf68df2fdc75ddf2d87b", "fc2c6782778e6c6d5a553d1cb73c98ad" } }, + { kKyra2, { DE_DEU, -1, -1 }, kPlatformPC, kNoSpecial, { "0ca4f9a1438264a4c63c3218e064ed3b", "0d9b0eb7b0ad889ec942d74d80dde1bf" } }, + { kKyra2, { IT_ITA, -1, -1 }, kPlatformPC, kNoSpecial, { "178d3ab913f61bfba21d2fb196405e8c", "3a61ed6b7c00ddae383a0361799e2ba6" } }, + + // talkie games + { kKyra2, { EN_ANY, FR_FRA, DE_DEU }, kPlatformPC, kTalkieVersion, { "85bbc1cc6c4cef6ad31fc6ee79518efb", "e20d0d2e500f01e399ec588247a7e213" } }, + { kKyra2, { IT_ITA, FR_FRA, DE_DEU }, kPlatformPC, kTalkieVersion, { "130795aa8f2333250c895dae9028b9bb", "e20d0d2e500f01e399ec588247a7e213" } }, // Italian Fan Translation + + // FM-TOWNS games + { kKyra2, { EN_ANY, JA_JPN, -1 }, kPlatformFMTowns, kNoSpecial, { "74f50d79c919cc8e7196c24942ce43d7", "a9a7fd4f05d00090e9e8bda073e6d431" } }, + + // PC-98 + { kKyra2, { EN_ANY, JA_JPN, -1 }, kPlatformPC98, kNoSpecial, { "9bbf9a69be956db072b485929b416082", "f55fda3e60c4956ce6e72b24d2ae1a07" } }, + + GAME_DUMMY_ENTRY +}; + +const Game kyra3Games[] = { + // DOS CD (multi language version, with no language specific strings) + { kKyra3, { EN_ANY, FR_FRA, DE_DEU }, kPlatformPC, kTalkieVersion, { "bf68701eb591d0b72219f314c0d32688", 0 } }, + { kKyra3, { EN_ANY, IT_ITA, DE_DEU }, kPlatformPC, kTalkieVersion, { "bf68701eb591d0b72219f314c0d32688", 0 } }, // Fan translation // TODO: Verify md5sum + { kKyra3, { ES_ESP, FR_FRA, DE_DEU }, kPlatformPC, kTalkieVersion, { "bf68701eb591d0b72219f314c0d32688", 0 } }, // Fan translation // TODO: Verify md5sum + + GAME_DUMMY_ENTRY +}; + +const Game lolGames[] = { + // DOS demo + { kLol, { EN_ANY, -1, -1 }, kPlatformPC, kDemoVersion, { "30bb5af87d38adb47d3e6ce06b1cb042", 0 } }, + + // DOS floppy (no language specifc strings) + { kLol, { EN_ANY, -1, -1 }, kPlatformPC, kNoSpecial, { "0cc764a204f7ba8cefe1a5f14c479619", 0 } }, + { kLol, { DE_DEU, -1, -1 }, kPlatformPC, kNoSpecial, { "6b843869772c1b779e1386be868c15dd", 0 } }, + + // PC98 (no language specifc strings) + { kLol, { JA_JPN, -1, -1 }, kPlatformPC98, kNoSpecial, { "6d5bd4a2f5ce433365734ca6b7a8d984", "1b0a457c48ae6908da301b656fe0aab4" } }, + + // DOS CD (multi language version, with no language specific strings) + { kLol, { EN_ANY, FR_FRA, DE_DEU }, kPlatformPC, kTalkieVersion, { "9d1778314de80598c0b0d032e2a1a1cf", "263998ec600afca1cc7b935c473df670" } }, + + GAME_DUMMY_ENTRY +}; + +} // end of anonymous namespace + +const Game * const gameDescs[] = { + kyra1Games, + kyra2Games, + kyra3Games, + lolGames, + 0 +}; + +// Need tables + +namespace { + +const int kyra1FloppyNeed[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1RoomList, + k1RoomFilenames, + k1CharacterImageFilenames, + k1DefaultShapes, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + k1AmuleteAnimSeq, + 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, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1HealingTipString, + k1PoisonGoneString, + k1Healing1Shapes, + k1Healing2Shapes, + k1ThePoisonStrings, + k1FluteStrings, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + k1WispJewelStrings, + k1MagicJewelStrings, + k1FlaskFullString, + k1FullFlaskString, + k1OutroReunionSeq, + k1OutroHomeString, + k1VeryCleverString, + k1GUIStrings, + k1NewGameString, + k1ConfigStrings, + k1AudioTracks, + k1AudioTracksIntro, + -1 +}; + +const int kyra1CDNeed[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1RoomList, + k1RoomFilenames, + k1CharacterImageFilenames, + k1DefaultShapes, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + k1AmuleteAnimSeq, + 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, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1HealingTipString, + k1PoisonGoneString, + k1Healing1Shapes, + k1Healing2Shapes, + k1ThePoisonStrings, + k1FluteStrings, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + k1WispJewelStrings, + k1MagicJewelStrings, + k1FlaskFullString, + k1FullFlaskString, + k1OutroReunionSeq, + k1OutroHomeString, + k1VeryCleverString, + k1GUIStrings, + k1NewGameString, + k1ConfigStrings, + k1AudioTracks, + k1AudioTracksIntro, + -1 +}; + +const int kyra1DemoNeed[] = { + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1Demo1Seq, + k1Demo2Seq, + k1Demo3Seq, + k1Demo4Seq, + k1AudioTracksIntro, + -1 +}; + +const int kyra1DemoCDNeed[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1AudioTracksIntro, + -1 +}; + +const int kyra1TownsNeed[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1RoomList, + k1RoomFilenames, + k1CharacterImageFilenames, + k1DefaultShapes, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + k1AmuleteAnimSeq, + 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, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1HealingTipString, + k1PoisonGoneString, + k1Healing1Shapes, + k1Healing2Shapes, + k1ThePoisonStrings, + k1FluteStrings, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + k1WispJewelStrings, + k1MagicJewelStrings, + k1FlaskFullString, + k1FullFlaskString, + k1OutroReunionSeq, + k1OutroHomeString, + k1VeryCleverString, + k1GUIStrings, + k1NewGameString, + k1ConfigStrings, + + k1TownsMusicFadeTable, + k1TownsMusicFadeTable, + k1TownsSFXwdTable, + k1TownsSFXbtTable, + k1TownsCDATable, + k1AudioTracks, + k1CreditsStrings, + -1 +}; + +const int kyra1PC98Need[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroCOLStrings, + k1IntroWSAStrings, + k1IntroStrings, + k1RoomList, + k1RoomFilenames, + k1CharacterImageFilenames, + k1DefaultShapes, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + k1AmuleteAnimSeq, + 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, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1HealingTipString, + k1PoisonGoneString, + k1Healing1Shapes, + k1Healing2Shapes, + k1ThePoisonStrings, + k1FluteStrings, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + k1WispJewelStrings, + k1MagicJewelStrings, + k1FlaskFullString, + k1FullFlaskString, + k1OutroReunionSeq, + k1OutroHomeString, + k1VeryCleverString, + k1GUIStrings, + k1NewGameString, + k1ConfigStrings, + + k1PC98StoryStrings, + k1PC98IntroSfx, + k1CreditsStrings, + -1 +}; + +const int kyra1AmigaNeed[] = { + k1KallakWritingSeq, + k1MalcolmTreeSeq, + k1WestwoodLogoSeq, + k1KyrandiaLogoSeq, + k1KallakMalcolmSeq, + k1ForestSeq, + k1IntroCPSStrings, + k1IntroWSAStrings, + k1IntroCOLStrings, + k1IntroStrings, + k1RoomList, + k1RoomFilenames, + k1CharacterImageFilenames, + k1DefaultShapes, + k1ItemNames, + k1TakenStrings, + k1PlacedStrings, + k1DroppedStrings, + k1NoDropStrings, + k1AmuleteAnimSeq, + k1PutDownString, + k1WaitAmuletString, + k1BlackJewelString, + k1HealingTipString, + k1PoisonGoneString, + k1Healing1Shapes, + k1Healing2Shapes, + k1ThePoisonStrings, + k1FluteStrings, + k1PoisonDeathShapes, + k1FluteShapes, + k1Winter1Shapes, + k1Winter2Shapes, + k1Winter3Shapes, + k1DrinkShapes, + k1WispShapes, + k1MagicAnimShapes, + k1BranStoneShapes, + k1WispJewelStrings, + k1MagicJewelStrings, + k1FlaskFullString, + k1FullFlaskString, + k1OutroReunionSeq, + k1OutroHomeString, + k1VeryCleverString, + k1GUIStrings, + k1NewGameString, + k1ConfigStrings, + k1CreditsStrings, + k1AmigaIntroSFXTable, + k1AmigaGameSFXTable, + -1 +}; + +const int kyra2CDNeed[] = { + k2SeqplayPakFiles, + k2SeqplayCredits, + k2SeqplayCreditsSpecial, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplayTlkFiles, + k2SeqplaySeqData, + k2SeqplayIntroTracks, + k2SeqplayFinaleTracks, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameTracks, + k2IngameTalkObjIndex, + k2IngameShapeAnimData, + -1 +}; + +const int kyra2CDDemoNeed[] = { + k2SeqplayPakFiles, + k2SeqplayCredits, + k2SeqplayCreditsSpecial, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplayTlkFiles, + k2SeqplaySeqData, + k2SeqplayIntroTracks, + k2SeqplayFinaleTracks, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameTracks, + k2IngameTalkObjIndex, + k2IngameShapeAnimData, + k2IngameTlkDemoStrings, + -1 +}; + +const int kyra2FloppyNeed[] = { + k2SeqplayPakFiles, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplayIntroTracks, + k2SeqplayFinaleTracks, + k2SeqplaySeqData, + k2IngamePakFiles, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameTracks, + k2IngameTalkObjIndex, + k2IngameShapeAnimData, + -1 +}; + +const int kyra2TownsNeed[] = { + k2SeqplayPakFiles, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplaySeqData, + k2SeqplayIntroCDA, + k2SeqplayFinaleCDA, + k2IngamePakFiles, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameCDA, + k2IngameTalkObjIndex, + k2IngameTimJpStrings, + k2IngameShapeAnimData, + -1 +}; + +const int kyra2PC98Need[] = { + k2SeqplayPakFiles, + k2SeqplayStrings, + k2SeqplaySfxFiles, + k2SeqplaySeqData, + k2IngamePakFiles, + k2IngameSfxFiles, + k2IngameSfxIndex, + k2IngameTalkObjIndex, + k2IngameTimJpStrings, + k2IngameShapeAnimData, + -1 +}; + +const int kyra2DemoNeed[] = { + k2SeqplayPakFiles, + k2SeqplaySeqData, + k2SeqplaySfxFiles, + k2SeqplayIntroTracks, + k2SeqplayShapeAnimData, + -1 +}; + +const int kyra3Need[] = { + k3MainMenuStrings, + k3MusicFiles, + k3ScoreTable, + k3SfxFiles, + k3SfxMap, + k3ItemAnimData, + k3ItemMagicTable, + k3ItemStringMap, + -1 +}; + +const int lolFloppyNeed[] = { + 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, + kLolStashSetup, + kLolDscUnk1, + kLolDscShapeIndex, + kLolDscOvlMap, + kLolDscScaleWidthData, + kLolDscScaleHeightData, + kLolDscX, + kLolDscY, + kLolDscTileIndex, + kLolDscUnk2, + kLolDscDoorShapeIndex, + kLolDscDimData1, + kLolDscDimData2, + kLolDscBlockMap, + kLolDscDimMap, + kLolDscOvlIndex, + kLolDscBlockIndex, + kLolDscDoor1, + kLolDscDoorScale, + kLolDscDoor4, + kLolDscDoorX, + kLolDscDoorY, + + kLolScrollXTop, + kLolScrollYTop, + kLolScrollXBottom, + kLolScrollYBottom, + + kLolButtonDefs, + kLolButtonList1, + kLolButtonList1, + kLolButtonList2, + kLolButtonList3, + kLolButtonList4, + kLolButtonList5, + kLolButtonList6, + kLolButtonList7, + kLolButtonList8, + + kLolLegendData, + kLolMapCursorOvl, + kLolMapStringId, + + kLolSpellbookAnim, + kLolSpellbookCoords, + kLolHealShapeFrames, + kLolLightningDefs, + kLolFireballCoords, + + -1 +}; + +const int lolPC98Need[] = { + kLolIngamePakFiles, + + kLolCharacterDefs, + kLolIngameSfxFiles, + kLolIngameSfxIndex, + kLolSpellProperties, + kLolGameShapeMap, + kLolSceneItemOffs, + kLolCharInvIndex, + kLolCharInvDefs, + kLolCharDefsMan, + kLolCharDefsWoman, + kLolCharDefsKieran, + kLolCharDefsAkshel, + kLolExpRequirements, + kLolMonsterModifiers, + kLolMonsterShiftOffsets, + kLolMonsterDirFlags, + kLolMonsterScaleY, + kLolMonsterScaleX, + kLolMonsterScaleWH, + kLolFlyingObjectShp, + kLolInventoryDesc, + + kLolLevelShpList, + kLolLevelDatList, + kLolCompassDefs, + kLolStashSetup, + kLolDscUnk1, + kLolDscShapeIndex, + kLolDscOvlMap, + kLolDscScaleWidthData, + kLolDscScaleHeightData, + kLolDscX, + kLolDscY, + kLolDscTileIndex, + kLolDscUnk2, + kLolDscDoorShapeIndex, + kLolDscDimData1, + kLolDscDimData2, + kLolDscBlockMap, + kLolDscDimMap, + kLolDscOvlIndex, + kLolDscBlockIndex, + kLolDscDoor1, + kLolDscDoorScale, + kLolDscDoor4, + kLolDscDoorX, + kLolDscDoorY, + + kLolScrollXTop, + kLolScrollYTop, + kLolScrollXBottom, + kLolScrollYBottom, + + kLolButtonDefs, + kLolButtonList1, + kLolButtonList1, + kLolButtonList2, + kLolButtonList3, + kLolButtonList4, + kLolButtonList5, + kLolButtonList6, + kLolButtonList7, + kLolButtonList8, + + kLolLegendData, + kLolMapStringId, + + kLolSpellbookAnim, + kLolSpellbookCoords, + kLolHealShapeFrames, + kLolLightningDefs, + kLolFireballCoords, + + kLolCredits, + + -1 +}; + +const int lolCDNeed[] = { + kLolHistory, + 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, + kLolDscOvlIndex, + kLolDscBlockIndex, + kLolDscDoor1, + kLolDscDoorScale, + kLolDscDoor4, + kLolDscDoorX, + kLolDscDoorY, + + kLolScrollXTop, + kLolScrollYTop, + kLolScrollXBottom, + kLolScrollYBottom, + + kLolButtonDefs, + kLolButtonList1, + kLolButtonList1, + kLolButtonList2, + kLolButtonList3, + kLolButtonList4, + kLolButtonList5, + kLolButtonList6, + kLolButtonList7, + kLolButtonList8, + + kLolLegendData, + kLolMapCursorOvl, + kLolMapStringId, + + kLolSpellbookAnim, + kLolSpellbookCoords, + kLolHealShapeFrames, + kLolLightningDefs, + kLolFireballCoords, + -1 +}; + +const int lolDemoNeed[] = { + k2SeqplayPakFiles, + k2SeqplayStrings, + k2SeqplaySeqData, + k2SeqplaySfxFiles, + k2SeqplayIntroTracks, + -1 +}; + +struct GameNeed { + int game; + int platform; + int special; + + const int *entries; +}; + +const GameNeed gameNeedTable[] = { + { kKyra1, kPlatformPC, kNoSpecial, kyra1FloppyNeed }, + { kKyra1, kPlatformAmiga, kNoSpecial, kyra1AmigaNeed }, + + { kKyra1, kPlatformPC, kTalkieVersion, kyra1CDNeed }, + + { kKyra1, kPlatformFMTowns, kNoSpecial, kyra1TownsNeed }, + + { kKyra1, kPlatformPC98, kNoSpecial, kyra1PC98Need }, + + { kKyra1, kPlatformPC, kDemoVersion, kyra1DemoNeed }, + + { kKyra1, kPlatformPC, kTalkieDemoVersion, kyra1DemoCDNeed }, + + { kKyra2, kPlatformPC, kNoSpecial, kyra2FloppyNeed }, + + { kKyra2, kPlatformPC, kTalkieVersion, kyra2CDNeed }, + + { kKyra2, kPlatformPC, kTalkieDemoVersion, kyra2CDDemoNeed }, + + { kKyra2, kPlatformFMTowns, kNoSpecial, kyra2TownsNeed }, + + { kKyra2, kPlatformPC98, kNoSpecial, kyra2PC98Need }, + + { kKyra2, kPlatformPC, kDemoVersion, kyra2DemoNeed }, + + { kLol, kPlatformPC, kDemoVersion, lolDemoNeed }, + + { kKyra3, kPlatformPC, kTalkieVersion, kyra3Need }, + + { kLol, kPlatformPC, kNoSpecial, lolFloppyNeed }, + { kLol, kPlatformPC98, kNoSpecial, lolPC98Need }, + + { kLol, kPlatformPC, kTalkieVersion, lolCDNeed }, + + { -1, -1, -1, 0 } +}; + +} // end of anonymous namespace + +const int *getNeedList(const Game *g) { + for (const GameNeed *need = gameNeedTable; need->game != -1; ++need) { + if (need->game == g->game && g->platform == need->platform && need->special == g->special) + return need->entries; + } + + return 0; +} + diff --git a/devtools/create_kyradat/md5.cpp b/devtools/create_kyradat/md5.cpp new file mode 100644 index 0000000000..214b5ef7ed --- /dev/null +++ b/devtools/create_kyradat/md5.cpp @@ -0,0 +1,267 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "md5.h" + +#define GET_UINT32(n, b, i) (n) = READ_LE_UINT32(b + i) +#define PUT_UINT32(n, b, i) WRITE_LE_UINT32(b + i, n) + +void md5_starts(md5_context *ctx) { + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process(md5_context *ctx, const uint8 data[64]) { + uint32 X[16], A, B, C, D; + + GET_UINT32(X[0], data, 0); + GET_UINT32(X[1], data, 4); + GET_UINT32(X[2], data, 8); + GET_UINT32(X[3], data, 12); + GET_UINT32(X[4], data, 16); + GET_UINT32(X[5], data, 20); + GET_UINT32(X[6], data, 24); + GET_UINT32(X[7], data, 28); + GET_UINT32(X[8], data, 32); + GET_UINT32(X[9], data, 36); + GET_UINT32(X[10], data, 40); + GET_UINT32(X[11], data, 44); + GET_UINT32(X[12], data, 48); + GET_UINT32(X[13], data, 52); + GET_UINT32(X[14], data, 56); + GET_UINT32(X[15], data, 60); + +#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a, b, c, d, k, s, t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x, y, z) (z ^ (x & (y ^ z))) + + P(A, B, C, D, 0, 7, 0xD76AA478); + P(D, A, B, C, 1, 12, 0xE8C7B756); + P(C, D, A, B, 2, 17, 0x242070DB); + P(B, C, D, A, 3, 22, 0xC1BDCEEE); + P(A, B, C, D, 4, 7, 0xF57C0FAF); + P(D, A, B, C, 5, 12, 0x4787C62A); + P(C, D, A, B, 6, 17, 0xA8304613); + P(B, C, D, A, 7, 22, 0xFD469501); + P(A, B, C, D, 8, 7, 0x698098D8); + P(D, A, B, C, 9, 12, 0x8B44F7AF); + P(C, D, A, B, 10, 17, 0xFFFF5BB1); + P(B, C, D, A, 11, 22, 0x895CD7BE); + P(A, B, C, D, 12, 7, 0x6B901122); + P(D, A, B, C, 13, 12, 0xFD987193); + P(C, D, A, B, 14, 17, 0xA679438E); + P(B, C, D, A, 15, 22, 0x49B40821); + +#undef F + +#define F(x, y, z) (y ^ (z & (x ^ y))) + + P(A, B, C, D, 1, 5, 0xF61E2562); + P(D, A, B, C, 6, 9, 0xC040B340); + P(C, D, A, B, 11, 14, 0x265E5A51); + P(B, C, D, A, 0, 20, 0xE9B6C7AA); + P(A, B, C, D, 5, 5, 0xD62F105D); + P(D, A, B, C, 10, 9, 0x02441453); + P(C, D, A, B, 15, 14, 0xD8A1E681); + P(B, C, D, A, 4, 20, 0xE7D3FBC8); + P(A, B, C, D, 9, 5, 0x21E1CDE6); + P(D, A, B, C, 14, 9, 0xC33707D6); + P(C, D, A, B, 3, 14, 0xF4D50D87); + P(B, C, D, A, 8, 20, 0x455A14ED); + P(A, B, C, D, 13, 5, 0xA9E3E905); + P(D, A, B, C, 2, 9, 0xFCEFA3F8); + P(C, D, A, B, 7, 14, 0x676F02D9); + P(B, C, D, A, 12, 20, 0x8D2A4C8A); + +#undef F + +#define F(x, y, z) (x ^ y ^ z) + + P(A, B, C, D, 5, 4, 0xFFFA3942); + P(D, A, B, C, 8, 11, 0x8771F681); + P(C, D, A, B, 11, 16, 0x6D9D6122); + P(B, C, D, A, 14, 23, 0xFDE5380C); + P(A, B, C, D, 1, 4, 0xA4BEEA44); + P(D, A, B, C, 4, 11, 0x4BDECFA9); + P(C, D, A, B, 7, 16, 0xF6BB4B60); + P(B, C, D, A, 10, 23, 0xBEBFBC70); + P(A, B, C, D, 13, 4, 0x289B7EC6); + P(D, A, B, C, 0, 11, 0xEAA127FA); + P(C, D, A, B, 3, 16, 0xD4EF3085); + P(B, C, D, A, 6, 23, 0x04881D05); + P(A, B, C, D, 9, 4, 0xD9D4D039); + P(D, A, B, C, 12, 11, 0xE6DB99E5); + P(C, D, A, B, 15, 16, 0x1FA27CF8); + P(B, C, D, A, 2, 23, 0xC4AC5665); + +#undef F + +#define F(x, y, z) (y ^ (x | ~z)) + + P(A, B, C, D, 0, 6, 0xF4292244); + P(D, A, B, C, 7, 10, 0x432AFF97); + P(C, D, A, B, 14, 15, 0xAB9423A7); + P(B, C, D, A, 5, 21, 0xFC93A039); + P(A, B, C, D, 12, 6, 0x655B59C3); + P(D, A, B, C, 3, 10, 0x8F0CCC92); + P(C, D, A, B, 10, 15, 0xFFEFF47D); + P(B, C, D, A, 1, 21, 0x85845DD1); + P(A, B, C, D, 8, 6, 0x6FA87E4F); + P(D, A, B, C, 15, 10, 0xFE2CE6E0); + P(C, D, A, B, 6, 15, 0xA3014314); + P(B, C, D, A, 13, 21, 0x4E0811A1); + P(A, B, C, D, 4, 6, 0xF7537E82); + P(D, A, B, C, 11, 10, 0xBD3AF235); + P(C, D, A, B, 2, 15, 0x2AD7D2BB); + P(B, C, D, A, 9, 21, 0xEB86D391); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +void md5_update(md5_context *ctx, const uint8 *input, uint32 length) { + uint32 left, fill; + + if (!length) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += length; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < length) + ctx->total[1]++; + + if (left && length >= fill) { + memcpy((void *)(ctx->buffer + left), (const void *)input, fill); + md5_process(ctx, ctx->buffer); + length -= fill; + input += fill; + left = 0; + } + + while (length >= 64) { + md5_process(ctx, input); + length -= 64; + input += 64; + } + + if (length) { + memcpy((void *)(ctx->buffer + left), (const void *)input, length); + } +} + +static const uint8 md5_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void md5_finish(md5_context *ctx, uint8 digest[16]) { + uint32 last, padn; + uint32 high, low; + uint8 msglen[8]; + + high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_UINT32(low, msglen, 0); + PUT_UINT32(high, msglen, 4); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + md5_update(ctx, md5_padding, padn); + md5_update(ctx, msglen, 8); + + PUT_UINT32(ctx->state[0], digest, 0); + PUT_UINT32(ctx->state[1], digest, 4); + PUT_UINT32(ctx->state[2], digest, 8); + PUT_UINT32(ctx->state[3], digest, 12); +} + +bool md5_file(const char *name, uint8 digest[16], uint32 length) { + FILE *f; + + f = fopen(name, "rb"); + if (f == NULL) { + printf("md5_file couldn't open '%s'\n", name); + return false; + } + + md5_context ctx; + uint32 i; + unsigned char buf[1000]; + bool restricted = (length != 0); + int readlen; + + if (!restricted || sizeof(buf) <= length) + readlen = sizeof(buf); + else + readlen = length; + + md5_starts(&ctx); + + + while ((i = (uint32)fread(buf, 1, readlen, f)) > 0) { + md5_update(&ctx, buf, i); + + length -= i; + if (restricted && length == 0) + break; + + if (restricted && sizeof(buf) > length) + readlen = length; + } + + md5_finish(&ctx, digest); + fclose(f); + return true; +} diff --git a/devtools/create_kyradat/md5.h b/devtools/create_kyradat/md5.h new file mode 100644 index 0000000000..dd50efece8 --- /dev/null +++ b/devtools/create_kyradat/md5.h @@ -0,0 +1,43 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef COMMON_MD5_H +#define COMMON_MD5_H + +#include "util.h" + +typedef struct { + uint32 total[2]; + uint32 state[4]; + uint8 buffer[64]; +} md5_context; + +void md5_starts(md5_context *ctx); +void md5_update(md5_context *ctx, const uint8 *input, uint32 length); +void md5_finish(md5_context *ctx, uint8 digest[16]); + +bool md5_file(const char *name, uint8 digest[16], uint32 length = 0); + +#endif diff --git a/devtools/create_kyradat/module.mk b/devtools/create_kyradat/module.mk new file mode 100644 index 0000000000..60cd1f8578 --- /dev/null +++ b/devtools/create_kyradat/module.mk @@ -0,0 +1,20 @@ +# $URL$ +# $Id$ + +MODULE := devtools/create_kyradat + +MODULE_OBJS := \ + create_kyradat.o \ + extract.o \ + games.o \ + md5.o \ + pak.o \ + search.o \ + tables.o \ + util.o + +# Set the name of the executable +TOOL_EXECUTABLE := create_kyradat + +# Include common rules +include $(srcdir)/rules.mk diff --git a/devtools/create_kyradat/pak.cpp b/devtools/create_kyradat/pak.cpp new file mode 100644 index 0000000000..4179f42df0 --- /dev/null +++ b/devtools/create_kyradat/pak.cpp @@ -0,0 +1,250 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "pak.h" + +bool PAKFile::loadFile(const char *file, const bool isAmiga) { + _isAmiga = isAmiga; + if (!file) + return true; + + delete _fileList; + _fileList = 0; + + FILE *pakfile = fopen(file, "rb"); + if (!pakfile) + return false; + + uint32 filesize = fileSize(pakfile); + + // TODO: get rid of temp. buffer + uint8 *buffer = new uint8[filesize]; + assert(buffer); + + fread(buffer, filesize, 1, pakfile); + + fclose(pakfile); + + const char *currentName = 0; + + uint32 startoffset = _isAmiga ? READ_BE_UINT32(buffer) : READ_LE_UINT32(buffer); + uint32 endoffset = 0; + uint8* position = buffer + 4; + + while (true) { + uint32 strlgt = strlen((const char*)position); + currentName = (const char*)position; + + if (!(*currentName)) + break; + + position += strlgt + 1; + endoffset = _isAmiga ? READ_BE_UINT32(position) : READ_LE_UINT32(position); + if (endoffset > filesize) { + endoffset = filesize; + } else if (endoffset == 0) { + endoffset = filesize; + } + position += 4; + + uint8 *data = new uint8[endoffset - startoffset]; + assert(data); + memcpy(data, buffer + startoffset, endoffset - startoffset); + addFile(currentName, data, endoffset - startoffset); + data = 0; + + if (endoffset == filesize) + break; + + startoffset = endoffset; + } + + delete[] buffer; + return true; +} + +bool PAKFile::saveFile(const char *file) { + if (!_fileList) + return true; + + FILE *f = fopen(file, "wb"); + if (!f) { + error("couldn't open file '%s' for writing", file); + return false; + } + + // TODO: implement error handling + uint32 startAddr = _fileList->getTableSize()+5+4; + static const char *zeroName = "\0\0\0\0\0"; + + uint32 curAddr = startAddr; + for (FileList *cur = _fileList; cur; cur = cur->next) { + if (_isAmiga) + writeUint32BE(f, curAddr); + else + writeUint32LE(f, curAddr); + fwrite(cur->filename, 1, strlen(cur->filename) + 1, f); + curAddr += cur->size; + } + if (_isAmiga) + writeUint32BE(f, curAddr); + else + writeUint32LE(f, curAddr); + fwrite(zeroName, 1, 5, f); + + for (FileList *cur = _fileList; cur; cur = cur->next) + fwrite(cur->data, 1, cur->size, f); + + fclose(f); + return true; +} + +void PAKFile::drawFileList() { + FileList *cur = _fileList; + while (cur) { + printf("Filename: '%s' size: %d\n", cur->filename, cur->size); + cur = cur->next; + } +} + +bool PAKFile::outputAllFiles() { + FileList *cur = _fileList; + while (cur) { + FILE *file = fopen(cur->filename, "wb"); + if (!file) { + error("couldn't open file '%s' for writing", cur->filename); + return false; + } + printf("Exracting file '%s'...", cur->filename); + if (fwrite(cur->data, 1, cur->size, file) == cur->size) { + printf("OK\n"); + } else { + printf("FAILED\n"); + return false; + } + fclose(file); + cur = cur->next; + } + return true; +} + +bool PAKFile::outputFileAs(const char *f, const char *fn) { + FileList *cur = (_fileList != 0) ? _fileList->findEntry(f) : 0; + + if (!cur) { + error("file '%s' not found", f); + return false; + } + + FILE *file = fopen(fn, "wb"); + if (!file) { + error("couldn't open file '%s' in write mode", fn); + return false; + } + printf("Exracting file '%s' to file '%s'...", cur->filename, fn); + if (fwrite(cur->data, 1, cur->size, file) == cur->size) { + printf("OK\n"); + } else { + printf("FAILED\n"); + return false; + } + fclose(file); + return true; +} + +const uint8 *PAKFile::getFileData(const char *file, uint32 *size) { + FileList *cur = (_fileList != 0) ? _fileList->findEntry(file) : 0; + + if (!cur) + return 0; + + if (size) + *size = cur->size; + return cur->data; +} + +bool PAKFile::addFile(const char *name, const char *file) { + if (_fileList && _fileList->findEntry(name)) { + error("entry '%s' already exists", name); + return false; + } + + FILE *f = fopen(file, "rb"); + if (!f) { + error("couldn't open file '%s'", file); + return false; + } + + uint32 filesize = fileSize(f); + uint8 *data = new uint8[filesize]; + assert(data); + if (fread(data, 1, filesize, f) != filesize) { + error("couldn't read from file '%s'", file); + return false; + } + fclose(f); + return addFile(name, data, filesize); +} + +bool PAKFile::addFile(const char *name, uint8 *data, uint32 size) { + if (_fileList && _fileList->findEntry(name)) { + error("entry '%s' already exists", name); + return false; + } + + FileList *newEntry = new FileList; + assert(newEntry); + newEntry->filename = new char[strlen(name)+1]; + assert(newEntry->filename); + strncpy(newEntry->filename, name, strlen(name)+1); + newEntry->size = size; + newEntry->data = data; + + if (_fileList) { + _fileList->addEntry(newEntry); + } else { + _fileList = newEntry; + } + return true; +} + +bool PAKFile::removeFile(const char *name) { + for (FileList *cur = _fileList, *last = 0; cur; last = cur, cur = cur->next) { + if (scumm_stricmp(cur->filename, name) == 0) { + FileList *next = cur->next; + cur->next = 0; + delete cur; + if (last) + last->next = next; + else + _fileList = next; + return true; + } + } + return false; +} diff --git a/devtools/create_kyradat/pak.h b/devtools/create_kyradat/pak.h new file mode 100644 index 0000000000..ee6dabb672 --- /dev/null +++ b/devtools/create_kyradat/pak.h @@ -0,0 +1,110 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_PAK_H +#define KYRA_PAK_H + +#include "util.h" +#include <string.h> + +class PAKFile { +public: + PAKFile() : _fileList(0), _isAmiga(false) {} + ~PAKFile() { delete _fileList; } + + bool loadFile(const char *file, const bool isAmiga); + bool saveFile(const char *file); + void clearFile() { delete _fileList; _fileList = 0; } + + uint32 getFileSize() const { return _fileList->getTableSize()+5+4+_fileList->getFileSize(); } + + void drawFileList(); + + bool outputAllFiles(); + + bool outputFile(const char *file) { return outputFileAs(file, file); } + bool outputFileAs(const char *file, const char *outputName); + const uint8 *getFileData(const char *file, uint32 *size); + + bool addFile(const char *name, const char *file); + bool addFile(const char *name, uint8 *data, uint32 size); + + bool removeFile(const char *name); +public: + struct FileList { + FileList() : filename(0), size(0), data(0), next(0) {} + ~FileList() { + delete[] filename; + delete[] data; + delete next; + } + + FileList *findEntry(const char *f) { + for (FileList *cur = this; cur; cur = cur->next) { + if (scumm_stricmp(cur->filename, f) != 0) + continue; + return cur; + } + return 0; + } + + const FileList *findEntry(const char *f) const { + for (const FileList *cur = this; cur; cur = cur->next) { + if (scumm_stricmp(cur->filename, f) != 0) + continue; + return cur; + } + return 0; + } + + void addEntry(FileList *e) { + if (next) + next->addEntry(e); + else + next = e; + } + uint32 getTableSize() const { + return strlen(filename)+1+4+((next != 0) ? next->getTableSize() : 0); + } + uint32 getFileSize() const { + return size + (next != 0 ? next->getFileSize() : 0); + } + + char *filename; + uint32 size; + uint8 *data; + + FileList *next; + }; + + typedef const FileList cFileList; + + cFileList *getFileList() const { return _fileList; } +private: + FileList *_fileList; + bool _isAmiga; +}; + +#endif diff --git a/devtools/create_kyradat/search.cpp b/devtools/create_kyradat/search.cpp new file mode 100644 index 0000000000..28631fa652 --- /dev/null +++ b/devtools/create_kyradat/search.cpp @@ -0,0 +1,219 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "search.h" +#include "md5.h" + +#include <algorithm> +#include <cassert> + +Hasher::Hash Hasher::createHash(const byte *data, uint32 size) { + md5_context ctx; + md5_starts(&ctx); + md5_update(&ctx, data, size); + + Hash hash; + md5_finish(&ctx, hash.digest); + return hash; +} + +SearchData SearchCreator::create(const char *filename) { + FILE *f = fopen(filename, "rb"); + assert(f); + + SearchData data; + data.size = fileSize(f); + + byte *buffer = new byte[data.size]; + fread(buffer, 1, data.size, f); + fclose(f); + + data = create(buffer, data.size); + delete[] buffer; + + return data; +} + +SearchData SearchCreator::create(const byte *buffer, uint32 size) { + SearchData data; + + data.size = size; + data.hash = Hasher::createHash(buffer, data.size); + data.byteSum = 0; + + for (uint32 i = 0; i < data.size; ++i) + data.byteSum += buffer[i]; + + return data; +} + +SumCreator::SumCreator(InputList list, const DataInput &input) : _curOffset(0), _input(input), _sums() { + // Sort in ascending order + list.sort(std::less<uint32>()); + + uint32 byteSum = 0; + uint32 oldSize = 0; + + for (InputList::const_iterator i = list.begin(); i != list.end(); ++i) { + // Strip out entries, which exceed the buffer size + if (*i > _input.size()) + continue; + + // Strip out duplicates + if (_sums.find(*i) != _sums.end()) + continue; + + // Only add the bytes exceeding the old sum's size + // to the sum. This saves a few accesses. + for (uint32 j = oldSize; j < *i; ++j) + byteSum += _input[j]; + + _sums[*i] = byteSum; + + // Save this sum's size + oldSize = *i; + } +} + +bool SumCreator::nextByte() { + // Calculate the bytes available for summing. We need to add + // 1 here, since we will only update the offset AFTER everything + // is done. + const uint32 sizeLeft = _input.size() - (_curOffset + 1); + + if (!sizeLeft) { + _sums.clear(); + return false; + } + + // Grab the old first byte. + const byte firstByte = _input[_curOffset]; + + typedef std::list<uint32> DeletionList; + DeletionList toRemove; + + for (SumMap::iterator i = _sums.begin(); i != _sums.end(); ++i) { + // If this entry needs to sum up a larger buffer than the buffer + // size left, we will remove the entry and continue to the next + // one. + if (i->first > sizeLeft) { + // Add the current entry to the removal list. + toRemove.push_back(i->first); + continue; + } + + // Update the byte sum. First we remove the old first byte + // from the sum, next we add the next available byte. + i->second -= firstByte; + i->second += _input[_curOffset + i->first]; + } + + // Remove all entries flagged for removal + for (DeletionList::const_iterator i = toRemove.begin(); i != toRemove.end(); ++i) + _sums.erase(*i); + + // Update out offset. + ++_curOffset; + + // We return whether there are still some sums left available. + return !_sums.empty(); +} + +bool SumCreator::hasSum(uint32 size) const { + return _sums.find(size) != _sums.end(); +} + +uint32 SumCreator::getSum(uint32 size) const { + SumMap::const_iterator s = _sums.find(size); + + if (s == _sums.end()) + return 0; + + return s->second; +} + +Search::Search(const char *filename) : _data(), _search() { + FILE *src = fopen(filename, "rb"); + assert(src); + + uint32 size = fileSize(src); + byte *data = new byte[size]; + fread(data, 1, size, src); + fclose(src); + + _data.resize(size); + std::copy(data, data + size, _data.begin()); + delete[] data; +} + +Search::Search(const byte *data, uint32 size) : _data(), _search() { + _data.resize(size); + std::copy(data, data + size, _data.begin()); +} + +void Search::addData(SearchData data) { + // Do not add any duplicates + if (std::find(_search.begin(), _search.end(), data) != _search.end()) + return; + + _search.push_back(data); +} + +bool Search::search(ResultList &res) { + SumCreator::InputList list; + for (SearchList::const_iterator i = _search.begin(); i != _search.end(); ++i) + list.push_back(i->size); + + SumCreator sum(list, _data); + list.clear(); + + do { + const uint32 offset = sum.getOffset(); + + for (SearchList::iterator i = _search.begin(); i != _search.end(); ) { + if (!sum.hasSum(i->size)) { + i = _search.erase(i); + continue; + } + + const uint32 byteSum = sum.getSum(i->size); + if (byteSum == i->byteSum) { + if (Hasher::createHash(&_data[offset], i->size) == i->hash) { + res.push_back(ResultData(*i, offset)); + i = _search.erase(i); + continue; + } + } + + ++i; + } + } while (sum.nextByte()); + + return !res.empty(); +} + diff --git a/devtools/create_kyradat/search.h b/devtools/create_kyradat/search.h new file mode 100644 index 0000000000..6459606ef8 --- /dev/null +++ b/devtools/create_kyradat/search.h @@ -0,0 +1,120 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SEARCH_H +#define SEARCH_H + +#include "util.h" + +#include <list> +#include <map> +#include <vector> +#include <cstring> + +class Hasher { +public: + struct Hash { + uint8 digest[16]; + + bool operator==(const Hash &r) const { + return !std::memcmp(digest, r.digest, sizeof(digest)); + } + + bool operator<(const Hash &r) const { + return std::memcmp(digest, r.digest, sizeof(digest)) < 0; + } + }; + + static Hash createHash(const byte *data, uint32 size); +}; + +struct SearchData { + uint32 size; + + uint32 byteSum; + Hasher::Hash hash; + + bool operator==(const SearchData &r) const { + return (size == r.size && byteSum == r.byteSum && hash == r.hash); + } + + bool operator<(const SearchData &r) const { + return (size < r.size && byteSum < r.byteSum && hash < r.hash); + } +}; + +class SearchCreator { +public: + static SearchData create(const char *filename); + static SearchData create(const byte *buffer, uint32 size); +}; + +class SumCreator { +public: + typedef std::list<uint32> InputList; + typedef std::vector<byte> DataInput; + + SumCreator(InputList list, const DataInput &input); + + bool nextByte(); + + uint32 getOffset() const { return _curOffset; } + + bool hasSum(uint32 size) const; + uint32 getSum(uint32 size) const; +private: + uint32 _curOffset; + DataInput _input; + + typedef std::map<uint32, uint32> SumMap; + SumMap _sums; +}; + +class Search { +public: + Search(const char *filename); + Search(const byte *data, uint32 size); + + void addData(SearchData data); + + struct ResultData { + SearchData data; + uint32 offset; + + ResultData() : data(), offset() {} + ResultData(SearchData d, uint32 o) : data(d), offset(o) {} + }; + + typedef std::list<ResultData> ResultList; + bool search(ResultList &res); +private: + SumCreator::DataInput _data; + + typedef std::list<SearchData> SearchList; + SearchList _search; +}; + +#endif + diff --git a/devtools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp new file mode 100644 index 0000000000..777f237650 --- /dev/null +++ b/devtools/create_kyradat/tables.cpp @@ -0,0 +1,1968 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "tables.h" +#include "create_kyradat.h" + +#define EXTRACT_END_ENTRY { UNK_LANG, kPlatformUnknown, { 0, 0, { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } } + +namespace { + +// Id provider tables + +const ExtractEntrySearchData k1ForestSeqProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000195, 0x00001455, { { 0x86, 0xC2, 0x45, 0xEB, 0x16, 0x8A, 0x44, 0x73, 0xB4, 0x59, 0x13, 0x9B, 0x85, 0x40, 0x82, 0x81 } } } }, // floppy + { UNK_LANG, kPlatformUnknown, { 0x000002DE, 0x00003946, { { 0x85, 0x79, 0xDC, 0xB8, 0x62, 0xAD, 0xD6, 0x01, 0xA5, 0x66, 0x6B, 0xC4, 0x61, 0xCA, 0x82, 0xF5 } } } }, // CD + Amiga + + { UNK_LANG, kPlatformUnknown, { 0x00000273, 0x00001D80, { { 0x18, 0x32, 0xB7, 0xFB, 0xD8, 0x1A, 0x6D, 0x83, 0x75, 0xF5, 0x2B, 0xF7, 0xC0, 0xFD, 0x85, 0xEF } } } }, // Amiga + CD demo + + { UNK_LANG, kPlatformFMTowns, { 0x00000196, 0x00001468, { { 0x06, 0x8D, 0xC1, 0x9B, 0xBC, 0x28, 0xE8, 0x36, 0x43, 0x67, 0x34, 0xAA, 0x78, 0xB9, 0xCB, 0x72 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x0000013B, 0x0000128A, { { 0xD8, 0xB1, 0xFF, 0x57, 0xC9, 0x5D, 0xE1, 0x23, 0xA5, 0xA0, 0x4B, 0x0F, 0x28, 0xAC, 0x56, 0x83 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1KallakWritingSeqProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000007F5, 0x00006DCD, { { 0x0E, 0x0A, 0x75, 0xA5, 0x71, 0x5A, 0xC6, 0x32, 0x52, 0x7F, 0xEC, 0x2B, 0x0B, 0xF2, 0x22, 0xE6 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000805, 0x0000719E, { { 0xA2, 0xFE, 0x0A, 0xAA, 0xD9, 0x43, 0x5A, 0xBE, 0x56, 0x38, 0x73, 0x42, 0xAC, 0xA9, 0x1B, 0x01 } } } }, // CD + + { UNK_LANG, kPlatformAmiga, { 0x000007F4, 0x00006DAD, { { 0x84, 0x9D, 0x82, 0xD2, 0x4E, 0x8B, 0xE2, 0x86, 0x82, 0x5E, 0xE7, 0x2C, 0x7A, 0xD6, 0xFE, 0x19 } } } }, + + { UNK_LANG, kPlatformFMTowns, { 0x000007F7, 0x00006E23, { { 0x97, 0x8C, 0x63, 0x8D, 0x91, 0x68, 0xA5, 0x63, 0x55, 0x43, 0xE7, 0xE0, 0x12, 0xF9, 0x80, 0xA4 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x000007F3, 0x00006D9E, { { 0x3E, 0x83, 0xA4, 0xBF, 0x43, 0xAC, 0xDD, 0x41, 0x33, 0xC3, 0x33, 0x4E, 0xAE, 0x08, 0xB6, 0xDA } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1KyrandiaLogoSeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000005C, 0x000003D3, { { 0x75, 0xC5, 0x55, 0x54, 0x00, 0xD7, 0xE9, 0x26, 0x0F, 0x01, 0xB1, 0xB7, 0xA9, 0x29, 0xF7, 0x69 } } } }, + { UNK_LANG, kPlatformPC, { 0x000000A6, 0x00000A09, { { 0x70, 0x6E, 0x74, 0xBB, 0xD7, 0x09, 0x05, 0xDD, 0xA3, 0x09, 0x96, 0x40, 0xBD, 0x01, 0x19, 0x05 } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x00000054, 0x00000300, { { 0x4E, 0xAD, 0xD0, 0x73, 0xD2, 0x3C, 0xF6, 0x6B, 0x65, 0x23, 0xA2, 0x30, 0xD6, 0xEE, 0x1C, 0x13 } } } }, // demo + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1KallakMalcolmSeqProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000026B, 0x00002132, { { 0x51, 0x07, 0x32, 0xA2, 0x09, 0x47, 0x97, 0x02, 0x85, 0x31, 0x39, 0x93, 0x3A, 0x53, 0x47, 0xA5 } } } }, // floppy + { UNK_LANG, kPlatformUnknown, { 0x0000027B, 0x0000220A, { { 0xB7, 0xC1, 0x57, 0x04, 0x9B, 0x67, 0x82, 0x7B, 0x6E, 0xFD, 0x59, 0xF2, 0x10, 0x93, 0x89, 0x12 } } } }, // CD + Amiga + + { UNK_LANG, kPlatformUnknown, { 0x000002B8, 0x0000280B, { { 0x98, 0xC8, 0x36, 0x8C, 0xF8, 0x92, 0xC2, 0xB9, 0x1B, 0x71, 0x6B, 0x4C, 0xA4, 0x6C, 0xF6, 0x30 } } } }, // Amiga + CD demo + + { UNK_LANG, kPlatformFMTowns, { 0x0000026D, 0x00002188, { { 0x7E, 0x3B, 0x06, 0x69, 0x11, 0x59, 0xBE, 0x42, 0xCB, 0x33, 0x9C, 0x15, 0xCF, 0x61, 0xF6, 0xB0 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x0000026C, 0x00002145, { { 0x95, 0xB7, 0x9E, 0x63, 0x99, 0xFA, 0x22, 0xBF, 0x62, 0x37, 0xC2, 0x2B, 0x40, 0x73, 0x53, 0x83 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1MalcolmTreeSeqProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000216, 0x000014FB, { { 0xBA, 0x6F, 0x63, 0xD5, 0x44, 0xCE, 0xE8, 0x20, 0xD4, 0x4C, 0x06, 0x58, 0x21, 0x8E, 0x07, 0x8B } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000230, 0x0000192A, { { 0x28, 0xCC, 0x89, 0x40, 0x8A, 0xF7, 0xCB, 0xC0, 0x11, 0x8F, 0x0F, 0xE5, 0x5F, 0x24, 0x2D, 0x32 } } } }, // CD + + { UNK_LANG, kPlatformAmiga, { 0x00000214, 0x000014C4, { { 0xA2, 0x60, 0x16, 0x14, 0x20, 0xE4, 0x8D, 0x89, 0xC4, 0x30, 0x07, 0x21, 0xC9, 0x26, 0xA6, 0x84 } } } }, + + { UNK_LANG, kPlatformFMTowns, { 0x00000218, 0x00001551, { { 0x30, 0x42, 0xD3, 0x7D, 0x6B, 0x43, 0x3B, 0xC7, 0x63, 0x56, 0x7D, 0x12, 0xE0, 0x53, 0x41, 0x48 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x00000217, 0x0000150E, { { 0x41, 0xFC, 0xD3, 0xAC, 0x8D, 0x1C, 0x11, 0x4E, 0xE0, 0x0C, 0xF6, 0x93, 0xA9, 0x22, 0x53, 0x7F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1WestwoodLogoSeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000004B, 0x000002FE, { { 0x6E, 0xDA, 0x5D, 0x1E, 0xF4, 0x38, 0xAE, 0x7A, 0x9F, 0xBC, 0x00, 0x7C, 0x77, 0x9D, 0x03, 0xAF } } } }, + { UNK_LANG, kPlatformPC, { 0x0000004B, 0x0000032A, { { 0x9A, 0x54, 0x6F, 0x6C, 0x70, 0xD1, 0x02, 0x94, 0xD1, 0xA1, 0xA7, 0xBE, 0x1B, 0x10, 0xBD, 0x2F } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x00000044, 0x00000243, { { 0x00, 0x11, 0x10, 0x64, 0x60, 0xE8, 0xB5, 0x59, 0x00, 0x60, 0xF5, 0x10, 0xB5, 0x63, 0x9D, 0x55 } } } }, // demo + + { UNK_LANG, kPlatformAmiga, { 0x0000004D, 0x00000319, { { 0xE9, 0x5D, 0xD4, 0x60, 0x4E, 0xA6, 0x92, 0x30, 0x9C, 0x77, 0x99, 0xBC, 0xB1, 0x97, 0xFB, 0xBD } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Demo1SeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000026, 0x0000016E, { { 0x61, 0xF2, 0x84, 0x42, 0x89, 0x6E, 0xB8, 0x0D, 0x01, 0xB7, 0xE4, 0x49, 0xA1, 0x72, 0xDC, 0x66 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Demo2SeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000023, 0x00000151, { { 0xE7, 0x9F, 0xA7, 0x80, 0xE3, 0xC1, 0x63, 0xF2, 0x3F, 0x7B, 0x64, 0xD9, 0x70, 0x3A, 0xF1, 0x55 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Demo3SeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000059, 0x000001A8, { { 0x9E, 0x90, 0x4F, 0x9E, 0xBC, 0x39, 0x37, 0xD1, 0x10, 0x67, 0x8C, 0xE5, 0x84, 0xFD, 0xD9, 0x7C } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Demo4SeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000020, 0x0000013E, { { 0xB7, 0x67, 0x1D, 0x50, 0x11, 0xD0, 0x16, 0x91, 0x40, 0x40, 0xD1, 0xC0, 0xA0, 0x79, 0x3D, 0xCE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1AmuleteAnimSeqProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002A, 0x0000025D, { { 0xB1, 0x59, 0x3C, 0x9A, 0x61, 0xC0, 0x1D, 0x80, 0xB5, 0x0C, 0x2E, 0xF9, 0xF6, 0x36, 0xED, 0x7D } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1OutroReunionSeqProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000547, 0x0000781C, { { 0xCF, 0xD6, 0x1D, 0x3D, 0x14, 0x40, 0x88, 0x35, 0x36, 0x4F, 0x0B, 0x1F, 0x9A, 0x1C, 0x3D, 0xAC } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x000005E5, 0x00008918, { { 0x6A, 0x33, 0x8C, 0xB0, 0x16, 0x57, 0x2D, 0xEB, 0xB2, 0xE1, 0x64, 0x80, 0x98, 0x99, 0x98, 0x19 } } } }, // CD + + { UNK_LANG, kPlatformAmiga, { 0x0000054A, 0x0000785F, { { 0x55, 0xEA, 0xB8, 0x7F, 0x3A, 0x86, 0xCD, 0xA6, 0xBC, 0xA7, 0x9A, 0x39, 0xED, 0xF5, 0x30, 0x0A } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x00000547, 0x00007876, { { 0x7A, 0xC7, 0x80, 0x34, 0x7A, 0x1B, 0xAB, 0xF8, 0xA7, 0x2F, 0x63, 0x3C, 0xDA, 0x89, 0x3F, 0x82 } } } }, // some floppy DOS + FM-TOWNS + + { UNK_LANG, kPlatformPC98, { 0x00000548, 0x00007889, { { 0x17, 0xE9, 0x40, 0xBA, 0x4A, 0xBD, 0xC6, 0x62, 0x56, 0x96, 0xD6, 0x1B, 0x11, 0xF3, 0xD8, 0x14 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1IntroCPSStringsProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00000015, 0x0000071D, { { 0x59, 0x65, 0x08, 0xF9, 0x4C, 0x81, 0xA1, 0xE3, 0x68, 0xF7, 0xE3, 0xF6, 0x33, 0x5F, 0xF5, 0x36 } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x00000014, 0x0000071D, { { 0xBA, 0xB6, 0x58, 0xB3, 0x28, 0x5E, 0x9F, 0x77, 0x69, 0x9D, 0x77, 0x53, 0x9D, 0x0D, 0xB0, 0x29 } } } }, // floppy + PC98 + { UNK_LANG, kPlatformPC, { 0x00000015, 0x00000786, { { 0xCF, 0x09, 0xE1, 0xD9, 0x8E, 0x34, 0x5D, 0xEA, 0xBC, 0xAC, 0xC4, 0xF4, 0x4A, 0xEC, 0xFF, 0xC1 } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x0000000C, 0x00000413, { { 0xA1, 0xE3, 0x06, 0x53, 0x23, 0x9A, 0xE0, 0xF1, 0xE4, 0xFD, 0xD9, 0x05, 0x22, 0xA6, 0x28, 0x46 } } } }, // demo + + { UNK_LANG, kPlatformAmiga, { 0x00000016, 0x0000070A, { { 0xD9, 0xDB, 0x91, 0xCD, 0x93, 0x81, 0xC4, 0x3F, 0x14, 0xF1, 0xC5, 0x02, 0xE7, 0x3F, 0x3A, 0x6C } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1IntroCOLStringsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x00000F09, { { 0x05, 0x7B, 0x69, 0xB7, 0x6A, 0xC3, 0x7F, 0xD9, 0x7E, 0x51, 0x87, 0xA5, 0x31, 0xD8, 0x80, 0xB3 } } } }, + { UNK_LANG, kPlatformUnknown, { 0x0000002B, 0x00000F09, { { 0x01, 0x40, 0x65, 0xC1, 0x33, 0xAA, 0x64, 0xA7, 0x44, 0xD5, 0x89, 0x68, 0x17, 0x47, 0xC7, 0x1D } } } }, // floppy(?) + PC98 + { UNK_LANG, kPlatformPC, { 0x00000046, 0x0000174F, { { 0xAA, 0x59, 0x01, 0x20, 0x06, 0xB4, 0x80, 0xC0, 0x84, 0x38, 0xFD, 0x97, 0xBF, 0x78, 0xDD, 0x78 } } } }, // demo + + { UNK_LANG, kPlatformAmiga, { 0x0000002E, 0x00000F09, { { 0x2A, 0x42, 0xB8, 0x4E, 0xC6, 0xF0, 0x5F, 0x4A, 0x08, 0xB4, 0xE3, 0xE5, 0xBD, 0x32, 0x11, 0x06 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1IntroWSAStringsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000093, 0x00002E5D, { { 0xAB, 0xD1, 0x32, 0x89, 0x2A, 0x8D, 0xC0, 0x2C, 0x87, 0x87, 0xA3, 0x14, 0x2A, 0x2A, 0x22, 0x7F } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x00000086, 0x00002E5D, { { 0xD2, 0x8D, 0x62, 0xEF, 0xEB, 0x75, 0x04, 0x13, 0x64, 0x85, 0x6B, 0x6C, 0xE8, 0x6C, 0xCF, 0x52 } } } }, + { UNK_LANG, kPlatformPC, { 0x0000004D, 0x00001AEC, { { 0x15, 0xBC, 0x8C, 0xD9, 0x33, 0x0C, 0xC5, 0x66, 0x87, 0x3B, 0x76, 0xEE, 0x0C, 0x41, 0x4D, 0x1F } } } }, // demo + + { UNK_LANG, kPlatformUnknown, { 0x00000080, 0x00002E5D, { { 0x67, 0x03, 0x20, 0xDF, 0xAA, 0x3C, 0x6A, 0xB5, 0x45, 0xD0, 0x00, 0x2B, 0x30, 0xCC, 0x36, 0xB6 } } } }, // Amiga + CD Demo + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1IntroStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x000004F5, 0x0001A7B1, { { 0xC7, 0x65, 0x5B, 0x5A, 0x56, 0x43, 0x94, 0x55, 0x5B, 0x00, 0xFD, 0x5D, 0xF4, 0xB5, 0x04, 0x15 } } } }, // floppy + { EN_ANY, kPlatformPC, { 0x000004F6, 0x0001A7B1, { { 0xDE, 0x41, 0xB1, 0x98, 0xD5, 0xAD, 0x6B, 0xBA, 0x33, 0x04, 0x19, 0x5D, 0xCC, 0x07, 0xB5, 0x56 } } } }, // CD + { EN_ANY, kPlatformPC, { 0x000002FA, 0x00010181, { { 0x48, 0xD3, 0x1B, 0x8E, 0x8D, 0xBC, 0x1F, 0x51, 0x35, 0x71, 0xE2, 0xAB, 0xC8, 0xBE, 0xFC, 0x88 } } } }, // demo + + { FR_FRA, kPlatformPC, { 0x000005EF, 0x000207E6, { { 0xDC, 0x6C, 0x9A, 0x7C, 0x19, 0x45, 0x2B, 0x25, 0x84, 0xCC, 0xE1, 0x40, 0xFE, 0x8E, 0xF4, 0x51 } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x000005F0, 0x000207E6, { { 0xB8, 0x51, 0xEA, 0x44, 0x64, 0x04, 0xE4, 0x6A, 0x7B, 0xBD, 0x31, 0x62, 0xC0, 0xDD, 0xEA, 0xEF } } } }, // CD + + { DE_DEU, kPlatformPC, { 0x00000605, 0x000212AB, { { 0x8F, 0x3A, 0x9D, 0x9A, 0x81, 0xF2, 0x4A, 0x90, 0xBC, 0xBD, 0x62, 0x8B, 0xD8, 0xD6, 0xF4, 0x5D } } } }, // floppy + { DE_DEU, kPlatformPC, { 0x00000606, 0x000212AB, { { 0xB0, 0x78, 0x86, 0xFB, 0xCB, 0x3D, 0x1E, 0x1E, 0x86, 0xE7, 0x2C, 0x2B, 0x3A, 0x3C, 0x6F, 0x1C } } } }, // CD + + { IT_ITA, kPlatformPC, { 0x0000057C, 0x0001DF02, { { 0x4B, 0x09, 0xBC, 0xBC, 0xB3, 0x3C, 0x69, 0xEB, 0xA6, 0xB5, 0x76, 0xED, 0xC7, 0x57, 0x71, 0xB0 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x000005F0, 0x0001CF13, { { 0x4F, 0xA0, 0x47, 0x57, 0x6D, 0x2D, 0xA6, 0x62, 0x06, 0xBE, 0x86, 0xD2, 0xD7, 0xEA, 0x2E, 0xD6 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x000005CF, 0x00020415, { { 0xCC, 0xE5, 0x9F, 0xB8, 0xCA, 0xFA, 0x2D, 0x05, 0xB8, 0xAF, 0x9F, 0x1F, 0x8A, 0xA8, 0x56, 0xDE } } } }, + + { EN_ANY, kPlatformAmiga, { 0x0000050A, 0x0001A7B1, { { 0x1B, 0x74, 0x71, 0x4C, 0xAB, 0x81, 0x10, 0x59, 0x8A, 0x21, 0x50, 0xBB, 0xFE, 0x6F, 0xD0, 0xE8 } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000626, 0x00021319, { { 0x80, 0x55, 0x54, 0x14, 0x5D, 0x6F, 0x49, 0x04, 0x4A, 0xEF, 0x92, 0xB8, 0x5B, 0x01, 0x0F, 0x97 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x00000545, 0x0001A84C, { { 0xEF, 0xE2, 0xE4, 0x92, 0xE1, 0x18, 0xF8, 0x3C, 0x91, 0x29, 0x4D, 0x82, 0xA4, 0x3E, 0xE6, 0x7D } } } }, + { JA_JPN, kPlatformFMTowns, { 0x000005FB, 0x0003163E, { { 0x16, 0x28, 0x83, 0xCE, 0x29, 0x94, 0x9F, 0x82, 0xDC, 0xD4, 0x06, 0xE8, 0x67, 0xC9, 0x56, 0x29 } } } }, + + { JA_JPN, kPlatformPC98, { 0x000005D0, 0x00032AD7, { { 0xEE, 0x36, 0x93, 0xDD, 0x71, 0x02, 0xE9, 0x0D, 0x54, 0xDE, 0xB6, 0xE1, 0x09, 0x59, 0x60, 0x64 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1OutroHomeStringProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000005, 0x00000189, { { 0xA5, 0xF3, 0x03, 0x3F, 0x43, 0x2B, 0x77, 0xCC, 0x5C, 0x96, 0x64, 0xB1, 0x75, 0xB5, 0x3E, 0xF6 } } } }, + + { JA_JPN, kPlatformUnknown, { 0x00000007, 0x000003E8, { { 0x68, 0x35, 0x87, 0x53, 0xD9, 0x53, 0x1F, 0x13, 0x24, 0x61, 0x0D, 0x8D, 0x33, 0x91, 0xF3, 0x47 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000007, 0x00000267, { { 0xD0, 0xC1, 0x11, 0x49, 0x3D, 0x3F, 0xCE, 0x84, 0x8F, 0xEF, 0xE3, 0xFD, 0x43, 0xCA, 0x92, 0xB0 } } } }, + + { DE_DEU, kPlatformUnknown, { 0x0000000E, 0x00000473, { { 0xB6, 0xEB, 0xE8, 0x22, 0x67, 0x24, 0xA9, 0xA3, 0x94, 0x55, 0xC6, 0x57, 0x17, 0x15, 0x5B, 0x04 } } } }, + + { ES_ESP, kPlatformPC, { 0x00000005, 0x00000178, { { 0x2E, 0x9C, 0x94, 0x0F, 0x29, 0x77, 0x27, 0x1D, 0x77, 0x1E, 0x5A, 0xF8, 0x0E, 0x8D, 0x09, 0x6B } } } }, + { IT_ITA, kPlatformPC, { 0x00000005, 0x00000178, { { 0x2E, 0x9C, 0x94, 0x0F, 0x29, 0x77, 0x27, 0x1D, 0x77, 0x1E, 0x5A, 0xF8, 0x0E, 0x8D, 0x09, 0x6B } } } }, + + { IT_ITA, kPlatformPC, { 0x00000007, 0x000001B8, { { 0x17, 0x95, 0x5B, 0x4F, 0xE2, 0x07, 0x5A, 0x49, 0xFA, 0xCE, 0x53, 0x8B, 0xE7, 0x46, 0x69, 0xC7 } } } }, // (fan) CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1RoomFilenamesProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x0000034C, 0x0000B7AA, { { 0x7C, 0x1B, 0x89, 0x09, 0xF0, 0x87, 0x3C, 0x64, 0x3D, 0x0E, 0x61, 0xCC, 0x09, 0x8D, 0xC9, 0x95 } } } }, + { UNK_LANG, kPlatformUnknown, { 0x000002DC, 0x0000B7AA, { { 0x31, 0x56, 0x41, 0x69, 0x1E, 0x84, 0x54, 0x2C, 0xF7, 0x7B, 0x98, 0x25, 0xF3, 0x91, 0x56, 0xFD } } } }, // DOS + PC98 + + { UNK_LANG, kPlatformAmiga, { 0x00000308, 0x0000B7AA, { { 0x6D, 0xA4, 0xE8, 0x27, 0x68, 0x24, 0xCF, 0xAA, 0x30, 0x32, 0x71, 0x74, 0x36, 0x68, 0x82, 0x20 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1RoomListProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x000064E8, 0x0010312B, { { 0x94, 0x5C, 0x87, 0x35, 0x35, 0x6B, 0x3E, 0xBF, 0x55, 0x3D, 0xDB, 0xD9, 0xFB, 0x97, 0x27, 0x5D } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x00004DD6, 0x0010312B, { { 0xC6, 0xF0, 0xC4, 0x2C, 0x5A, 0xD7, 0x48, 0xE4, 0x41, 0x23, 0x65, 0x6D, 0xC8, 0xC7, 0xCE, 0xF5 } } } }, // DOS + PC98 + + { UNK_LANG, kPlatformAmiga, { 0x00004ECC, 0x0010312B, { { 0x9A, 0x91, 0xF1, 0x9C, 0x8A, 0x96, 0x1C, 0x7B, 0xB7, 0xE4, 0xF1, 0xE9, 0x7D, 0xEF, 0x40, 0xBF } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1CharacterImageFilenamesProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x000000F7, 0x00003A8F, { { 0x1F, 0xAB, 0x8E, 0x5F, 0xAD, 0x76, 0x57, 0x37, 0xD7, 0x9B, 0x3F, 0x35, 0x4B, 0xA0, 0x98, 0x37 } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x000000E4, 0x00003A8F, { { 0x7A, 0x77, 0x6D, 0x26, 0xC8, 0x43, 0xCB, 0x74, 0x46, 0x2E, 0x04, 0x22, 0x89, 0x27, 0x33, 0x06 } } } }, // DOS + PC98 + + { UNK_LANG, kPlatformAmiga, { 0x000000F0, 0x00003A8F, { { 0xC0, 0xD9, 0x8C, 0x2B, 0x65, 0x51, 0x7C, 0x13, 0x52, 0x7E, 0xF7, 0x63, 0xA6, 0xA9, 0xCE, 0x40 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1AudioTracksProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000041, 0x00000FBF, { { 0xB5, 0xA2, 0x90, 0xE9, 0x73, 0x83, 0x47, 0x5A, 0xB3, 0x3E, 0x04, 0xBB, 0xAA, 0xC8, 0x84, 0x53 } } } }, + + { UNK_LANG, kPlatformFMTowns, { 0x0000005D, 0x0000154E, { { 0xA7, 0x7E, 0x03, 0x0A, 0x81, 0x54, 0xD2, 0x5D, 0x7B, 0x33, 0x07, 0xBF, 0x70, 0x01, 0x4B, 0x79 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1AudioTracksIntroProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000006, 0x0000022C, { { 0x5F, 0xC9, 0xE1, 0x4B, 0x34, 0x52, 0xB9, 0xF8, 0xFF, 0x37, 0x8B, 0xF4, 0xEF, 0x5E, 0xC5, 0xDA } } } }, // floppy + demo + { UNK_LANG, kPlatformUnknown, { 0x0000000C, 0x00000458, { { 0xEB, 0xB3, 0x96, 0xA5, 0x07, 0xE6, 0x11, 0x58, 0xDB, 0x3F, 0x34, 0x30, 0xFB, 0x7B, 0x92, 0xC8 } } } }, // CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1ItemNamesProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000468, 0x00018B13, { { 0xCE, 0xFE, 0x19, 0x5D, 0x3F, 0xD7, 0x2A, 0xF6, 0xD0, 0xC5, 0xBC, 0x17, 0x6A, 0x52, 0xDB, 0xFE } } } }, + + { FR_FRA, kPlatformPC, { 0x00000506, 0x0001C3CC, { { 0x46, 0xD4, 0x19, 0x04, 0x2A, 0x46, 0xCD, 0x63, 0x41, 0x5A, 0x8E, 0xA8, 0x00, 0xDD, 0x02, 0x77 } } } }, + + { DE_DEU, kPlatformPC, { 0x00000512, 0x0001DD2C, { { 0x5D, 0xB0, 0x6B, 0x8E, 0x9C, 0x70, 0x09, 0x90, 0x3C, 0xC6, 0x58, 0x1F, 0x71, 0x24, 0x76, 0x56 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000591, 0x0001F869, { { 0x4D, 0xD7, 0x66, 0xBB, 0x9A, 0xD8, 0x79, 0x1E, 0x92, 0x2B, 0xE5, 0xC2, 0x0F, 0x02, 0x0B, 0x35 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000506, 0x0001C1D9, { { 0xF2, 0x2D, 0x18, 0x13, 0x61, 0xFB, 0x57, 0x93, 0x5C, 0xDC, 0x79, 0x44, 0x96, 0x01, 0xA6, 0x90 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000530, 0x0001D90A, { { 0x52, 0xFB, 0xA8, 0x3F, 0xA3, 0x6F, 0xC2, 0x67, 0x55, 0x9F, 0x66, 0x9F, 0xFD, 0x79, 0x44, 0xDF } } } }, + + { EN_ANY, kPlatformAmiga, { 0x00000380, 0x00012960, { { 0x2D, 0x81, 0xCF, 0x7A, 0x9D, 0x71, 0x83, 0xB7, 0xE5, 0x00, 0xB0, 0x6E, 0x25, 0x94, 0xCB, 0xA4 } } } }, + { DE_DEU, kPlatformAmiga, { 0x000003E5, 0x0001607D, { { 0x6D, 0xBE, 0xAD, 0xE5, 0xD1, 0x41, 0x6C, 0x42, 0x71, 0x79, 0x9C, 0x78, 0x93, 0x84, 0xC8, 0x11 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x00000505, 0x00018B13, { { 0x62, 0x76, 0x84, 0x5D, 0x8D, 0xBA, 0x23, 0xC5, 0x67, 0x26, 0x22, 0xBD, 0xBE, 0x81, 0x2D, 0xFF } } } }, + { JA_JPN, kPlatformFMTowns, { 0x00000587, 0x000247A1, { { 0xE8, 0xCA, 0x1E, 0x34, 0x05, 0xE5, 0x08, 0xCA, 0xA7, 0xFE, 0x55, 0xCB, 0x75, 0xD0, 0xA7, 0x19 } } } }, + + { JA_JPN, kPlatformPC98, { 0x000004CF, 0x000247A1, { { 0xBE, 0x80, 0x3F, 0x10, 0xF7, 0x3A, 0x85, 0xD1, 0xE8, 0x24, 0xE6, 0x4E, 0x8F, 0x17, 0xC9, 0x2E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1TakenStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000010, 0x000004C2, { { 0x08, 0xC0, 0x66, 0xB1, 0x45, 0x04, 0x78, 0xF9, 0xAF, 0x0F, 0x52, 0xC8, 0x0E, 0x0C, 0x69, 0x86 } } } }, + + { FR_FRA, kPlatformPC, { 0x0000001E, 0x000008FA, { { 0xC9, 0xCC, 0x2E, 0x0B, 0xE4, 0xE0, 0x44, 0xBD, 0xC2, 0x10, 0x09, 0xA3, 0x36, 0xB1, 0x5D, 0x1C } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x0000000F, 0x0000047D, { { 0xE8, 0xB5, 0x15, 0xD5, 0x96, 0x81, 0xD2, 0x84, 0xAB, 0x33, 0xC1, 0x1C, 0x47, 0x1B, 0xFE, 0xDB } } } }, // CD + + { DE_DEU, kPlatformPC, { 0x0000001C, 0x000009C0, { { 0xA8, 0x64, 0xDD, 0x9D, 0x91, 0x42, 0x04, 0x26, 0xD0, 0x80, 0x40, 0xED, 0x08, 0x51, 0xC9, 0xBB } } } }, + + { IT_ITA, kPlatformPC, { 0x00000014, 0x00000588, { { 0x5B, 0x75, 0xAE, 0xD7, 0x50, 0x6C, 0x3E, 0x65, 0x5C, 0xF8, 0x84, 0x34, 0x48, 0x58, 0x0E, 0x6E } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000000F, 0x000002F0, { { 0x37, 0x22, 0x62, 0xE4, 0x1B, 0x1F, 0xD6, 0x9E, 0x94, 0xA3, 0x41, 0x00, 0xD5, 0x29, 0x28, 0x09 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000014, 0x000005D8, { { 0xD6, 0x00, 0x90, 0x6A, 0x75, 0x3B, 0xF1, 0xFE, 0xF4, 0x3E, 0x0E, 0x1D, 0x39, 0xEB, 0x2D, 0xC8 } } } }, + + { EN_ANY, kPlatformAmiga, { 0x00000008, 0x00000261, { { 0x93, 0x5B, 0x79, 0xE8, 0x89, 0x8E, 0xB5, 0x37, 0x39, 0x2A, 0xB0, 0x04, 0x98, 0x80, 0x5A, 0x4E } } } }, + { DE_DEU, kPlatformAmiga, { 0x0000000E, 0x000004E0, { { 0x52, 0x4D, 0x74, 0x91, 0x70, 0x0D, 0x4C, 0x40, 0x5C, 0x7E, 0xBA, 0xDA, 0x24, 0x49, 0xF3, 0x1A } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000001C, 0x00000AED, { { 0x32, 0xD2, 0x87, 0x67, 0x3D, 0x01, 0x50, 0xF3, 0xFA, 0x19, 0x7A, 0xB0, 0xF8, 0x6F, 0x8A, 0x07 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x0000001F, 0x00000EB7, { { 0x7F, 0x8C, 0xFF, 0x35, 0x30, 0x71, 0x9A, 0x78, 0xCC, 0x07, 0x11, 0x86, 0xE3, 0x0D, 0x16, 0xDF } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000016, 0x00000C56, { { 0x97, 0xF0, 0x57, 0xCC, 0x03, 0x06, 0x41, 0xDC, 0xFC, 0xD5, 0xA2, 0x35, 0x0C, 0x71, 0x37, 0xCC } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PlacedStringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000009, 0x000002B7, { { 0xE7, 0xCF, 0x8A, 0x19, 0xEF, 0x98, 0xE5, 0x74, 0x46, 0x46, 0x47, 0x65, 0xB6, 0x81, 0x70, 0x0A } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000000D, 0x0000074C, { { 0x0E, 0x1C, 0x1F, 0xD2, 0xCF, 0xBF, 0x40, 0xE1, 0x59, 0x0F, 0x1B, 0x46, 0xED, 0x8B, 0x96, 0x8E } } } }, + + { FR_FRA, kPlatformPC, { 0x00000011, 0x00000545, { { 0x05, 0xEF, 0x74, 0x54, 0x06, 0xB7, 0x64, 0x47, 0x21, 0x56, 0x55, 0x74, 0x70, 0x2D, 0xA8, 0x23 } } } }, + + { DE_DEU, kPlatformUnknown, { 0x0000000B, 0x00000389, { { 0xB9, 0x74, 0xBE, 0x63, 0xB4, 0xA4, 0x8A, 0x04, 0xD9, 0x50, 0x73, 0xB7, 0x01, 0x9E, 0x77, 0xD3 } } } }, + + { IT_ITA, kPlatformPC, { 0x0000000D, 0x0000040D, { { 0x9C, 0x71, 0x53, 0x35, 0xC3, 0xE8, 0x46, 0xB9, 0xD2, 0xFA, 0x1C, 0x8C, 0xC3, 0xFF, 0xBC, 0x1F } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000011, 0x000003B8, { { 0xC8, 0xA6, 0xE4, 0x8A, 0xF7, 0x4C, 0x3F, 0xA6, 0x24, 0x7F, 0xEF, 0xE4, 0x63, 0x8B, 0x72, 0xF3 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000000D, 0x00000439, { { 0x57, 0xAE, 0x1C, 0xC1, 0xF5, 0xE8, 0x5B, 0x9E, 0x90, 0x02, 0xB9, 0x8D, 0x86, 0x38, 0xFB, 0xA8 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1DroppedStringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000000A, 0x0000033C, { { 0x96, 0x63, 0xFD, 0x73, 0x71, 0xCC, 0x62, 0x59, 0x86, 0x02, 0x47, 0x55, 0x82, 0xF8, 0x5E, 0x1F } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000000B, 0x0000059F, { { 0xDD, 0x5E, 0x51, 0x7E, 0xD9, 0xFC, 0xCD, 0xAD, 0x6B, 0x93, 0x71, 0xBE, 0x83, 0x63, 0x3F, 0x88 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000011, 0x00000579, { { 0x3D, 0x0C, 0x3C, 0xAD, 0x2E, 0xE3, 0x7A, 0x5A, 0x4A, 0x21, 0x1C, 0x96, 0xC5, 0x5A, 0xA7, 0x9E } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000011, 0x00000612, { { 0xEC, 0xCD, 0x99, 0x58, 0xF7, 0x08, 0x92, 0x43, 0x95, 0x10, 0x6B, 0xDD, 0x61, 0xF7, 0x5C, 0xA4 } } } }, + + { IT_ITA, kPlatformPC, { 0x0000000B, 0x0000031B, { { 0x32, 0x0C, 0xCD, 0x83, 0xF6, 0x97, 0xC8, 0x76, 0x57, 0x6B, 0x7C, 0xAD, 0x51, 0xEB, 0x91, 0x1F } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000011, 0x000003B8, { { 0xC8, 0xA6, 0xE4, 0x8A, 0xF7, 0x4C, 0x3F, 0xA6, 0x24, 0x7F, 0xEF, 0xE4, 0x63, 0x8B, 0x72, 0xF3 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000008, 0x00000261, { { 0x1D, 0xB5, 0xFB, 0x23, 0x94, 0xA7, 0x86, 0x7A, 0xAC, 0x53, 0xDA, 0x6F, 0xCC, 0x41, 0x0F, 0xD7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1NoDropStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000047, 0x00001881, { { 0xEF, 0x81, 0x2B, 0x8F, 0x06, 0x0C, 0xA6, 0xBA, 0x50, 0x9C, 0x99, 0x40, 0x53, 0xFD, 0xC1, 0x55 } } } }, + + { FR_FRA, kPlatformPC, { 0x0000004C, 0x00001B39, { { 0xFF, 0xD5, 0x5D, 0x1C, 0xF1, 0x8A, 0xA4, 0x21, 0xB1, 0x56, 0x2B, 0xAC, 0x9F, 0x40, 0x30, 0x53 } } } }, + + { DE_DEU, kPlatformPC, { 0x0000004C, 0x00001AFF, { { 0xE5, 0x05, 0x79, 0x10, 0x91, 0x95, 0x64, 0x40, 0xB2, 0x73, 0x39, 0xFA, 0x50, 0x8D, 0xCE, 0x8A } } } }, + + { IT_ITA, kPlatformPC, { 0x00000045, 0x00001850, { { 0x50, 0x34, 0x82, 0xA9, 0x28, 0xDE, 0x44, 0xB3, 0x2D, 0x59, 0x0B, 0x7F, 0xCE, 0x42, 0x1F, 0x73 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000004C, 0x00001650, { { 0x42, 0x7A, 0x04, 0xCD, 0x69, 0xB1, 0x06, 0x9A, 0xD8, 0x7E, 0x7A, 0x14, 0x5B, 0x1C, 0x70, 0xB8 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000003D, 0x000015FA, { { 0x87, 0x2E, 0xE6, 0x8A, 0xF1, 0xC9, 0xC9, 0xEC, 0xD3, 0x2C, 0x25, 0x7E, 0x36, 0x02, 0xF7, 0xAC } } } }, + + { EN_ANY, kPlatformAmiga, { 0x00000048, 0x00001881, { { 0x69, 0xA8, 0x0B, 0x47, 0xFD, 0xA0, 0x94, 0x12, 0x82, 0x1D, 0xE0, 0x9C, 0xB1, 0x10, 0x6D, 0x11 } } } }, + { DE_DEU, kPlatformAmiga, { 0x0000004D, 0x00001AFF, { { 0xF8, 0x83, 0x2E, 0x08, 0x88, 0x7B, 0x72, 0x7F, 0x71, 0xD4, 0x05, 0xF3, 0x1A, 0x78, 0xF1, 0x9D } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000007A, 0x0000323C, { { 0x00, 0x7F, 0x8E, 0x2E, 0x7B, 0xFC, 0x06, 0x0B, 0x7A, 0x7F, 0x17, 0xAF, 0x47, 0x82, 0xC1, 0x16 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x00000061, 0x00002E9C, { { 0x8A, 0xFA, 0x43, 0x26, 0x68, 0x6D, 0x5A, 0x59, 0x0C, 0x9E, 0xCB, 0x28, 0x43, 0x33, 0x54, 0x49 } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000042, 0x000025C2, { { 0x6F, 0x34, 0x59, 0x17, 0x22, 0xCE, 0x1A, 0x82, 0x18, 0xE3, 0x9F, 0x86, 0x84, 0xF1, 0x8E, 0x0C } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PutDownStringProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000026, 0x00000D27, { { 0x83, 0x09, 0x51, 0xD3, 0x94, 0x2B, 0xB1, 0x8B, 0x8B, 0x16, 0xA9, 0xEB, 0xE8, 0xA2, 0x4F, 0x0C } } } }, + + { JA_JPN, kPlatformUnknown, { 0x00000029, 0x0000187D, { { 0xDE, 0xEE, 0x66, 0x88, 0x57, 0xF5, 0xF9, 0x2E, 0xD2, 0x14, 0xF5, 0x83, 0xA0, 0x0D, 0x96, 0x86 } } } }, + + { FR_FRA, kPlatformPC, { 0x0000002E, 0x0000101D, { { 0xBC, 0xEA, 0x6C, 0x1F, 0x31, 0xCF, 0x30, 0x26, 0x2D, 0x24, 0xC5, 0xEA, 0x97, 0x49, 0xDC, 0x4C } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000028, 0x00000E7E, { { 0x26, 0x93, 0x76, 0x37, 0x41, 0x2E, 0xF3, 0xED, 0xF5, 0x7B, 0xA7, 0xEB, 0x80, 0x61, 0x3B, 0x84 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000034, 0x0000131D, { { 0x36, 0x87, 0x4D, 0x73, 0x2A, 0x67, 0xBA, 0xCE, 0xCB, 0x33, 0x3C, 0x10, 0xCC, 0x3E, 0x7E, 0xAD } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000002E, 0x00000EB2, { { 0x14, 0x08, 0xE6, 0xD1, 0x54, 0x76, 0x2A, 0x9E, 0xBE, 0x5A, 0x15, 0xEB, 0x52, 0x01, 0x52, 0x97 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000002D, 0x00001052, { { 0x12, 0x0A, 0x23, 0x11, 0xDF, 0x8A, 0x59, 0xD4, 0xF2, 0xCA, 0xA5, 0xA7, 0x76, 0x1B, 0x54, 0xB6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1WaitAmuletStringProvider[] = { + { EN_ANY, kPlatformPC, { 0x0000003D, 0x0000150D, { { 0x11, 0xC8, 0x7E, 0x83, 0x7A, 0xC3, 0x5D, 0xD9, 0x72, 0xFC, 0x75, 0xCB, 0x57, 0xE9, 0xF1, 0x36 } } } }, + + { JA_JPN, kPlatformUnknown, { 0x00000029, 0x000017A7, { { 0xFD, 0xA3, 0xAD, 0x24, 0x16, 0x49, 0x22, 0x6F, 0x52, 0xE9, 0x50, 0x11, 0x51, 0x38, 0xCA, 0xE0 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000049, 0x00001ADD, { { 0xFD, 0xCF, 0x9C, 0xAD, 0xA2, 0xAA, 0x74, 0x11, 0x8E, 0x89, 0x02, 0xCB, 0x2B, 0x5B, 0x2B, 0x1C } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000048, 0x000019CF, { { 0x82, 0xDD, 0xBD, 0xA3, 0xD0, 0xE0, 0x19, 0xC0, 0x6D, 0xC5, 0xEE, 0x7A, 0x0B, 0x49, 0x06, 0xCE } } } }, + + { IT_ITA, kPlatformPC, { 0x0000004A, 0x00001B4C, { { 0x38, 0x26, 0x54, 0x10, 0x3D, 0x32, 0xCD, 0xAE, 0x3F, 0x96, 0xFE, 0x6F, 0x4A, 0x94, 0x72, 0xB0 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000049, 0x0000184F, { { 0x11, 0x42, 0xB2, 0xD6, 0x76, 0xEA, 0xF9, 0xCA, 0x46, 0xE4, 0xA6, 0x35, 0xE8, 0xB9, 0x8B, 0xE9 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000042, 0x000017FD, { { 0x0A, 0x8A, 0x7E, 0x9A, 0x5F, 0x4A, 0x35, 0x06, 0x4D, 0x6B, 0xBF, 0x29, 0x1B, 0xAD, 0xD8, 0x37 } } } }, + + { EN_ANY, kPlatformUnknown, { 0x0000003E, 0x0000150D, { { 0xA8, 0xBF, 0x99, 0x9B, 0xC1, 0x36, 0x21, 0x47, 0x6D, 0x99, 0x4F, 0x34, 0xE6, 0x61, 0x47, 0xFD } } } }, // Amiga + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1BlackJewelStringProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000023, 0x00000B73, { { 0xBE, 0xE9, 0xBD, 0x65, 0xB9, 0xB1, 0xCD, 0xF0, 0x45, 0x03, 0x01, 0x70, 0xBE, 0xD0, 0x0F, 0x80 } } } }, + + { JA_JPN, kPlatformUnknown, { 0x00000035, 0x0000205F, { { 0x33, 0xD6, 0x19, 0xEE, 0xEA, 0xDD, 0x9F, 0xB5, 0x77, 0x0C, 0x8E, 0x84, 0x5E, 0x61, 0x22, 0x3E } } } }, + + { FR_FRA, kPlatformPC, { 0x0000002B, 0x00000F11, { { 0x68, 0xA0, 0xA3, 0xA0, 0xB6, 0xD1, 0x40, 0x22, 0xB4, 0x10, 0x3D, 0x5A, 0x7F, 0x1F, 0x4B, 0xE7 } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000031, 0x0000113B, { { 0xA5, 0x00, 0xD1, 0xDC, 0x25, 0x99, 0x3E, 0x6B, 0xFF, 0xC8, 0x6C, 0xDA, 0xA4, 0xCF, 0x51, 0xD7 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000022, 0x00000B6E, { { 0xAE, 0xA0, 0xDF, 0x07, 0xDD, 0x88, 0x98, 0x6B, 0xDD, 0x9E, 0x2E, 0xC0, 0xBD, 0x45, 0x2E, 0x2B } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000002B, 0x00000D6D, { { 0x08, 0x5E, 0x1F, 0xA8, 0x8F, 0x1F, 0x6A, 0xE0, 0xF3, 0x49, 0xEF, 0x44, 0xA8, 0xCD, 0xDE, 0x45 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000025, 0x00000CF6, { { 0x4B, 0x13, 0x39, 0xCB, 0x3F, 0x44, 0x18, 0x46, 0x43, 0xDB, 0x94, 0xC5, 0x3E, 0x6B, 0xC4, 0x74 } } } }, + + { EN_ANY, kPlatformUnknown, { 0x00000024, 0x00000B73, { { 0x8D, 0x57, 0x5F, 0x93, 0x85, 0x75, 0xF2, 0xD8, 0x36, 0xC2, 0x7C, 0x0E, 0x3B, 0xEA, 0xE0, 0x0A } } } }, // Amiga + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PoisonGoneStringProvider[] = { + { EN_ANY, kPlatformPC, { 0x0000002D, 0x00000F59, { { 0x9A, 0x88, 0x07, 0x5A, 0x9C, 0xC3, 0x7B, 0xB0, 0x79, 0x69, 0xE0, 0x84, 0x11, 0x9B, 0x82, 0xCD } } } }, + + { FR_FRA, kPlatformPC, { 0x00000059, 0x00001E91, { { 0xDA, 0x9C, 0xC4, 0x7A, 0x79, 0x73, 0x60, 0xBF, 0x31, 0xF8, 0x8F, 0xAF, 0xC1, 0x4D, 0x25, 0xEC } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x0000002A, 0x00000EAA, { { 0x0B, 0x4E, 0xDF, 0x03, 0x9E, 0x64, 0x3B, 0x13, 0x10, 0x6A, 0xF9, 0x4C, 0x66, 0x0D, 0x09, 0xC5 } } } }, // (fan) CD + + { DE_DEU, kPlatformPC, { 0x00000036, 0x00001324, { { 0x30, 0x67, 0xEE, 0x7C, 0x4D, 0x36, 0xFE, 0x46, 0x05, 0x44, 0x23, 0xA1, 0xB4, 0x07, 0x16, 0xB5 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000034, 0x0000128D, { { 0x4E, 0x54, 0xFE, 0x58, 0x7F, 0x15, 0xFA, 0xC1, 0x50, 0xF8, 0x47, 0x29, 0x15, 0xE8, 0x83, 0xC7 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000002A, 0x00000DFD, { { 0x57, 0xDC, 0xE0, 0x45, 0x2E, 0x89, 0x77, 0x7F, 0x4B, 0x41, 0xCF, 0x4A, 0xFE, 0x0B, 0xAF, 0xC1 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000033, 0x0000127E, { { 0x67, 0xEB, 0xD3, 0x00, 0xF8, 0x4F, 0xF1, 0x79, 0x48, 0xE6, 0x9C, 0xB2, 0xA7, 0xCF, 0x76, 0x07 } } } }, + + { EN_ANY, kPlatformAmiga, { 0x0000002E, 0x00000F59, { { 0xAD, 0x95, 0xF3, 0xA7, 0xBB, 0x04, 0x08, 0x77, 0xD0, 0x71, 0xFC, 0x8B, 0x33, 0x2A, 0x6D, 0xD3 } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000037, 0x00001324, { { 0xB3, 0xE6, 0x0A, 0x49, 0x37, 0x73, 0x3C, 0xAF, 0x78, 0x9E, 0x7D, 0x13, 0x75, 0xAE, 0xA8, 0x89 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000003C, 0x000013B4, { { 0xE9, 0x54, 0xF1, 0xEC, 0x64, 0x5A, 0xEB, 0xC7, 0xAA, 0x7E, 0xA2, 0x9F, 0xE8, 0xFB, 0x3A, 0x82 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x0000003D, 0x000017D1, { { 0x7C, 0x93, 0x62, 0x32, 0x47, 0xB9, 0x78, 0x03, 0x86, 0x8D, 0x99, 0xB8, 0x86, 0x68, 0xEF, 0x3A } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000016, 0x00000B60, { { 0xFF, 0x8C, 0xC0, 0x1B, 0x2C, 0x0C, 0x23, 0x89, 0x93, 0x79, 0xC5, 0xCD, 0xAC, 0xF9, 0xEA, 0xA7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1HealingTipStringProvider[] = { + { EN_ANY, kPlatformPC, { 0x0000002D, 0x00000F04, { { 0xC0, 0xC7, 0x0C, 0x3D, 0xA7, 0x62, 0x14, 0xFB, 0xE8, 0x52, 0x05, 0x0D, 0xFE, 0xF6, 0xC7, 0x28 } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000002B, 0x00001949, { { 0xC7, 0xE3, 0x0A, 0x6B, 0x8F, 0xCA, 0xBC, 0x3A, 0xDC, 0x76, 0x48, 0xD3, 0x8B, 0xD9, 0x44, 0x2E } } } }, + + { FR_FRA, kPlatformPC, { 0x00000036, 0x0000132C, { { 0x86, 0x65, 0x80, 0x10, 0x40, 0x32, 0x6C, 0x2F, 0x5E, 0x76, 0xFB, 0xDC, 0x19, 0x33, 0x02, 0x3C } } } }, + + { DE_DEU, kPlatformUnknown, { 0x0000003C, 0x00001537, { { 0x78, 0xC2, 0x76, 0x24, 0x0D, 0x1F, 0xC0, 0x13, 0x4E, 0x34, 0x0A, 0x50, 0x4C, 0x35, 0x7E, 0xB1 } } } }, + + { IT_ITA, kPlatformPC, { 0x0000003F, 0x0000170E, { { 0x0B, 0x37, 0xA4, 0x5E, 0x05, 0x4A, 0x96, 0x1F, 0x2E, 0x02, 0x43, 0xBE, 0xCC, 0xF9, 0x21, 0x5E } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000036, 0x00001364, { { 0x59, 0x70, 0x13, 0x8D, 0x93, 0x9C, 0x1B, 0x69, 0x2F, 0x13, 0x9A, 0xB2, 0x4C, 0x97, 0x7E, 0x95 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000028, 0x00000E0F, { { 0x3E, 0x40, 0xCA, 0x2A, 0x5F, 0xFE, 0x74, 0x30, 0x8C, 0x31, 0x41, 0x09, 0xBD, 0xFD, 0xA3, 0x7E } } } }, + + { EN_ANY, kPlatformUnknown, { 0x0000002E, 0x00000F04, { { 0x95, 0x39, 0x36, 0x89, 0xC4, 0x60, 0x7C, 0x0C, 0xDC, 0x06, 0xF7, 0x86, 0x1A, 0xF7, 0x93, 0x2B } } } }, // Amiga + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1WispJewelStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000053, 0x00001C62, { { 0x9A, 0xF1, 0xCC, 0xB3, 0x09, 0xF0, 0x9C, 0x33, 0x0E, 0xF0, 0xE3, 0xF8, 0x24, 0x63, 0x40, 0x95 } } } }, // floppy + { EN_ANY, kPlatformPC, { 0x00000052, 0x00001CE8, { { 0x6D, 0x69, 0x6D, 0x15, 0x4F, 0xF1, 0xD8, 0xA6, 0x53, 0x9F, 0xE3, 0x77, 0x75, 0x25, 0xE7, 0x93 } } } }, // CD + + { FR_FRA, kPlatformPC, { 0x0000005B, 0x00001E9A, { { 0xC1, 0x26, 0xF3, 0x64, 0x18, 0x7D, 0xF7, 0x5A, 0xB6, 0x2B, 0x44, 0x57, 0xDC, 0x60, 0x20, 0x3C } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x00000050, 0x00001B8D, { { 0x9A, 0xCE, 0x1D, 0x62, 0xFA, 0xC6, 0x73, 0x80, 0x02, 0x0A, 0x61, 0x24, 0xDC, 0x2A, 0xEF, 0xE6 } } } }, // CD + + { DE_DEU, kPlatformPC, { 0x00000061, 0x00002184, { { 0x4B, 0x20, 0xD7, 0xE6, 0x00, 0xBF, 0x32, 0x40, 0xB7, 0xD0, 0xD6, 0xEC, 0x9C, 0x0F, 0x0B, 0xF0 } } } }, // floppy + { DE_DEU, kPlatformPC, { 0x00000058, 0x00001E88, { { 0x0E, 0x14, 0xD1, 0xF3, 0x03, 0x29, 0x48, 0x1D, 0x32, 0x2A, 0xBB, 0x0B, 0x48, 0xB3, 0x2E, 0x47 } } } }, // CD + + { IT_ITA, kPlatformPC, { 0x00000074, 0x00002945, { { 0x17, 0x8B, 0x7E, 0xD9, 0x04, 0x7C, 0xD4, 0x9D, 0xCE, 0xF0, 0x79, 0x00, 0xAC, 0x82, 0x7C, 0x82 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000050, 0x00001A10, { { 0xFB, 0x79, 0x74, 0x14, 0xB9, 0x75, 0x4F, 0x44, 0x83, 0xB1, 0xD4, 0xBE, 0x17, 0x0F, 0xC4, 0xD6 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000005F, 0x0000211E, { { 0xE7, 0x0A, 0x85, 0x25, 0x44, 0x41, 0x47, 0x3B, 0x7A, 0xA6, 0x62, 0xAE, 0xAE, 0xD5, 0x92, 0x45 } } } }, + + { EN_ANY, kPlatformAmiga, { 0x00000056, 0x00001C62, { { 0x43, 0x28, 0x3C, 0x0F, 0x78, 0x52, 0xE7, 0x2A, 0x77, 0xF3, 0x21, 0x5A, 0xF0, 0xFC, 0x9E, 0xF8 } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000063, 0x00002184, { { 0x6B, 0xDC, 0x6B, 0xCF, 0xD4, 0xC7, 0x2A, 0x9A, 0x2E, 0x34, 0x71, 0x4E, 0xB7, 0xF6, 0xAF, 0xDA } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x00000075, 0x00002B94, { { 0xA5, 0x4C, 0xBF, 0x5F, 0xD3, 0xF8, 0x6D, 0xE4, 0xB4, 0x8E, 0x64, 0x84, 0xD9, 0xBA, 0x2B, 0x33 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x00000067, 0x00002C6B, { { 0x55, 0x56, 0x6B, 0xEA, 0xEF, 0x34, 0xDA, 0x23, 0x23, 0xF4, 0x9D, 0x0F, 0xBF, 0xC3, 0x1F, 0xDA } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000037, 0x00001EDF, { { 0xA8, 0x42, 0x79, 0xEB, 0x82, 0xAF, 0x03, 0xD7, 0x03, 0xF9, 0xE0, 0x60, 0xD4, 0x87, 0xAD, 0x2E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1MagicJewelStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000013, 0x0000069E, { { 0x7C, 0xF2, 0xEE, 0x7C, 0x8A, 0xCE, 0x5B, 0x09, 0x32, 0xDC, 0x31, 0x1F, 0x45, 0x21, 0x84, 0xFF } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000000F, 0x0000087E, { { 0xD8, 0xF1, 0x40, 0x9D, 0x9C, 0x15, 0x9E, 0xBD, 0x69, 0xE5, 0xE1, 0x51, 0x34, 0x22, 0xF3, 0x75 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000011, 0x000005DB, { { 0x44, 0x99, 0x35, 0x77, 0x9B, 0x3D, 0xF8, 0xAF, 0x7A, 0xA6, 0x14, 0xD0, 0x99, 0xC6, 0x80, 0x7B } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000014, 0x000006EF, { { 0xDE, 0x77, 0xB6, 0x8C, 0x39, 0x5C, 0x6F, 0xDF, 0x7D, 0x04, 0x0F, 0x65, 0x24, 0x75, 0xED, 0x95 } } } }, + + { IT_ITA, kPlatformPC, { 0x0000001D, 0x00000A83, { { 0x60, 0x69, 0x18, 0x6C, 0x34, 0xB0, 0x56, 0xE3, 0x06, 0x7C, 0xB1, 0xDD, 0x26, 0x80, 0xAE, 0x30 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000011, 0x000005E4, { { 0xD5, 0x11, 0xDA, 0x40, 0x09, 0x6A, 0x5D, 0x76, 0x5C, 0x20, 0xC4, 0x43, 0x4D, 0xF3, 0x67, 0xF0 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000011, 0x000005CD, { { 0x32, 0x2A, 0xFF, 0x9F, 0x10, 0x75, 0x6B, 0xD6, 0x46, 0xAE, 0x55, 0xD3, 0x68, 0x4F, 0xBB, 0x5A } } } }, + + { EN_ANY, kPlatformUnknown, { 0x00000014, 0x0000069E, { { 0x6A, 0x1C, 0x9B, 0x85, 0x61, 0xC7, 0x28, 0xA9, 0xA3, 0xF4, 0xFA, 0x47, 0x90, 0x8F, 0x06, 0xB4 } } } }, // Amiga + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1ThePoisonStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000057, 0x00001C24, { { 0xBC, 0x31, 0x5C, 0x25, 0x50, 0x36, 0x58, 0x20, 0x55, 0xFC, 0x75, 0x47, 0x2D, 0x43, 0x73, 0x78 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000068, 0x000022D8, { { 0x39, 0xDA, 0xB3, 0xD2, 0xDA, 0x3F, 0xAB, 0x40, 0x1A, 0x4F, 0x9D, 0x02, 0xBA, 0x37, 0xEC, 0x4D } } } }, + + { DE_DEU, kPlatformPC, { 0x00000072, 0x00002690, { { 0xEF, 0x62, 0x85, 0xA3, 0x8B, 0x20, 0x4B, 0x65, 0xF8, 0xE7, 0x2C, 0x02, 0x3F, 0x3F, 0x25, 0x65 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000063, 0x000021F8, { { 0x3C, 0x2E, 0xF8, 0xAD, 0xCF, 0xB5, 0xE7, 0x2C, 0x98, 0x7A, 0xB9, 0x6F, 0x7A, 0x42, 0xE1, 0x92 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000068, 0x00002077, { { 0x5D, 0xF4, 0xF9, 0xD9, 0x87, 0x34, 0x14, 0xAB, 0xE4, 0x9A, 0x67, 0xAF, 0x18, 0x8B, 0x40, 0x98 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000059, 0x00001DF7, { { 0x16, 0x7B, 0x5F, 0x91, 0x06, 0x5B, 0xFC, 0x9C, 0x88, 0x61, 0xCC, 0x1B, 0x52, 0x4F, 0x91, 0xC5 } } } }, + + { EN_ANY, kPlatformAmiga, { 0x00000058, 0x00001C24, { { 0xBA, 0x1F, 0xBD, 0x5C, 0x85, 0x3D, 0x3C, 0x92, 0xD1, 0x13, 0xF3, 0x40, 0x2E, 0xBB, 0x1C, 0xE2 } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000073, 0x00002690, { { 0x44, 0xAE, 0xC9, 0xFD, 0x9F, 0x8E, 0x1B, 0xDD, 0x3F, 0xE4, 0x4D, 0x4B, 0x5A, 0x13, 0xE5, 0x99 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x00000092, 0x0000334E, { { 0xC9, 0x02, 0xB5, 0xEF, 0x90, 0xA8, 0x9C, 0x6E, 0xAD, 0xD6, 0x1F, 0xCC, 0x71, 0x9F, 0x19, 0x2C } } } }, + { JA_JPN, kPlatformFMTowns, { 0x000000A0, 0x00003EEB, { { 0x4B, 0x0C, 0xD5, 0xF0, 0xFE, 0x05, 0xF5, 0x09, 0x96, 0xA9, 0xE4, 0xDD, 0x86, 0x8D, 0x79, 0x3C } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000045, 0x00002350, { { 0xAD, 0x17, 0xA0, 0x40, 0x86, 0x0E, 0x1D, 0x2F, 0xA7, 0x14, 0x5B, 0x81, 0x38, 0x09, 0x80, 0x21 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1FluteStringsProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000003C, 0x00001599, { { 0x96, 0x72, 0x5A, 0x8A, 0xA0, 0xEE, 0xA2, 0xCE, 0x4D, 0x21, 0x01, 0x6C, 0xC5, 0x1A, 0xEB, 0x21 } } } }, // floppy + AMIGA + { EN_ANY, kPlatformPC, { 0x0000009C, 0x00002334, { { 0xA8, 0xA3, 0x1F, 0x0D, 0x36, 0x25, 0x19, 0x98, 0x50, 0xA0, 0x13, 0x65, 0xF4, 0xE8, 0x27, 0x19 } } } }, // CD + + { FR_FRA, kPlatformPC, { 0x00000045, 0x000018EE, { { 0x3E, 0x3B, 0x20, 0x46, 0xEB, 0xB0, 0x88, 0x26, 0xB2, 0x0D, 0xD6, 0x8F, 0xF7, 0x53, 0x74, 0xAE } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000040, 0x000016F2, { { 0x70, 0xFF, 0x86, 0x73, 0x9E, 0x75, 0xDD, 0x17, 0x27, 0x86, 0x44, 0xE9, 0x78, 0x3D, 0x48, 0xDB } } } }, + + { IT_ITA, kPlatformPC, { 0x0000004C, 0x00001BFB, { { 0x06, 0x4F, 0x6A, 0x37, 0x8B, 0x44, 0x27, 0x26, 0xCE, 0x28, 0xB2, 0x47, 0x71, 0xE2, 0x27, 0x73 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000045, 0x00001726, { { 0x5A, 0xCF, 0x64, 0x4B, 0x61, 0x57, 0xEC, 0xB3, 0xBF, 0x32, 0x45, 0x51, 0x5D, 0x02, 0xC5, 0xB6 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000052, 0x00001D8E, { { 0x9D, 0xA5, 0xF1, 0x42, 0xD1, 0x48, 0xEB, 0x8F, 0x4B, 0xDC, 0xD9, 0x10, 0x55, 0xBD, 0x12, 0xBB } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000005A, 0x000024F9, { { 0xCA, 0x1F, 0x62, 0x23, 0x22, 0x25, 0x4A, 0x94, 0x8A, 0x50, 0x59, 0xD5, 0xB4, 0x4E, 0xF1, 0xA6 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x00000053, 0x00002745, { { 0x7A, 0xBB, 0xFC, 0x30, 0xB6, 0xCE, 0x61, 0xD4, 0xDB, 0xB0, 0xE6, 0xB2, 0xF4, 0x4D, 0x81, 0x35 } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000032, 0x00001CDF, { { 0xB7, 0x08, 0x8D, 0x67, 0xB2, 0x0F, 0x59, 0x2D, 0xA6, 0x36, 0x21, 0x7B, 0x8B, 0x89, 0xE3, 0xED } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1FlaskFullStringProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x0000001C, 0x000009C8, { { 0xA5, 0xC7, 0x5E, 0x6E, 0x02, 0xEE, 0x8C, 0xF8, 0xF0, 0xBF, 0x69, 0xB8, 0x05, 0x1E, 0xF5, 0x28 } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000001F, 0x00001135, { { 0x90, 0x52, 0x4A, 0x95, 0xE4, 0x89, 0xD6, 0x0A, 0xE1, 0x2E, 0x98, 0x11, 0x02, 0xF5, 0x79, 0x37 } } } }, + + { FR_FRA, kPlatformPC, { 0x0000001E, 0x00000AC7, { { 0x4E, 0x7A, 0xC8, 0xC5, 0xD4, 0xB8, 0xD0, 0x73, 0x66, 0x2B, 0x2A, 0x13, 0xDE, 0xE1, 0x32, 0xAA } } } }, + + { DE_DEU, kPlatformUnknown, { 0x0000001E, 0x00000A71, { { 0x11, 0x88, 0x37, 0x8E, 0x17, 0xF2, 0x82, 0x1E, 0x72, 0xF0, 0xA3, 0x2B, 0x4F, 0x76, 0x5F, 0xBA } } } }, + + { IT_ITA, kPlatformPC, { 0x00000021, 0x00000C19, { { 0xC0, 0xFA, 0xD2, 0xB8, 0xCA, 0x94, 0x67, 0x10, 0x65, 0x01, 0x7F, 0xB0, 0x95, 0xC6, 0x0E, 0xFF } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000001E, 0x00000973, { { 0xD3, 0x93, 0x3C, 0xA6, 0xF7, 0x79, 0xE6, 0x05, 0x49, 0x88, 0x89, 0xDE, 0xCA, 0x77, 0x2F, 0x1B } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000001B, 0x0000099D, { { 0x13, 0x23, 0x5D, 0x38, 0x9B, 0xFB, 0x00, 0x5C, 0xA1, 0x3A, 0x22, 0xD6, 0xCD, 0x5C, 0x09, 0xAE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1FullFlaskStringProvider[] = { + { EN_ANY, kPlatformPC, { 0x00000097, 0x00003521, { { 0x9C, 0x30, 0xC7, 0xC9, 0x97, 0xF3, 0x0E, 0xC4, 0x6E, 0xCA, 0x63, 0xC6, 0xD8, 0x06, 0xFF, 0x30 } } } }, + + { FR_FRA, kPlatformPC, { 0x00000086, 0x00002E16, { { 0x94, 0x6C, 0x6D, 0xB6, 0x4C, 0x84, 0xBB, 0xF6, 0xC8, 0x50, 0x4C, 0x00, 0x38, 0xE3, 0x09, 0x5B } } } }, + + { DE_DEU, kPlatformPC, { 0x000000AF, 0x00003E38, { { 0x66, 0x86, 0xAF, 0x1A, 0x2D, 0x33, 0x40, 0xE7, 0x96, 0x9B, 0x32, 0x26, 0xFF, 0x9F, 0x79, 0x8B } } } }, + + { IT_ITA, kPlatformPC, { 0x00000086, 0x00002CDB, { { 0xB1, 0xAE, 0x2A, 0x03, 0x28, 0xEC, 0x6D, 0x2F, 0xED, 0x71, 0xBE, 0x60, 0xCF, 0xAB, 0x8C, 0x00 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x000000B5, 0x00004111, { { 0xA3, 0x4D, 0xA0, 0xF5, 0xE5, 0xD7, 0xFE, 0x11, 0xBB, 0x2C, 0xB5, 0xF2, 0xE0, 0x52, 0xF1, 0xF0 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000009A, 0x0000363B, { { 0x38, 0x25, 0xE6, 0xB5, 0xCB, 0x78, 0x5E, 0xAD, 0x2D, 0xD4, 0x2E, 0x8B, 0x89, 0x20, 0xB1, 0x95 } } } }, + + { EN_ANY, kPlatformAmiga, { 0x0000009A, 0x00003521, { { 0x26, 0xE5, 0xC8, 0x6D, 0x14, 0x81, 0x9F, 0x90, 0x38, 0x3C, 0x00, 0x9D, 0x8E, 0x72, 0xB1, 0x83 } } } }, + { DE_DEU, kPlatformAmiga, { 0x000000B0, 0x00003E38, { { 0x8A, 0x6D, 0x42, 0x36, 0x29, 0x06, 0xB2, 0xCE, 0xA3, 0x41, 0x14, 0xE8, 0xB1, 0xEF, 0x6E, 0x3B } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000009D, 0x00003521, { { 0xAB, 0x74, 0x71, 0x5C, 0x6E, 0x65, 0xF5, 0x5E, 0xB0, 0x6E, 0x0E, 0xC7, 0x56, 0xCB, 0x55, 0x98 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x0000007D, 0x000039CE, { { 0x9E, 0xBE, 0x13, 0x7F, 0x4D, 0x4B, 0xCB, 0x08, 0xC3, 0xE5, 0xF1, 0xC2, 0xD3, 0x69, 0x9E, 0xDF } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000079, 0x000039CE, { { 0xEF, 0x3F, 0x36, 0xD4, 0x6C, 0x64, 0x74, 0x9A, 0xFE, 0x13, 0xB5, 0x77, 0x9A, 0xCF, 0x15, 0x5C } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1VeryCleverStringProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000032, 0x0000118D, { { 0x4B, 0x6D, 0xD4, 0xDC, 0x3E, 0xA2, 0x2D, 0x6D, 0x2C, 0x5A, 0xF7, 0x67, 0x4B, 0x6D, 0x40, 0xEF } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000002F, 0x00001BDF, { { 0x32, 0x2C, 0x60, 0x1E, 0xB7, 0xE0, 0xFE, 0x5F, 0xEA, 0xEF, 0xA4, 0x73, 0xAC, 0xCB, 0xBA, 0xFE } } } }, + + { FR_FRA, kPlatformPC, { 0x00000027, 0x00000DE1, { { 0x43, 0xC2, 0xC7, 0xD2, 0xA3, 0x70, 0x36, 0x38, 0xB5, 0x5B, 0x22, 0xEF, 0xBA, 0x0D, 0x37, 0x27 } } } }, + + { DE_DEU, kPlatformUnknown, { 0x00000043, 0x00001871, { { 0x33, 0x3F, 0xEA, 0x7F, 0x5F, 0x56, 0x98, 0xF3, 0x03, 0x8D, 0x3E, 0xAC, 0xA1, 0x62, 0x2A, 0xD7 } } } }, + + { IT_ITA, kPlatformPC, { 0x00000038, 0x000013CF, { { 0x58, 0x7B, 0x59, 0x50, 0x84, 0xBB, 0x5B, 0x70, 0xDF, 0x76, 0x2F, 0xC3, 0x7E, 0xEC, 0x6A, 0x8B } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x00000027, 0x00000D01, { { 0x72, 0x7E, 0x88, 0xFB, 0xDA, 0xC0, 0x9E, 0x31, 0xAC, 0x32, 0xFD, 0x90, 0x7D, 0x01, 0x86, 0xD0 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x00000036, 0x000013F8, { { 0x2D, 0x9B, 0x7D, 0x58, 0xD1, 0x94, 0x04, 0x45, 0x6E, 0x81, 0xCC, 0x1E, 0x2F, 0xC5, 0xC9, 0xEA } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1NewGameStringProvider[] = { + { EN_ANY, kPlatformUnknown, { 0x00000015, 0x0000052B, { { 0xAB, 0xD2, 0x16, 0x26, 0xC2, 0x86, 0xFA, 0xC8, 0x42, 0xCD, 0x16, 0xCD, 0x25, 0xB7, 0x44, 0xDC } } } }, + + { JA_JPN, kPlatformUnknown, { 0x0000001B, 0x00000EC8, { { 0x13, 0x9A, 0xBC, 0x8F, 0xE2, 0x4B, 0xD7, 0x0B, 0xC0, 0x81, 0x60, 0x10, 0xC2, 0xA6, 0x9C, 0xFA } } } }, + + { FR_FRA, kPlatformPC, { 0x0000001D, 0x0000079B, { { 0x2B, 0x5B, 0x54, 0x29, 0x76, 0x31, 0x5E, 0x89, 0xC2, 0xD1, 0xDB, 0x3B, 0xF0, 0xBC, 0xCD, 0x66 } } } }, + + { DE_DEU, kPlatformUnknown, { 0x0000001D, 0x0000076F, { { 0x5C, 0x84, 0x2A, 0xB1, 0x61, 0xDD, 0x7B, 0xB3, 0xD4, 0x6A, 0xD2, 0xEF, 0xA4, 0x5F, 0x81, 0xFE } } } }, + + { IT_ITA, kPlatformPC, { 0x0000001C, 0x0000075E, { { 0xC8, 0xCB, 0x35, 0x5E, 0x73, 0x09, 0xDB, 0xA1, 0xF1, 0x8D, 0x14, 0x54, 0x8D, 0xF7, 0xB1, 0xD3 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000001D, 0x000007BD, { { 0xF4, 0x5C, 0x50, 0x82, 0x91, 0x7E, 0x09, 0x52, 0x44, 0x95, 0xC2, 0x2E, 0xC9, 0x52, 0x12, 0x2B } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000001B, 0x00000701, { { 0x2B, 0x87, 0xC3, 0x82, 0x68, 0xA5, 0xFC, 0xC5, 0x64, 0x9E, 0xAB, 0xD2, 0x8A, 0x07, 0x9C, 0x1E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1DefaultShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000048A, 0x00012C0A, { { 0x90, 0x9E, 0x21, 0x9F, 0x90, 0x16, 0x1D, 0xA5, 0x57, 0xF8, 0x71, 0xE1, 0x15, 0x44, 0x29, 0x73 } } } }, + + // TODO: Where did this come from? + /*{ UNK_LANG, kPlatformUnknown, { 0x000004F3, 0x00014AE4, { { 0x6E, 0x37, 0x81, 0x15, 0x4D, 0xDD, 0xBA, 0xA6, 0xE3, 0x5F, 0xB6, 0xC8, 0x20, 0xE9, 0xE0, 0x63 } } } },*/ + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Healing1ShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000009A, 0x00002F17, { { 0x92, 0x2C, 0xF1, 0x5C, 0x8B, 0xCE, 0xEB, 0x0B, 0xE4, 0x07, 0x16, 0xAA, 0x25, 0x4F, 0x83, 0xEB } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Healing2ShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000D2, 0x00004257, { { 0xAC, 0x35, 0xAA, 0x72, 0x50, 0x67, 0x58, 0xE4, 0x70, 0xB0, 0xBB, 0xCA, 0xA7, 0x4C, 0x91, 0x82 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PoisonDeathShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000008C, 0x00002E90, { { 0xBC, 0x44, 0xFB, 0x98, 0xE7, 0x42, 0xF6, 0xC8, 0x87, 0xDD, 0x00, 0x42, 0x85, 0xD8, 0x1E, 0x81 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1FluteShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000FC, 0x00004F0F, { { 0xB1, 0xF0, 0x56, 0x6E, 0xAB, 0x3C, 0x88, 0x13, 0x97, 0x7C, 0xCC, 0x61, 0x85, 0x8A, 0x28, 0x12 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Winter1ShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000031, 0x00000E70, { { 0x3A, 0x15, 0x36, 0x51, 0x2F, 0xF8, 0xAF, 0xE6, 0x41, 0x71, 0x8D, 0x44, 0x99, 0x48, 0xB3, 0x4F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Winter2ShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000F5, 0x00005192, { { 0xD3, 0x64, 0xAC, 0x64, 0x42, 0x9F, 0xB9, 0xCA, 0x0C, 0xC8, 0x97, 0x67, 0x8C, 0x92, 0xB4, 0x79 } } } }, + + { UNK_LANG, kPlatformUnknown, { 0x000000F5, 0x000029E4, { { 0xF0, 0x7B, 0x05, 0xD8, 0xC1, 0x97, 0x27, 0x17, 0xFA, 0x32, 0xE9, 0x1A, 0x46, 0xA5, 0xEB, 0x84 } } } }, // CD + Amiga + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1Winter3ShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001C, 0x00000A5E, { { 0x84, 0xDD, 0xC0, 0xEA, 0xE3, 0xBE, 0x98, 0x66, 0xE0, 0xA3, 0x4D, 0x00, 0x88, 0x31, 0x61, 0x1F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1DrinkShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000069, 0x00001EDA, { { 0x21, 0xFA, 0x2F, 0x41, 0x8F, 0x70, 0x3B, 0xBB, 0x93, 0x35, 0x49, 0xEC, 0x1C, 0xEE, 0xDD, 0xAC } } } }, + + { UNK_LANG, kPlatformFMTowns, { 0x0000006A, 0x00001EDA, { { 0xE2, 0xDA, 0xEC, 0x87, 0x4A, 0x27, 0xD8, 0xC1, 0x57, 0xE7, 0xD8, 0xD7, 0x87, 0x5F, 0x3A, 0xEB } } } }, + + { UNK_LANG, kPlatformPC98, { 0x0000006A, 0x00001EDA, { { 0xE2, 0xDA, 0xEC, 0x87, 0x4A, 0x27, 0xD8, 0xC1, 0x57, 0xE7, 0xD8, 0xD7, 0x87, 0x5F, 0x3A, 0xEB } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1WispShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000B6, 0x00003A53, { { 0x34, 0x52, 0x9D, 0x06, 0x4F, 0x1B, 0xCD, 0xB7, 0x30, 0xF7, 0xB4, 0x9F, 0x0F, 0x34, 0xDD, 0xF7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1MagicAnimShapesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000023, 0x00000A2D, { { 0x48, 0x8E, 0x2A, 0x61, 0x93, 0xCD, 0x58, 0x3B, 0x45, 0x62, 0xD9, 0x01, 0x8F, 0xBA, 0x2A, 0x1A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1BranStoneShapesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000006E, 0x00001E41, { { 0x77, 0x99, 0x54, 0xED, 0x4C, 0x31, 0x08, 0x50, 0x41, 0x22, 0x6B, 0xED, 0x34, 0xF4, 0x17, 0xA1 } } } }, + + { UNK_LANG, kPlatformAmiga, { 0x0000006E, 0x00002026, { { 0x5A, 0xAF, 0x28, 0xF3, 0x0F, 0x82, 0x05, 0xB4, 0x33, 0x83, 0xCE, 0x56, 0xDB, 0xE7, 0x5C, 0xB4 } } } }, + + { UNK_LANG, kPlatformFMTowns, { 0x00000063, 0x00001E41, { { 0xDA, 0xA1, 0x93, 0x68, 0xBF, 0xB3, 0xBB, 0xD1, 0x2E, 0xF9, 0xB2, 0x25, 0x72, 0xD9, 0xA6, 0x00 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x00000063, 0x00001E41, { { 0xDA, 0xA1, 0x93, 0x68, 0xBF, 0xB3, 0xBB, 0xD1, 0x2E, 0xF9, 0xB2, 0x25, 0x72, 0xD9, 0xA6, 0x00 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette1Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x0000024B, { { 0x6C, 0x6C, 0xE9, 0xB6, 0xC4, 0xC2, 0x29, 0xA5, 0xB6, 0xB3, 0x82, 0xB6, 0x03, 0x5B, 0x66, 0x7A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette2Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000033, 0x00000470, { { 0x63, 0x02, 0x97, 0x7D, 0xBE, 0x97, 0x5E, 0x88, 0x2E, 0x50, 0x18, 0x6A, 0x4A, 0x61, 0x09, 0xA6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette3Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000033, 0x0000042A, { { 0xF8, 0x32, 0x65, 0x55, 0x1C, 0xC5, 0x6E, 0x71, 0xC6, 0x6A, 0x8E, 0xC5, 0x3C, 0xBC, 0x1F, 0xA8 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette4Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000033, 0x000003A4, { { 0xA1, 0xA6, 0x6F, 0x53, 0xA2, 0x1E, 0x27, 0x6F, 0x0D, 0xD0, 0x4F, 0xDC, 0x4C, 0xDC, 0xAE, 0x17 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette5Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000033, 0x0000033D, { { 0x22, 0x02, 0xB3, 0xCD, 0x4E, 0xD5, 0x6E, 0x65, 0x2B, 0x38, 0x7D, 0x3E, 0x27, 0x03, 0x1A, 0x59 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette6Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000033, 0x000001EA, { { 0xC7, 0xA7, 0x0E, 0xBA, 0x3F, 0x5E, 0xD3, 0x02, 0x99, 0x3B, 0x32, 0x00, 0x39, 0x3C, 0xD2, 0xAC } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette7Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000036, 0x0000040C, { { 0x1A, 0x8E, 0x3E, 0x5F, 0x09, 0xFE, 0x4A, 0xF1, 0x5D, 0x2E, 0x2C, 0xD3, 0xFF, 0x75, 0x7D, 0x1C } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette8Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000036, 0x000008E4, { { 0x55, 0xB4, 0xD3, 0xD1, 0x89, 0x49, 0xA5, 0x7E, 0x40, 0xF9, 0xFE, 0x6E, 0x16, 0xE8, 0xBD, 0xBB } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette9Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x000001DB, { { 0x7A, 0x04, 0x16, 0xDD, 0x6A, 0xBA, 0x51, 0x9E, 0x24, 0x9E, 0xEA, 0x76, 0xD0, 0xFA, 0x92, 0xF4 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette10Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x0000017A, { { 0xD2, 0x20, 0x1F, 0x12, 0xE1, 0x65, 0x68, 0xA7, 0x9C, 0x69, 0x8E, 0x99, 0xDF, 0xC5, 0xD2, 0x8E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette11Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x00000136, { { 0xBF, 0x38, 0xB1, 0xFE, 0xBF, 0x25, 0xBC, 0xD3, 0xCC, 0x60, 0x40, 0x97, 0xB6, 0x4A, 0xC7, 0xB2 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette12Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x00000102, { { 0x1C, 0x1E, 0x6A, 0x30, 0xE1, 0xD1, 0xF9, 0x3D, 0x9A, 0xF1, 0x84, 0xBD, 0x44, 0x07, 0x51, 0xEA } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette13Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x00000000, { { 0x76, 0x22, 0x21, 0x4B, 0x85, 0x36, 0xAF, 0xE7, 0xB8, 0x9B, 0x1C, 0x66, 0x06, 0x06, 0x9B, 0x0D } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette14Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x000003BF, { { 0x78, 0xE8, 0xA8, 0xF2, 0x4D, 0x54, 0x48, 0x47, 0xC9, 0xC1, 0x5B, 0x6C, 0x69, 0xCB, 0x65, 0xB6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette15Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002D, 0x000002DD, { { 0x9F, 0x66, 0x50, 0xAC, 0xED, 0x0C, 0x63, 0x20, 0xE9, 0x4E, 0x4D, 0x3D, 0xC4, 0xBC, 0x94, 0x8A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette16Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000021, 0x0000036E, { { 0xA9, 0xDB, 0x1C, 0x35, 0xED, 0xED, 0xE4, 0x40, 0x68, 0x29, 0xB1, 0x6E, 0x60, 0xE4, 0xB0, 0xDB } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette17Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000021, 0x000004D7, { { 0xC0, 0xB5, 0x7B, 0x94, 0xED, 0xD7, 0x48, 0x66, 0x37, 0x54, 0xE8, 0xFC, 0x0F, 0xA5, 0x54, 0x8A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette18Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x000002FD, { { 0x0A, 0xDD, 0x81, 0xA8, 0x89, 0xD2, 0x53, 0x05, 0x25, 0xCC, 0x2B, 0x8B, 0x48, 0x1D, 0xAB, 0x0A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette19Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x00000134, { { 0xCB, 0x0F, 0xA9, 0xD2, 0xD8, 0xEA, 0x2A, 0x1F, 0x16, 0x7B, 0x90, 0xE5, 0x72, 0xB3, 0x52, 0x50 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette20Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x00000396, { { 0x3B, 0xD8, 0xA5, 0xC5, 0x66, 0x3E, 0xC7, 0x88, 0xD0, 0x3B, 0x42, 0x29, 0x84, 0x58, 0xA7, 0x00 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette21Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x00000134, { { 0x96, 0x70, 0x7D, 0x5B, 0xC4, 0xBA, 0x89, 0x89, 0xC9, 0x42, 0xF4, 0x70, 0x33, 0xF5, 0xE8, 0x02 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette22Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x00000376, { { 0xA2, 0x92, 0x28, 0x65, 0xAB, 0xCC, 0x16, 0xE8, 0xA5, 0x72, 0x2F, 0x00, 0x66, 0x8F, 0x8D, 0x96 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette23Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000015, 0x000002C2, { { 0x5C, 0x78, 0x74, 0x81, 0x76, 0xB5, 0x26, 0x8E, 0x20, 0xAE, 0x50, 0xCD, 0x2B, 0x9E, 0x81, 0x8B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette24Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x00000472, { { 0xC6, 0xF0, 0xA6, 0x33, 0x7E, 0xAE, 0xBC, 0xF9, 0xAE, 0xE2, 0xF4, 0x7B, 0x71, 0x44, 0x50, 0xEF } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette25Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x000004CD, { { 0x57, 0x03, 0xB5, 0x27, 0x64, 0x48, 0xBF, 0x6A, 0x0F, 0xC2, 0xC0, 0x4A, 0x73, 0x9A, 0xFE, 0xB3 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette26Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x000004CA, { { 0xF8, 0x39, 0x8D, 0x6F, 0x8D, 0x9C, 0x6E, 0x0A, 0x33, 0xE8, 0xF2, 0xA6, 0xF6, 0x40, 0x70, 0xE5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette27Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x000004D9, { { 0xF6, 0xD4, 0x88, 0x57, 0x6F, 0x1A, 0xA3, 0x1F, 0x6B, 0x17, 0x4D, 0xA0, 0x9E, 0xD8, 0x09, 0x66 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette28Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x0000051D, { { 0x59, 0x02, 0xE3, 0xC6, 0x28, 0xF6, 0xBC, 0xD4, 0xC8, 0x7E, 0x58, 0x6F, 0xE4, 0xA2, 0x28, 0x4F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette29Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x00000534, { { 0xC2, 0x26, 0x94, 0x47, 0x28, 0x11, 0xAA, 0xE6, 0x10, 0xA2, 0xD4, 0xD9, 0x61, 0x57, 0x62, 0x22 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette30Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x00000453, { { 0xE1, 0x30, 0xC2, 0xCD, 0x79, 0xD8, 0x36, 0x8D, 0xAC, 0xF7, 0x87, 0x05, 0x49, 0xD7, 0x7A, 0x5F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette31Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000027, 0x000002FB, { { 0xA6, 0x65, 0xE1, 0xE1, 0xCC, 0x71, 0x83, 0x63, 0x9A, 0x04, 0xE2, 0x00, 0xBF, 0x90, 0xDF, 0x95 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette32Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000027, 0x0000016C, { { 0xAA, 0x88, 0x97, 0xE3, 0xCA, 0x06, 0x11, 0x07, 0x8F, 0xFA, 0x75, 0x26, 0xA8, 0x7A, 0x49, 0x28 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1SpecialPalette33Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x0000094C, { { 0x2E, 0x5E, 0x34, 0x3E, 0x99, 0x61, 0x6F, 0x88, 0x91, 0xA7, 0x75, 0xAA, 0x42, 0x4B, 0x1F, 0x5D } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1GUIStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x000001B0, 0x00009562, { { 0x78, 0xB0, 0x81, 0x15, 0x96, 0x09, 0x1E, 0x6C, 0x20, 0x7B, 0xF7, 0xB1, 0x29, 0x2A, 0x3D, 0xE4 } } } }, // floppy + { EN_ANY, kPlatformPC, { 0x00000209, 0x00009788, { { 0xDD, 0xA0, 0x5C, 0x30, 0x60, 0x68, 0xDC, 0x24, 0xBE, 0x3F, 0xA2, 0x31, 0xE0, 0x81, 0x6C, 0xCA } } } }, // CD + + { FR_FRA, kPlatformPC, { 0x00000234, 0x0000C262, { { 0x08, 0x83, 0x32, 0x4E, 0x48, 0xEC, 0x83, 0x4B, 0x1B, 0x82, 0x58, 0x48, 0xA3, 0x30, 0x05, 0x33 } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x0000025D, 0x0000CBDC, { { 0x36, 0xF0, 0x92, 0x9C, 0x5F, 0xFF, 0x5D, 0x65, 0x5F, 0x0B, 0xC0, 0x72, 0x9F, 0x30, 0x47, 0xAB } } } }, // CD + + { DE_DEU, kPlatformPC, { 0x00000236, 0x0000BA9C, { { 0xEB, 0xA6, 0x90, 0x9D, 0x99, 0x4B, 0x4F, 0xD9, 0xCE, 0xFF, 0x44, 0x3F, 0x77, 0x6F, 0xE1, 0x71 } } } }, // floppy + { DE_DEU, kPlatformPC, { 0x00000261, 0x0000C538, { { 0xF3, 0xED, 0x5E, 0x73, 0x6F, 0x6E, 0x06, 0xF8, 0x48, 0xF8, 0x30, 0x69, 0x34, 0x5D, 0x99, 0x0C } } } }, // CD + + { IT_ITA, kPlatformPC, { 0x00000225, 0x0000B0E1, { { 0x57, 0xE2, 0x39, 0xA8, 0xF5, 0x70, 0x48, 0xB4, 0x3D, 0xD4, 0x2A, 0x8C, 0x7C, 0x76, 0xB7, 0x8D } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000025D, 0x0000AFD0, { { 0x8E, 0x97, 0xA9, 0x55, 0x16, 0xF7, 0x42, 0x83, 0xA3, 0x68, 0x2F, 0xD6, 0x37, 0x1C, 0x9A, 0xD1 } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000023A, 0x0000C3BD, { { 0xED, 0x0D, 0xE7, 0x5B, 0xDC, 0x21, 0x41, 0x54, 0x68, 0x7D, 0x8E, 0x97, 0x1A, 0xB1, 0xA1, 0x4A } } } }, // floppy + + { EN_ANY, kPlatformAmiga, { 0x000001DF, 0x00009042, { { 0x0D, 0xD3, 0x1A, 0x92, 0x8D, 0x9C, 0x72, 0x55, 0xEF, 0xFB, 0x81, 0x21, 0x3B, 0x43, 0xA7, 0xE8 } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000237, 0x0000BAF7, { { 0xD7, 0x1A, 0x8E, 0xCC, 0x6D, 0x3E, 0xA9, 0xDD, 0x9A, 0x6B, 0x71, 0xFE, 0xD4, 0x50, 0x30, 0x6E } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x000001FC, 0x00009D9A, { { 0xE8, 0x39, 0x46, 0x0A, 0x41, 0xC3, 0xDC, 0x33, 0x6E, 0xC5, 0x5D, 0x99, 0xCC, 0xF6, 0xDD, 0xCC } } } }, + { JA_JPN, kPlatformFMTowns, { 0x0000025F, 0x0000E56A, { { 0x77, 0x9A, 0x02, 0x52, 0xED, 0x62, 0x23, 0x5A, 0x58, 0x78, 0x19, 0x52, 0x03, 0xD7, 0x88, 0x40 } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000213, 0x0000EC5A, { { 0x3B, 0xBA, 0xFB, 0x61, 0x34, 0x60, 0x25, 0xDA, 0x48, 0xBF, 0x95, 0x7F, 0x7F, 0xB6, 0xE4, 0x55 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1ConfigStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x0000003F, 0x000016E9, { { 0x4F, 0x19, 0x60, 0x67, 0xA8, 0x31, 0x0B, 0xD5, 0x3D, 0x06, 0x39, 0xF1, 0x42, 0xB0, 0xFD, 0x5C } } } }, // floppy + { EN_ANY, kPlatformPC, { 0x00000061, 0x00002249, { { 0x5D, 0xE2, 0x05, 0xA7, 0xEC, 0x0A, 0x73, 0xF5, 0x01, 0x5B, 0x64, 0x71, 0x83, 0xEC, 0x56, 0x24 } } } }, // CD + + { FR_FRA, kPlatformPC, { 0x0000004B, 0x00001AE8, { { 0xE3, 0xC9, 0x0F, 0x54, 0x48, 0x31, 0x6E, 0x5F, 0x51, 0x8E, 0xF8, 0xE6, 0xAC, 0x16, 0xAC, 0x1C } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x0000007A, 0x00002C37, { { 0x9E, 0xD8, 0x85, 0xB4, 0x9D, 0x32, 0x9D, 0x80, 0x58, 0xE4, 0x08, 0xC7, 0x75, 0xD2, 0x9C, 0x1E } } } }, // CD + + { DE_DEU, kPlatformPC, { 0x0000005E, 0x00002280, { { 0xC7, 0xD2, 0x22, 0xB5, 0xD3, 0xBC, 0x7A, 0x97, 0x26, 0x04, 0x07, 0x78, 0xAA, 0xAB, 0x1D, 0x5C } } } }, // floppy + { DE_DEU, kPlatformPC, { 0x00000082, 0x00002E94, { { 0xC5, 0xDC, 0x44, 0x6C, 0x4B, 0x3E, 0x4E, 0x27, 0x0C, 0xCC, 0x65, 0x6C, 0x20, 0x8D, 0x71, 0x07 } } } }, // CD + + { IT_ITA, kPlatformPC, { 0x00000054, 0x00001E98, { { 0x10, 0x6B, 0x6B, 0x9B, 0x91, 0x05, 0xE9, 0x30, 0xE2, 0x75, 0xE2, 0x45, 0x79, 0x17, 0x73, 0xC9 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x0000007A, 0x00002904, { { 0xD3, 0xD2, 0x96, 0x6E, 0xE7, 0xE8, 0x64, 0x77, 0x73, 0xCD, 0xC2, 0x9E, 0x57, 0xB5, 0xD3, 0xCD } } } }, // (fan) CD + + { ES_ESP, kPlatformPC, { 0x0000004A, 0x00001B7B, { { 0x6B, 0x69, 0x50, 0x92, 0x9B, 0x35, 0x58, 0xE1, 0xEA, 0xBF, 0x42, 0x0B, 0xEB, 0x88, 0x41, 0x8D } } } }, // floppy + + { EN_ANY, kPlatformAmiga, { 0x0000002E, 0x00000FA1, { { 0x5E, 0xFF, 0xFF, 0x3D, 0xF8, 0x11, 0x6F, 0x3B, 0xC5, 0x39, 0x8F, 0x25, 0x8F, 0x0F, 0xE9, 0x2B } } } }, + { DE_DEU, kPlatformAmiga, { 0x00000043, 0x00001783, { { 0xB2, 0x2B, 0xAB, 0x27, 0x06, 0x9A, 0x1E, 0x4B, 0xA7, 0xD3, 0xFF, 0xEB, 0xFD, 0x12, 0xDC, 0x94 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000004A, 0x000016E9, { { 0x37, 0x12, 0xAD, 0x4C, 0xB8, 0x2C, 0xF5, 0x75, 0x20, 0x74, 0xA0, 0xFD, 0x58, 0xB1, 0x71, 0x77 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x00000057, 0x00002262, { { 0xC5, 0x9A, 0x4A, 0xE3, 0xDF, 0xD3, 0x0E, 0x8E, 0xBB, 0xAF, 0x75, 0xD3, 0x67, 0xB1, 0xF6, 0x08 } } } }, + + { JA_JPN, kPlatformPC98, { 0x0000003F, 0x00001E9D, { { 0x8A, 0x3C, 0x78, 0x6B, 0x3F, 0x0A, 0x7D, 0x92, 0x16, 0x39, 0xEB, 0x1C, 0x84, 0x9E, 0x4F, 0x84 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1TownsMusicFadeTableProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00000B10, 0x000076DE, { { 0x9F, 0x08, 0x5B, 0xD6, 0x25, 0x7F, 0x11, 0x08, 0x87, 0x45, 0x92, 0xD3, 0xE5, 0xA8, 0x7C, 0x2F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1TownsSFXwdTableProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00012608, 0x006717A1, { { 0x34, 0xDD, 0x2D, 0xA5, 0x14, 0x05, 0xEE, 0x2F, 0x93, 0x7C, 0x78, 0x4D, 0xCA, 0x13, 0xED, 0x93 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1TownsSFXbtTableProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00000100, 0x00007FFE, { { 0xEF, 0x3D, 0x9F, 0x31, 0xE7, 0x19, 0x1E, 0x4F, 0xF3, 0x66, 0x42, 0xC8, 0x0D, 0x89, 0x96, 0x20 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1TownsCDATableProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x000002C4, 0x0000C5ED, { { 0x76, 0x86, 0x77, 0xF9, 0x85, 0x23, 0x32, 0x56, 0x3C, 0x06, 0x03, 0xCF, 0x0C, 0x49, 0x94, 0xB5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PC98StoryStringsProvider[] = { + { JA_JPN, kPlatformPC98, { 0x00000054, 0x00002FAD, { { 0xCB, 0x25, 0xD1, 0xFA, 0x65, 0xCE, 0xD5, 0xE6, 0xAD, 0xE3, 0x48, 0x25, 0xC8, 0x51, 0xC6, 0x12 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1PC98IntroSfxProvider[] = { + { UNK_LANG, kPlatformPC98, { 0x00000300, 0x00017445, { { 0xC3, 0x54, 0x4A, 0x58, 0x00, 0x33, 0xEA, 0xF1, 0x20, 0xA8, 0x0C, 0xDE, 0x7A, 0x94, 0xAB, 0x5E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1CreditsStringsProvider[] = { + { EN_ANY, kPlatformAmiga, { 0x000004CC, 0x000182F7, { { 0x7D, 0x14, 0xA6, 0xEC, 0x12, 0x67, 0xAC, 0xA7, 0x7B, 0xF8, 0x44, 0x19, 0x52, 0xCC, 0x3A, 0x65 } } } }, + { DE_DEU, kPlatformAmiga, { 0x000004FB, 0x00019987, { { 0x8B, 0xF1, 0x61, 0xB9, 0x3E, 0xA4, 0x28, 0x9B, 0x45, 0x86, 0xD1, 0xF0, 0xC3, 0x35, 0x44, 0xA0 } } } }, + + { EN_ANY, kPlatformFMTowns, { 0x0000058C, 0x0001AD16, { { 0xFC, 0x1B, 0xE6, 0xEB, 0x03, 0x1C, 0x54, 0x93, 0x64, 0x53, 0xB1, 0x17, 0x9D, 0x95, 0x1B, 0x4A } } } }, + { JA_JPN, kPlatformFMTowns, { 0x0000058C, 0x0001AD16, { { 0xFC, 0x1B, 0xE6, 0xEB, 0x03, 0x1C, 0x54, 0x93, 0x64, 0x53, 0xB1, 0x17, 0x9D, 0x95, 0x1B, 0x4A } } } }, + + { JA_JPN, kPlatformPC98, { 0x00000530, 0x00019571, { { 0x38, 0x4F, 0xE0, 0x74, 0x27, 0x21, 0xEC, 0x63, 0x41, 0x32, 0xB1, 0xD9, 0xA5, 0x65, 0x62, 0x71 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1AmigaIntroSFXTableProvider[] = { + { UNK_LANG, kPlatformAmiga, { 0x00000140, 0x00000D82, { { 0x61, 0xF6, 0x8F, 0xE5, 0xCD, 0x15, 0x58, 0x9F, 0xDF, 0x0E, 0x22, 0xAA, 0x9A, 0xCF, 0xC4, 0xA6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k1AmigaGameSFXTableProvider[] = { + { UNK_LANG, kPlatformAmiga, { 0x000003C0, 0x00005505, { { 0x8D, 0x6D, 0x2C, 0x58, 0x50, 0xF7, 0xBF, 0x60, 0xC3, 0x15, 0x20, 0x23, 0x1F, 0x90, 0x3E, 0xD6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayPakFilesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000022, 0x000008E0, { { 0xB7, 0x3B, 0x51, 0x46, 0x78, 0x2D, 0x4D, 0x82, 0xD4, 0x30, 0xFC, 0x6E, 0xC4, 0x5B, 0x27, 0x3E } } } }, // DOS floppy + PC98 + + { UNK_LANG, kPlatformPC, { 0x00000046, 0x0000121A, { { 0x42, 0xC2, 0x5A, 0xDC, 0x27, 0x2D, 0xB4, 0x44, 0x85, 0x58, 0x0F, 0xB6, 0x6D, 0x76, 0x04, 0x4F } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x00000014, 0x000004FA, { { 0xBB, 0x4C, 0x16, 0xEB, 0x56, 0xEF, 0xAC, 0x68, 0x6B, 0x49, 0x96, 0x3A, 0x9F, 0x00, 0x75, 0xF6 } } } }, // demo + { UNK_LANG, kPlatformPC, { 0x0000000C, 0x00000308, { { 0xC0, 0xAC, 0x10, 0xF1, 0x12, 0xD1, 0x21, 0x92, 0xA1, 0x62, 0x5B, 0x6E, 0xCF, 0x88, 0x32, 0x7C } } } }, // Lands of Lore demo + + { UNK_LANG, kPlatformFMTowns, { 0x00000033, 0x00000BBD, { { 0x92, 0x5B, 0xDA, 0xE3, 0x7C, 0x39, 0xC4, 0x75, 0x24, 0xBA, 0x67, 0x27, 0x6E, 0x21, 0xA3, 0xF7 } } } }, + + // TODO: Where did this come from? + //{ UNK_LANG, kPlatformUnknown, { 0x0000002E, 0x00000C09, { { 0x6A, 0x25, 0xF6, 0x03, 0xA6, 0x88, 0xA0, 0x53, 0xE1, 0xF4, 0xB9, 0x0C, 0x71, 0x17, 0x36, 0x6B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x000008C8, 0x0002FDE3, { { 0x62, 0xD1, 0x6F, 0xBC, 0xEC, 0xE6, 0xCF, 0xE8, 0xD8, 0xE9, 0xDE, 0xFB, 0x09, 0xAF, 0x34, 0x92 } } } }, // floppy + { EN_ANY, kPlatformPC, { 0x00000916, 0x00031417, { { 0x3E, 0x15, 0xDA, 0xF4, 0x77, 0x44, 0x80, 0x47, 0xDB, 0x32, 0x0E, 0x6D, 0xCA, 0x32, 0x65, 0x1B } } } }, // CD + { EN_ANY, kPlatformPC, { 0x00000102, 0x00005BD6, { { 0xB3, 0x00, 0xE5, 0x39, 0x02, 0x3D, 0xBF, 0xDD, 0x54, 0x70, 0xEA, 0xC1, 0xCB, 0xAC, 0xAA, 0xF7 } } } }, // Lands of Lore demo + + { DE_DEU, kPlatformPC, { 0x000009EC, 0x000370F9, { { 0x56, 0x94, 0xCC, 0xE5, 0x38, 0x19, 0xAD, 0xD1, 0xBB, 0x6A, 0x6E, 0xEC, 0xC5, 0x1B, 0x57, 0x7B } } } }, // floppy + { DE_DEU, kPlatformPC, { 0x00000A3F, 0x000389F4, { { 0x51, 0xC1, 0x87, 0x16, 0x53, 0x8C, 0x68, 0x8E, 0x9B, 0x81, 0xA1, 0xD2, 0xCE, 0x5F, 0x83, 0x31 } } } }, // CD + + { FR_FRA, kPlatformPC, { 0x000009C9, 0x00036324, { { 0x2C, 0xC2, 0xD9, 0xCF, 0x90, 0x2A, 0xDF, 0xE9, 0x85, 0x9E, 0x5D, 0xBB, 0x1D, 0x9A, 0x14, 0x69 } } } }, // floppy + { FR_FRA, kPlatformPC, { 0x00000995, 0x000352D7, { { 0xED, 0x7C, 0x49, 0x7B, 0x1A, 0x2C, 0x73, 0x61, 0x73, 0xAF, 0x16, 0x89, 0x1E, 0x01, 0xE2, 0xAE } } } }, // CD + + { IT_ITA, kPlatformPC, { 0x00000916, 0x0003188F, { { 0xDC, 0x46, 0x06, 0xE1, 0xB0, 0x66, 0xBC, 0x18, 0x2E, 0x6E, 0x9E, 0xC9, 0xA4, 0x14, 0x8D, 0x08 } } } }, // floppy + { IT_ITA, kPlatformPC, { 0x000008C8, 0x00030947, { { 0x7F, 0x75, 0x5F, 0x99, 0x94, 0xFE, 0xA1, 0xE6, 0xEF, 0xB8, 0x93, 0x71, 0x83, 0x1B, 0xAC, 0x4A } } } }, // (fan) CD + + { EN_ANY, kPlatformFMTowns, { 0x00000990, 0x00030C61, { { 0x60, 0x51, 0x11, 0x83, 0x3F, 0x06, 0xC3, 0xA3, 0xE0, 0xC0, 0x2F, 0x41, 0x29, 0xDE, 0x65, 0xB1 } } } }, + { JA_JPN, kPlatformFMTowns, { 0x000008A8, 0x00036831, { { 0x56, 0x5B, 0x23, 0x61, 0xE8, 0x3B, 0xE1, 0x36, 0xD6, 0x62, 0xD0, 0x84, 0x00, 0x04, 0x05, 0xAD } } } }, + + { EN_ANY, kPlatformPC98, { 0x000008F4, 0x00030C61, { { 0xA4, 0x4C, 0xD9, 0x05, 0x65, 0x24, 0xE5, 0x3E, 0x6C, 0x8B, 0xEE, 0x8D, 0x4F, 0x09, 0x6F, 0x00 } } } }, + { JA_JPN, kPlatformPC98, { 0x000007F5, 0x00036831, { { 0xF7, 0xCF, 0xF1, 0x2B, 0x26, 0x1E, 0xEC, 0xC8, 0x13, 0xDE, 0xC7, 0x71, 0x72, 0x05, 0x0F, 0xA7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplaySfxFilesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000173, 0x00008198, { { 0x2D, 0xF5, 0x5C, 0xAE, 0xDB, 0x71, 0x60, 0xFE, 0x78, 0x04, 0xFC, 0xAD, 0x4B, 0x43, 0xB1, 0x4B } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000234, 0x0000B0B2, { { 0xE4, 0x19, 0x4F, 0x8C, 0x53, 0xFD, 0x5F, 0x2A, 0xFB, 0x77, 0x1C, 0x32, 0xB3, 0x39, 0x25, 0x85 } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x000000DE, 0x00004EA4, { { 0x97, 0xA8, 0x4A, 0xED, 0x12, 0x87, 0xEB, 0x82, 0x42, 0xFA, 0x45, 0x0D, 0x45, 0x8F, 0xFE, 0x76 } } } }, // demo + { UNK_LANG, kPlatformPC, { 0x000000C5, 0x00004508, { { 0xBF, 0xA9, 0x1A, 0x37, 0x0B, 0xF8, 0x13, 0x9D, 0x2D, 0x67, 0x3D, 0x9B, 0xE9, 0x16, 0x07, 0x0C } } } }, // Lands of Lore demo + + { UNK_LANG, kPlatformFMTowns, { 0x000001A3, 0x00008098, { { 0xA9, 0xD2, 0xE2, 0x32, 0x59, 0xC4, 0x97, 0x74, 0x11, 0x49, 0x8F, 0x2B, 0xBF, 0x00, 0xF9, 0xF1 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x00000173, 0x00008098, { { 0x29, 0xA6, 0xF1, 0x2D, 0x35, 0x38, 0xFD, 0x3B, 0xF0, 0xB1, 0xE1, 0xFE, 0x45, 0xB1, 0x43, 0xAE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayTlkFilesProvider[] = { + { EN_ANY, kPlatformPC, { 0x0000009D, 0x0000286B, { { 0x58, 0x30, 0x72, 0x62, 0xC8, 0x77, 0x2A, 0x06, 0xD6, 0x24, 0x1A, 0x7A, 0xAF, 0x79, 0xFF, 0xAE } } } }, + { FR_FRA, kPlatformPC, { 0x0000009D, 0x00002878, { { 0x28, 0x5D, 0x7F, 0x5B, 0x57, 0xC2, 0xFF, 0x73, 0xC1, 0x8E, 0xD6, 0xE0, 0x4D, 0x03, 0x99, 0x2C } } } }, + { DE_DEU, kPlatformPC, { 0x0000009D, 0x00002885, { { 0x87, 0x24, 0xB6, 0xE9, 0xD6, 0xAA, 0x68, 0x2D, 0x6B, 0x05, 0xDF, 0xE1, 0x2B, 0xA4, 0x79, 0xE5 } } } }, + { IT_ITA, kPlatformPC, { 0x0000009D, 0x0000286B, { { 0x58, 0x30, 0x72, 0x62, 0xC8, 0x77, 0x2A, 0x06, 0xD6, 0x24, 0x1A, 0x7A, 0xAF, 0x79, 0xFF, 0xAE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplaySeqDataProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000006F4, 0x0000F5AD, { { 0x23, 0x1E, 0x30, 0xF0, 0xF1, 0x5B, 0xFF, 0x4B, 0xDF, 0xB1, 0x78, 0xD8, 0x48, 0x7A, 0xA3, 0xDD } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x000006F4, 0x0000FA52, { { 0xC8, 0x33, 0xCC, 0x0A, 0x40, 0x8A, 0x96, 0x4F, 0x42, 0x7E, 0x8B, 0x62, 0x9C, 0x2F, 0x33, 0x0B } } } }, // floppy (French) + { UNK_LANG, kPlatformPC, { 0x000006F4, 0x0000F8A6, { { 0x8B, 0xF3, 0x80, 0xE1, 0xB8, 0xCA, 0xE1, 0x18, 0x72, 0xA3, 0xF0, 0x4C, 0xBF, 0x81, 0x97, 0x71 } } } }, // floppy (German) + { UNK_LANG, kPlatformPC, { 0x000006F4, 0x0000FA35, { { 0x4C, 0x26, 0x1B, 0xF6, 0x8E, 0x73, 0xB7, 0xD2, 0x58, 0x59, 0xB8, 0x97, 0x58, 0xFB, 0x0E, 0x2A } } } }, // floppy (Italian) + { UNK_LANG, kPlatformPC, { 0x000006BE, 0x0000E9FF, { { 0x9A, 0xCD, 0x40, 0x44, 0xEF, 0x9F, 0x05, 0x86, 0xDA, 0x49, 0x8A, 0x85, 0x68, 0xDF, 0xA7, 0x55 } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x0000027C, 0x00007742, { { 0x42, 0x37, 0xF8, 0xDD, 0xA2, 0x8C, 0xA6, 0x26, 0x89, 0x5F, 0xCF, 0x61, 0xDD, 0x8F, 0xC7, 0x1E } } } }, // demo + { UNK_LANG, kPlatformPC, { 0x0000024C, 0x00004C10, { { 0x21, 0x3A, 0x86, 0x60, 0xA8, 0xFF, 0x42, 0x19, 0x35, 0x32, 0xA5, 0xB9, 0x3A, 0xDD, 0xA9, 0xC7 } } } }, // Lands of Lore demo + + { UNK_LANG, kPlatformFMTowns, { 0x000006BC, 0x0000DCE3, { { 0x27, 0x09, 0x22, 0xDC, 0xED, 0xDE, 0x88, 0xAE, 0xDB, 0x97, 0x52, 0x12, 0x96, 0x8D, 0x8D, 0x37 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x000006BE, 0x0000E043, { { 0x35, 0xA0, 0xF1, 0x14, 0xC7, 0x60, 0x80, 0x35, 0xA2, 0xDB, 0xF2, 0x73, 0x96, 0xC0, 0xAE, 0x84 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayCreditsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000AE8, 0x0002E520, { { 0x19, 0x59, 0xEA, 0x70, 0x23, 0xE2, 0x41, 0x78, 0x2D, 0xF5, 0xE6, 0x28, 0xEA, 0x0C, 0xCF, 0x79 } } } }, + { IT_ITA, kPlatformPC, { 0x00000AE8, 0x0002EE4A, { { 0x3E, 0x5C, 0x6F, 0x9E, 0x72, 0x2D, 0xAB, 0x17, 0x1D, 0x27, 0xFF, 0x32, 0xD3, 0x48, 0x46, 0xBA } } } }, // (fan) CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayCreditsSpecialProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001A, 0x00000829, { { 0xDF, 0x31, 0x0F, 0xB9, 0xC9, 0xC4, 0xF2, 0xB5, 0xF7, 0x98, 0x6F, 0x44, 0x4E, 0x9C, 0xFE, 0xA7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayIntroTracksProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000010, 0x00000592, { { 0xDE, 0xD9, 0x5E, 0xCA, 0x5A, 0x9F, 0x8B, 0xB1, 0xE2, 0xDB, 0xA4, 0xA1, 0xAF, 0xD4, 0x75, 0x46 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000008, 0x000002C9, { { 0xFA, 0x80, 0x3C, 0x78, 0x66, 0x2C, 0xD5, 0x91, 0x5D, 0xF1, 0xE9, 0xC1, 0x6A, 0x65, 0xEB, 0xD6 } } } }, // CD + { UNK_LANG, kPlatformPC, { 0x00000010, 0x00000542, { { 0xE5, 0xAA, 0x6A, 0xB9, 0x19, 0xAB, 0x35, 0x26, 0x43, 0x70, 0x32, 0xEF, 0xB9, 0x7F, 0x0F, 0x19 } } } }, // demo + { UNK_LANG, kPlatformPC, { 0x0000001A, 0x0000096C, { { 0xC2, 0xBD, 0x2C, 0x65, 0xD3, 0xFE, 0xF1, 0x6A, 0xE7, 0x34, 0x18, 0x0C, 0x86, 0x95, 0x66, 0x35 } } } }, // Lands of Lore demo + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayFinaleTracksProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000012, 0x00000618, { { 0x22, 0x61, 0x4D, 0x6F, 0xCE, 0x38, 0x64, 0xAB, 0x20, 0xD8, 0x34, 0x33, 0x44, 0x21, 0xE0, 0x23 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000009, 0x0000030C, { { 0x24, 0x3F, 0x57, 0xFA, 0x7E, 0x6D, 0x61, 0x6C, 0x53, 0xBC, 0x44, 0x38, 0x61, 0xE9, 0x3E, 0xE6 } } } }, // CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayIntroCDAProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00000018, 0x00000036, { { 0xCE, 0x10, 0x68, 0x7E, 0x84, 0x68, 0x3A, 0x23, 0x36, 0x41, 0x07, 0xE8, 0x59, 0xDB, 0xA3, 0x31 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayFinaleCDAProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x00000008, 0x000000AE, { { 0x38, 0x47, 0x35, 0xAA, 0xEC, 0xBA, 0xD3, 0xD0, 0x3E, 0x17, 0xFD, 0xB8, 0x9F, 0xB9, 0xAD, 0x61 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2SeqplayShapeAnimDataProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000B8, 0x00000270, { { 0xBD, 0x3B, 0xFA, 0xE6, 0xA0, 0x40, 0x4E, 0x6E, 0x3E, 0x43, 0x81, 0xF3, 0x35, 0x57, 0x62, 0x27 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngamePakFilesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000049F, 0x00012F40, { { 0x4B, 0x2A, 0x84, 0xE3, 0xA5, 0x34, 0xE9, 0xB3, 0xB7, 0x39, 0xF1, 0x1B, 0x4C, 0xE6, 0x43, 0x79 } } } }, // floppy + + { UNK_LANG, kPlatformFMTowns, { 0x0000011C, 0x00003FB8, { { 0x66, 0x34, 0xE8, 0x1C, 0xF9, 0xFF, 0x84, 0x90, 0x20, 0x71, 0x42, 0xA3, 0x2C, 0x4A, 0xE9, 0x46 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x000000F4, 0x00003F57, { { 0x8A, 0xA7, 0x2C, 0xB9, 0x6E, 0x8D, 0x95, 0xBF, 0xF8, 0xB9, 0x98, 0x63, 0x20, 0xF8, 0xB0, 0x7B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameSfxFilesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000006F1, 0x0001545E, { { 0xD3, 0x8A, 0xA1, 0xD4, 0x83, 0x77, 0x96, 0x6D, 0x87, 0xB1, 0x71, 0x8F, 0x38, 0x6A, 0x34, 0xDC } } } }, + { UNK_LANG, kPlatformFMTowns, { 0x00000967, 0x0002101A, { { 0x09, 0xC7, 0xB7, 0x2A, 0x76, 0xF1, 0x4B, 0x87, 0xC5, 0x83, 0xFF, 0xF3, 0xDB, 0x3C, 0x66, 0x60 } } } }, + { UNK_LANG, kPlatformPC98, { 0x000006F1, 0x0001545E, { { 0xD3, 0x8A, 0xA1, 0xD4, 0x83, 0x77, 0x96, 0x6D, 0x87, 0xB1, 0x71, 0x8F, 0x38, 0x6A, 0x34, 0xDC } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameSfxIndexProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000358, 0x000074F4, { { 0xC8, 0x30, 0x1D, 0x9C, 0xFC, 0xF8, 0xD5, 0xBA, 0x7E, 0xAB, 0x13, 0x3F, 0x43, 0x50, 0xFA, 0xC4 } } } }, // CD + + { UNK_LANG, kPlatformUnknown, { 0x00000358, 0x0000747E, { { 0x20, 0x99, 0x4D, 0xB8, 0xF2, 0x05, 0xF2, 0xA7, 0x07, 0x28, 0x97, 0xFB, 0x70, 0x1F, 0x2A, 0x73 } } } }, // floppy + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameTracksProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000007E, 0x00001E45, { { 0xC6, 0x52, 0xCC, 0x1A, 0x23, 0x3B, 0xDA, 0x03, 0xF3, 0xC2, 0x46, 0xDF, 0x01, 0xA3, 0x9E, 0x50 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameCDAProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000130, 0x00001B9D, { { 0x9E, 0xFB, 0x01, 0xE7, 0xBA, 0xE1, 0x4F, 0x3C, 0xC5, 0xB9, 0x75, 0x80, 0xEA, 0xAC, 0xB0, 0x0F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameTalkObjIndexProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000078, 0x00000A9C, { { 0x27, 0x65, 0xFA, 0xB1, 0xF8, 0x04, 0x7F, 0x93, 0x2B, 0x2D, 0x44, 0x3C, 0x95, 0x13, 0x50, 0xD2 } } } }, // floppy (English) + { UNK_LANG, kPlatformPC, { 0x00000078, 0x00000A53, { { 0x18, 0x5B, 0x79, 0x92, 0x54, 0xDB, 0x4B, 0x0C, 0x78, 0x89, 0x7C, 0x59, 0xBF, 0x53, 0x37, 0x14 } } } }, // floppy (German + French) + { UNK_LANG, kPlatformPC, { 0x00000078, 0x00000A7C, { { 0x33, 0x89, 0x69, 0xEF, 0x62, 0x94, 0x3A, 0xC0, 0xB2, 0xBA, 0xFB, 0x0C, 0x86, 0x2C, 0xAC, 0x5C } } } }, // floppy (Italian) + { UNK_LANG, kPlatformPC, { 0x00000084, 0x00000CD0, { { 0x82, 0x2E, 0xF4, 0xDD, 0x28, 0x75, 0xDD, 0x79, 0x78, 0x62, 0x55, 0x48, 0xDD, 0xF7, 0x16, 0x81 } } } }, // CD + + { UNK_LANG, kPlatformFMTowns, { 0x0000007A, 0x00000744, { { 0x74, 0x84, 0xB4, 0xA6, 0x9D, 0x91, 0xBF, 0x24, 0x1E, 0xD5, 0xDE, 0xD4, 0x73, 0x93, 0x1F, 0xE6 } } } }, + + { UNK_LANG, kPlatformPC98, { 0x00000078, 0x0000099D, { { 0x2F, 0x06, 0x8D, 0x4E, 0x76, 0x9E, 0x92, 0xFD, 0x43, 0xA4, 0x12, 0xED, 0xBA, 0x30, 0xFE, 0x94 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameTimJpStringsProvider[] = { + { UNK_LANG, kPlatformFMTowns, { 0x0000002D, 0x00001302, { { 0x15, 0x29, 0xFD, 0xB1, 0xEB, 0xC0, 0x00, 0xA4, 0x19, 0xDA, 0xC7, 0x2E, 0x17, 0x0F, 0x3F, 0xB7 } } } }, + { UNK_LANG, kPlatformPC98, { 0x0000002C, 0x00001302, { { 0xAB, 0xBA, 0xC8, 0x2A, 0xD0, 0xD1, 0x1C, 0xEA, 0x6F, 0x35, 0x12, 0x5D, 0x85, 0xFB, 0x92, 0x84 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameShapeAnimDataProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000348, 0x0001AAEB, { { 0x67, 0xD1, 0x03, 0xBF, 0x4B, 0xEC, 0x80, 0x26, 0x5D, 0x1D, 0x0E, 0x5B, 0xF1, 0xE8, 0x4C, 0x64 } } } }, // CD + + { UNK_LANG, kPlatformUnknown, { 0x00000348, 0x00002473, { { 0xBC, 0x18, 0x51, 0xFA, 0x51, 0x1D, 0x24, 0x7D, 0x44, 0xD0, 0xE2, 0x38, 0x31, 0x33, 0x3B, 0x56 } } } }, // floppy + FM-TOWNS + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k2IngameTlkDemoStringsProvider[] = { + { EN_ANY, kPlatformPC, { 0x000000CB, 0x00004741, { { 0xF3, 0x54, 0x37, 0xEE, 0x61, 0x9E, 0xE0, 0x82, 0x64, 0x8B, 0xF3, 0x53, 0xC7, 0x2F, 0x49, 0x1F } } } }, + { FR_FRA, kPlatformPC, { 0x000000BE, 0x00004327, { { 0x8C, 0xF2, 0x5E, 0x85, 0xDA, 0xA1, 0x91, 0x90, 0xE5, 0xC7, 0x2A, 0xBA, 0x48, 0xC3, 0x9A, 0xCA } } } }, + { DE_DEU, kPlatformPC, { 0x000000DC, 0x00004C7B, { { 0xC9, 0x75, 0x3A, 0x4A, 0xF4, 0xB0, 0xE8, 0x61, 0x90, 0x74, 0x34, 0x84, 0x53, 0x54, 0xA2, 0x4F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3MainMenuStringsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000B0, 0x00003E75, { { 0xA7, 0x91, 0x9B, 0x61, 0x31, 0x12, 0x74, 0xB5, 0x4B, 0x4F, 0x8A, 0x44, 0xA9, 0xB1, 0x03, 0xC0 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3MusicFilesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000001D5, 0x00007436, { { 0x27, 0xC2, 0x96, 0xFF, 0x22, 0xEC, 0xB5, 0x26, 0xF9, 0x4F, 0x04, 0xDD, 0x58, 0x17, 0xFE, 0xC6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3ScoreTableProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000000C8, 0x0000038F, { { 0x4E, 0x2E, 0xC3, 0xD9, 0x13, 0xA0, 0x74, 0x7E, 0xAB, 0xA1, 0x23, 0x2F, 0x11, 0x35, 0x4D, 0xA5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3SfxFilesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000008BF, 0x0001A766, { { 0xBD, 0x5D, 0x65, 0x5D, 0xC4, 0x34, 0xDF, 0x36, 0xF5, 0xC0, 0xE8, 0x7B, 0x51, 0x9F, 0xE5, 0xC7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3SfxMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000004C0, 0x0000C4F9, { { 0x06, 0x61, 0x45, 0x38, 0xC2, 0x6A, 0x12, 0x23, 0x55, 0x2C, 0x7F, 0xA5, 0xE2, 0x79, 0x81, 0x9E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3ItemAnimDataProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000001C8, 0x00003777, { { 0x8F, 0xE8, 0x80, 0x4A, 0x88, 0x83, 0xC0, 0x48, 0x55, 0x47, 0x81, 0xD3, 0xB7, 0xD5, 0x09, 0x8F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3ItemMagicTableProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x00000F9E, { { 0x87, 0xA7, 0xC0, 0xA2, 0x0F, 0xA3, 0x5B, 0x08, 0x76, 0x6F, 0x02, 0x68, 0x13, 0x17, 0x3B, 0x76 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData k3ItemStringMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x0000003C, { { 0x4C, 0xA7, 0xAA, 0xB0, 0x3C, 0xCC, 0x78, 0x91, 0x0A, 0xF2, 0x7F, 0x25, 0x80, 0xB3, 0x74, 0x74 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngamePakFilesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000088, 0x0000224F, { { 0xDA, 0x24, 0x18, 0xA3, 0xEF, 0x16, 0x70, 0x8F, 0xA8, 0xC2, 0x2E, 0xC2, 0xED, 0x39, 0x03, 0xD1 } } } }, + { UNK_LANG, kPlatformPC98, { 0x00000084, 0x00002125, { { 0x7A, 0x89, 0xE2, 0x36, 0xEC, 0x6F, 0x52, 0x2B, 0xEF, 0xBA, 0x3D, 0x28, 0x54, 0xDA, 0xFB, 0x72 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharacterDefsProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000492, 0x000046B0, { { 0x7A, 0x94, 0x8B, 0xC6, 0xF7, 0xF1, 0x2F, 0xF3, 0xBC, 0x1B, 0x0B, 0x4E, 0x00, 0xC9, 0x44, 0x58 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000492, 0x000047FD, { { 0x8C, 0x0B, 0x8B, 0xCE, 0xE0, 0xB0, 0x8F, 0xA9, 0x06, 0xC3, 0x98, 0xE6, 0x2E, 0x09, 0xB6, 0x93 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x00000492, 0x00004ACD, { { 0xDF, 0x87, 0xFE, 0x89, 0x59, 0xCC, 0x01, 0xD7, 0xC7, 0xEB, 0x16, 0xA4, 0x09, 0xAF, 0x5D, 0xC0 } } } }, // CD + { UNK_LANG, kPlatformPC98, { 0x00000492, 0x00005893, { { 0x7C, 0x7E, 0xFB, 0x80, 0xD9, 0xB6, 0x16, 0x87, 0x80, 0xB7, 0x46, 0x9B, 0x96, 0x1A, 0x6A, 0xBE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngameSfxFilesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000008F2, 0x0001E5B6, { { 0x63, 0x5E, 0x37, 0xAA, 0x27, 0x80, 0x4C, 0x85, 0xB1, 0x9D, 0x7B, 0x1D, 0x64, 0xA3, 0xEB, 0x97 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x000008F2, 0x0001E5B7, { { 0x9E, 0xC8, 0xE8, 0x19, 0x2F, 0x58, 0x0B, 0xC7, 0x2D, 0x41, 0x72, 0xE7, 0xF4, 0x80, 0x03, 0xCB } } } }, // CD + { UNK_LANG, kPlatformPC98, { 0x000008EF, 0x0001E585, { { 0x85, 0x81, 0x5C, 0xA4, 0x34, 0x44, 0xF4, 0x58, 0xF9, 0x82, 0xEE, 0x0F, 0x6A, 0x0D, 0xA2, 0x7F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngameSfxIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x000003E8, 0x0000E8D2, { { 0x19, 0x39, 0x17, 0xED, 0xAE, 0xDC, 0x7A, 0xAC, 0x45, 0x5F, 0x2D, 0xCD, 0x65, 0x8D, 0xAD, 0xAE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMusicTrackMapProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000000F0, 0x0000210D, { { 0x55, 0x25, 0x3E, 0x35, 0xD2, 0xD8, 0x13, 0xE3, 0x1D, 0xB1, 0xB3, 0x00, 0x2E, 0x17, 0x91, 0x2F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngameGMSfxIndexProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000000FA, 0x00006281, { { 0x25, 0x89, 0xB0, 0x3B, 0x12, 0x09, 0x02, 0xF6, 0xFE, 0x76, 0xD5, 0xC9, 0x5B, 0x88, 0xAC, 0xAA } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngameMT32SfxIndexProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000000FA, 0x00006579, { { 0x16, 0x40, 0x1C, 0x09, 0x69, 0xA9, 0x0D, 0x6D, 0x4B, 0x0C, 0x99, 0xF0, 0x40, 0x5D, 0xBB, 0x6E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolIngamePcSpkSfxIndexProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000000FA, 0x00005EFC, { { 0xA3, 0x5C, 0x69, 0xED, 0x13, 0xEC, 0x08, 0x0E, 0xFA, 0x72, 0x83, 0x0D, 0xD7, 0x8D, 0x9C, 0x70 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolSpellPropertiesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000118, 0x00000B06, { { 0x27, 0x69, 0x53, 0x01, 0xA0, 0xE3, 0x76, 0xAA, 0x33, 0xA4, 0x52, 0x11, 0x52, 0xB1, 0x0E, 0xDA } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolGameShapeMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000114, 0x000038D3, { { 0xB2, 0x8A, 0x5D, 0x9A, 0x51, 0x63, 0x4D, 0x65, 0xE4, 0xF5, 0xBA, 0x88, 0x70, 0x6C, 0xA6, 0xF8 } } } }, // floppy + PC98 + { UNK_LANG, kPlatformPC, { 0x00000114, 0x00003B97, { { 0x29, 0xE5, 0x0F, 0x51, 0xF0, 0x10, 0x35, 0x3E, 0x70, 0x3A, 0xAA, 0xFE, 0xD7, 0xD5, 0xAA, 0x9F } } } }, // CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolSceneItemOffsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000008, 0x00000300, { { 0x69, 0x80, 0x5A, 0x3E, 0x63, 0xC1, 0x04, 0x60, 0x09, 0x2F, 0x49, 0xD7, 0x26, 0x32, 0xAA, 0xE2 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharInvIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x00000006, { { 0x19, 0x79, 0x4E, 0xFC, 0x05, 0x14, 0x89, 0x23, 0xEB, 0xCA, 0x94, 0x50, 0xE8, 0xD3, 0x81, 0x24 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharInvDefsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000058, 0x00001D7A, { { 0x25, 0xE4, 0xEB, 0x6D, 0xBE, 0xEA, 0xBD, 0x9A, 0x9F, 0xA5, 0x9E, 0xEB, 0x3D, 0x03, 0x1D, 0x72 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharDefsManProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x0000003D, { { 0xEB, 0x82, 0x32, 0x9D, 0x76, 0xC8, 0x3D, 0x5E, 0x8C, 0x26, 0x53, 0xDF, 0xC1, 0xFD, 0x0F, 0xC5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharDefsWomanProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x0000003D, { { 0xEB, 0x82, 0x32, 0x9D, 0x76, 0xC8, 0x3D, 0x5E, 0x8C, 0x26, 0x53, 0xDF, 0xC1, 0xFD, 0x0F, 0xC5 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharDefsKieranProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x000002E3, { { 0xBF, 0xB1, 0x0F, 0x40, 0xBF, 0xA1, 0xD0, 0x2B, 0xC9, 0x80, 0x35, 0x40, 0xA9, 0xA3, 0x01, 0xC8 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCharDefsAkshelProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x000002FB, { { 0x47, 0x3C, 0x07, 0x15, 0x20, 0xE6, 0x90, 0x59, 0x55, 0xF2, 0xA7, 0xC3, 0x27, 0x22, 0xAB, 0xDC } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolExpRequirementsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000002C, 0x00000C0A, { { 0x3F, 0x36, 0xFA, 0xE3, 0xB0, 0x76, 0x5E, 0xFF, 0xE9, 0xBA, 0xDF, 0xD0, 0x9D, 0xFF, 0xDD, 0x27 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterModifiersProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000018, 0x000002C6, { { 0x38, 0x9A, 0x8B, 0x50, 0xD2, 0x9B, 0x95, 0x38, 0x91, 0x02, 0xA9, 0xBE, 0x78, 0xE5, 0x89, 0x65 } } } }, // floppy + PC98 + { UNK_LANG, kPlatformPC, { 0x00000018, 0x000002EE, { { 0x4E, 0x37, 0x56, 0xE3, 0x42, 0xB3, 0x15, 0x2C, 0x7E, 0x9B, 0x7E, 0x50, 0x32, 0x91, 0x55, 0xBE } } } }, // CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterShiftOffsetsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000020, 0x00000803, { { 0x30, 0x55, 0x74, 0x0D, 0xC7, 0x3B, 0xD9, 0x5C, 0x26, 0xF0, 0x4E, 0x8F, 0xE4, 0x4D, 0xCB, 0x2A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterDirFlagsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000010, 0x00000080, { { 0xE5, 0xA1, 0xE3, 0xCE, 0xA0, 0x5F, 0x15, 0xE9, 0x5B, 0x28, 0x90, 0xC0, 0xDF, 0x21, 0xEC, 0x24 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterScaleYProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001E, 0x00000982, { { 0xE2, 0x71, 0x5F, 0x57, 0x4A, 0x8F, 0x50, 0xDB, 0x3E, 0xDA, 0xAB, 0x10, 0xEB, 0xDB, 0x0D, 0x14 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterScaleXProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000020, 0x00000918, { { 0xF6, 0x14, 0xE6, 0x48, 0x4E, 0x5B, 0x43, 0xCC, 0xCE, 0x4E, 0x98, 0x71, 0x5A, 0xC2, 0x00, 0x1E } } } }, + { UNK_LANG, kPlatformPC98, { 0x0000001D, 0x000008D2, { { 0x1C, 0x25, 0x38, 0xE2, 0xBB, 0xB2, 0xDB, 0x93, 0x1B, 0x25, 0xB6, 0x89, 0xA9, 0x9B, 0x0A, 0xFE } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMonsterScaleWHProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000082, 0x00001D2A, { { 0x85, 0x7E, 0x18, 0xDD, 0x74, 0x1C, 0x62, 0x6F, 0xF4, 0xE5, 0xAF, 0x65, 0xEC, 0x6A, 0x90, 0xAD } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolFlyingObjectShpProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000082, 0x00000252, { { 0xDE, 0x9D, 0x89, 0xAF, 0x0F, 0x50, 0x14, 0x60, 0x68, 0xAF, 0x19, 0xD8, 0x54, 0x8A, 0x36, 0x27 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolInventoryDescProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000016, 0x0000082D, { { 0x86, 0xB4, 0xB9, 0x50, 0xB6, 0xDA, 0x29, 0xB2, 0xC0, 0x0D, 0x34, 0x3F, 0x8D, 0x88, 0xAA, 0xE4 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolLevelShpListProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000007F, 0x00002090, { { 0x17, 0x31, 0x8A, 0xB5, 0x9B, 0x3A, 0xDA, 0x16, 0x9E, 0xE3, 0xD1, 0x5F, 0xB4, 0x7B, 0xB2, 0x25 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolLevelDatListProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000007F, 0x00001FB8, { { 0xF6, 0xE9, 0x98, 0x79, 0x51, 0xCA, 0xA0, 0x35, 0xE4, 0xD0, 0xA1, 0xCD, 0x23, 0x89, 0x7D, 0x11 } } } }, // floppy + PC98 + { UNK_LANG, kPlatformPC, { 0x000000FF, 0x000047EC, { { 0x0D, 0xA5, 0xFD, 0x8A, 0x33, 0xDB, 0x93, 0x43, 0xE2, 0x57, 0x35, 0xEC, 0xA6, 0xCF, 0x7A, 0xA1 } } } }, // CD + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCompassDefsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000100, 0x000030EF, { { 0x6F, 0xF0, 0x46, 0x6E, 0xB3, 0x72, 0xCF, 0xC7, 0xE3, 0xAF, 0xBE, 0x63, 0xA1, 0x1C, 0x33, 0x20 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolItemPricesProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000005C, 0x00001251, { { 0x18, 0x62, 0x5E, 0xE2, 0xE4, 0x2A, 0xB0, 0xA0, 0x8B, 0x8D, 0x9D, 0x07, 0x5F, 0x83, 0x53, 0xF7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolStashSetupProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000C, 0x0000001E, { { 0x1C, 0x93, 0x66, 0x56, 0xDB, 0xD7, 0xA4, 0xB3, 0xE7, 0x2F, 0xEA, 0x88, 0xE2, 0xC8, 0x79, 0xD0 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscUnk1Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000024, 0x00000A2A, { { 0xAC, 0x4E, 0x73, 0x2C, 0xB0, 0xEE, 0x24, 0x0E, 0x66, 0x8D, 0x48, 0xE5, 0xCA, 0x6B, 0x7F, 0x7F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscShapeIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000024, 0x00000728, { { 0x14, 0xBA, 0x6D, 0x5C, 0x7D, 0x20, 0x0D, 0x35, 0xA7, 0xB0, 0x8D, 0x2F, 0x1D, 0x2A, 0x49, 0xA4 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscOvlMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x0000001F, { { 0x9C, 0xF2, 0xCC, 0x48, 0x42, 0xC6, 0x76, 0x83, 0xD3, 0x1A, 0x43, 0x42, 0x7F, 0xEF, 0x19, 0x0F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscScaleWidthDataProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x00000ABE, { { 0x28, 0x9A, 0xAA, 0x16, 0xC4, 0xFD, 0x52, 0xA9, 0x76, 0x98, 0x72, 0x0C, 0x2D, 0xE4, 0xB0, 0x57 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscScaleHeightDataProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x000009E8, { { 0x25, 0x35, 0x07, 0xBC, 0xF9, 0x82, 0x8B, 0x5B, 0x67, 0x7C, 0x38, 0xD1, 0xF8, 0x35, 0x81, 0xC7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscXProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x00001468, { { 0x55, 0xC5, 0x30, 0x76, 0x0A, 0xDC, 0xEC, 0xAB, 0x68, 0x9B, 0x61, 0xF0, 0x58, 0x78, 0x56, 0xA6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscYProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000024, 0x00000282, { { 0x09, 0x98, 0x3A, 0x33, 0x15, 0xA1, 0x4A, 0xFF, 0x76, 0x19, 0x2B, 0xB1, 0x74, 0x89, 0xF4, 0x37 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscTileIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x00000099, { { 0x18, 0xD9, 0x39, 0x27, 0x5B, 0x34, 0xAE, 0x7C, 0xA9, 0xA9, 0xDB, 0x42, 0x49, 0x61, 0x6B, 0x37 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscUnk2Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000017, 0x000000D2, { { 0xDE, 0xDA, 0x75, 0x15, 0x2B, 0xDC, 0x90, 0x3F, 0xC9, 0x92, 0x04, 0x01, 0x23, 0x7A, 0xDA, 0x2E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoorShapeIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000017, 0x0000000A, { { 0x2E, 0xC4, 0xA1, 0x47, 0x7C, 0xAE, 0xAD, 0xD8, 0x8A, 0x72, 0x95, 0x2F, 0x18, 0xC5, 0x08, 0x19 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDimData1Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000144, 0x0001007D, { { 0x18, 0x3D, 0xA5, 0xF7, 0x1A, 0x5A, 0x90, 0xA7, 0x4E, 0x66, 0x1A, 0x4E, 0x0C, 0x69, 0x58, 0x31 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDimData2Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000289, 0x00001BC2, { { 0x7F, 0x9D, 0xD3, 0x5A, 0x57, 0x73, 0xEA, 0x37, 0x44, 0x5E, 0x1A, 0x88, 0xFB, 0xE8, 0xE8, 0x8F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscBlockMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000C, 0x00000012, { { 0x01, 0xEE, 0x32, 0xA6, 0x71, 0x15, 0x8D, 0xFB, 0x33, 0xF2, 0xD6, 0x8A, 0x30, 0x00, 0x10, 0x4B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDimMapProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000012, 0x00000014, { { 0x4D, 0x53, 0x2E, 0xF2, 0xA3, 0xF9, 0xE2, 0xEC, 0x44, 0xBE, 0x5F, 0x04, 0x91, 0xF8, 0xE1, 0x04 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscOvlIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000028, 0x00000048, { { 0x3E, 0x8E, 0x62, 0xAF, 0xD1, 0x28, 0x39, 0x73, 0x0D, 0xD8, 0x4A, 0xA7, 0xF4, 0xD7, 0x32, 0x25 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscBlockIndexProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000048, 0x00002200, { { 0xF4, 0x8B, 0x32, 0xC3, 0xD3, 0xFB, 0x46, 0xF2, 0xB8, 0x3A, 0x58, 0x39, 0x94, 0x57, 0x97, 0x4B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoor1Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000080, 0x00000348, { { 0xC6, 0x58, 0x8B, 0xFE, 0x18, 0x72, 0x47, 0xF1, 0xB6, 0x3A, 0x0F, 0xFB, 0x3D, 0x99, 0x74, 0xD0 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoorScaleProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000010, 0x0000024C, { { 0x8D, 0x83, 0x26, 0xEE, 0xDC, 0xF7, 0x13, 0xC0, 0xAA, 0x88, 0xC2, 0xAA, 0x66, 0xA7, 0x59, 0x41 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoor4Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000008, 0x00000103, { { 0x29, 0xC0, 0x4B, 0x7F, 0x36, 0x23, 0xBB, 0x38, 0x4C, 0x83, 0xC6, 0x9D, 0xB4, 0x8F, 0x29, 0x2E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoorXProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000480, 0x0001654D, { { 0x2A, 0x1F, 0xBF, 0xE3, 0xC4, 0xEF, 0x7E, 0xD1, 0x61, 0x51, 0xFE, 0x88, 0x8D, 0x1F, 0x59, 0x70 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolDscDoorYProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000480, 0x00026666, { { 0x06, 0xBF, 0xA4, 0xD4, 0x6E, 0x29, 0x42, 0xA2, 0xA0, 0x8E, 0x3C, 0x14, 0xF3, 0xD6, 0x3F, 0x87 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolScrollXTopProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x0000004B, { { 0x18, 0x1E, 0x6E, 0xE9, 0x34, 0xF0, 0x02, 0xC6, 0x57, 0x34, 0xDF, 0x55, 0xD9, 0x39, 0xE8, 0x98 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolScrollYTopProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x00000022, { { 0xF3, 0x20, 0x5A, 0xC1, 0xBB, 0x0C, 0x79, 0x52, 0x23, 0xC1, 0x36, 0x81, 0x70, 0x2F, 0x92, 0xFC } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolScrollXBottomProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x0000004B, { { 0x18, 0x1E, 0x6E, 0xE9, 0x34, 0xF0, 0x02, 0xC6, 0x57, 0x34, 0xDF, 0x55, 0xD9, 0x39, 0xE8, 0x98 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolScrollYBottomProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000000A, 0x0000003C, { { 0x5B, 0x4F, 0xB7, 0xB5, 0x55, 0xA2, 0x9A, 0x21, 0xEF, 0xB4, 0x98, 0x47, 0x05, 0x57, 0x49, 0x55 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonDefsProvider[] = { + { UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000CAAE, { { 0xC1, 0x83, 0x0D, 0xA0, 0x66, 0x16, 0x3D, 0x31, 0xCE, 0x30, 0x9F, 0x4E, 0x00, 0x65, 0x5A, 0xC8 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000C34E, { { 0x7F, 0x9A, 0x0F, 0x28, 0x1A, 0x8F, 0x03, 0x46, 0x48, 0xEB, 0xC9, 0xB9, 0x23, 0x29, 0x5E, 0x50 } } } }, // floppy + { UNK_LANG, kPlatformPC, { 0x0000082A, 0x0000C47B, { { 0xDF, 0x1A, 0x18, 0x1F, 0x58, 0x05, 0x1F, 0x56, 0xD8, 0x6D, 0xBB, 0x93, 0xEC, 0x35, 0x9D, 0xA5 } } } }, // CD + { UNK_LANG, kPlatformPC98, { 0x0000082A, 0x0000AB58, { { 0xDD, 0x2B, 0xA9, 0x54, 0x60, 0x25, 0x2C, 0x74, 0xF8, 0x5D, 0xC6, 0xD2, 0x2C, 0x1A, 0x24, 0x44 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList1Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000050, 0x00000A37, { { 0x0F, 0x73, 0xEC, 0xDD, 0xAB, 0xFF, 0x49, 0x46, 0x5E, 0x8F, 0x0D, 0xC3, 0xE7, 0x1B, 0x89, 0x51 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList2Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001E, 0x00000522, { { 0xEA, 0x41, 0x46, 0xE2, 0xFE, 0xAA, 0x7D, 0x5E, 0x89, 0x7F, 0xBF, 0x9B, 0x30, 0x60, 0x74, 0xF3 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList3Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000004, 0x0000023E, { { 0x70, 0xAA, 0xCA, 0xAC, 0x5C, 0x21, 0xCF, 0xA5, 0xBF, 0x7F, 0x5F, 0xBC, 0xF1, 0x24, 0x8A, 0xAF } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList4Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001E, 0x0000054D, { { 0x19, 0x2A, 0xBE, 0x7F, 0x94, 0x10, 0xA0, 0x60, 0x2A, 0x33, 0xD6, 0x11, 0x85, 0xF0, 0xA4, 0xA9 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList5Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000020, 0x0000045D, { { 0xE3, 0x7C, 0xC2, 0x36, 0x21, 0x46, 0xDB, 0xF3, 0xDD, 0x38, 0x4B, 0x40, 0xE0, 0x35, 0x09, 0xC3 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList6Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000001C, 0x000004C4, { { 0x21, 0x7C, 0x29, 0x3F, 0x95, 0x6F, 0x91, 0x8C, 0xB2, 0x30, 0x09, 0xA6, 0x7B, 0x48, 0x44, 0x8F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList7Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000006, 0x0000021D, { { 0xDC, 0xCE, 0x1B, 0xEB, 0x11, 0x6D, 0xDE, 0x37, 0x17, 0xC8, 0x06, 0x51, 0xC3, 0x0C, 0xCB, 0xA6 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolButtonList8Provider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000004, 0x00000253, { { 0x0C, 0x7B, 0x10, 0x99, 0x93, 0xD0, 0x33, 0xCA, 0xAB, 0x8D, 0x7E, 0x24, 0xE5, 0x7E, 0x6C, 0x91 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolLegendDataProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000030, 0x00000858, { { 0x63, 0x5E, 0x60, 0xC7, 0x62, 0x2C, 0x5D, 0x8F, 0x74, 0x71, 0x98, 0xB7, 0x09, 0xD2, 0x51, 0xC7 } } } }, + { UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x00000A52, { { 0x81, 0xC5, 0xA4, 0xE7, 0x60, 0xDA, 0xD6, 0x5E, 0x19, 0xAB, 0xF3, 0xC7, 0xDD, 0xDB, 0x92, 0x5E } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMapCursorOvlProvider[] = { + { UNK_LANG, kPlatformPC, { 0x00000019, 0x000009CD, { { 0xF6, 0xD2, 0xFA, 0x36, 0x62, 0x95, 0x1D, 0x99, 0x7F, 0x11, 0x5F, 0xA8, 0x4D, 0x47, 0x72, 0x40 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolMapStringIdProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x0000003C, 0x00000CFB, { { 0xE3, 0xC3, 0x41, 0x06, 0xD1, 0x71, 0x77, 0x78, 0xAD, 0x39, 0xAE, 0x2C, 0x16, 0x21, 0x45, 0xB7 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolSpellbookAnimProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000038, 0x000003A1, { { 0x50, 0xA0, 0xF6, 0xA7, 0x53, 0x96, 0x86, 0x49, 0xB0, 0x8D, 0xA8, 0xB2, 0x2D, 0x9A, 0xE2, 0x1F } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolSpellbookCoordsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000018, 0x0000018F, { { 0xA5, 0xF6, 0x8A, 0x58, 0x9A, 0xC7, 0x3C, 0x3A, 0xB5, 0x87, 0x89, 0x87, 0x73, 0x51, 0x9B, 0x1B } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolHealShapeFramesProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000050, 0x000000F4, { { 0xC9, 0x6E, 0x39, 0xE1, 0xD7, 0xAD, 0x10, 0x4F, 0xE2, 0xFE, 0xDC, 0xAD, 0x00, 0x9D, 0x41, 0xEF } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolLightningDefsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000014, 0x00000385, { { 0x68, 0x39, 0x65, 0xCB, 0xA9, 0x80, 0x90, 0xFB, 0xDD, 0x77, 0x0C, 0x76, 0x5A, 0xB5, 0x05, 0x03 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolFireballCoordsProvider[] = { + { UNK_LANG, kPlatformUnknown, { 0x00000200, 0x0000FD81, { { 0xB3, 0xE0, 0x6F, 0x89, 0xCD, 0xE5, 0xA9, 0x6A, 0x4B, 0x61, 0x7A, 0x3F, 0x47, 0x26, 0x73, 0x58 } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolCreditsProvider[] = { + { JA_JPN , kPlatformPC98, { 0x000005E7, 0x0001A1B0, { { 0x2A, 0xD0, 0x38, 0x84, 0x0C, 0x38, 0xCB, 0x52, 0x5D, 0x82, 0xBE, 0x03, 0x76, 0xFA, 0x0A, 0x4A } } } }, + + EXTRACT_END_ENTRY +}; + +const ExtractEntrySearchData kLolHistoryProvider[] = { + { UNK_LANG, kPlatformPC, { 0x000001D1, 0x00007F9B, { { 0x25, 0x10, 0x86, 0x40, 0xAC, 0x53, 0xFE, 0x11, 0x4D, 0xE2, 0xD9, 0x35, 0xD6, 0x89, 0xBB, 0x09 } } } }, + + EXTRACT_END_ENTRY +}; + +// Provider tables + +struct ExtractEntry { + int id; + const ExtractEntrySearchData *providers; +}; + +const ExtractEntry extractProviders[] = { + { k1ForestSeq, k1ForestSeqProvider }, + { k1KallakWritingSeq, k1KallakWritingSeqProvider }, + { k1KyrandiaLogoSeq, k1KyrandiaLogoSeqProvider }, + { k1KallakMalcolmSeq, k1KallakMalcolmSeqProvider }, + { k1MalcolmTreeSeq, k1MalcolmTreeSeqProvider }, + { k1WestwoodLogoSeq, k1WestwoodLogoSeqProvider }, + { k1Demo1Seq, k1Demo1SeqProvider }, + { k1Demo2Seq, k1Demo2SeqProvider }, + { k1Demo3Seq, k1Demo3SeqProvider }, + { k1Demo4Seq, k1Demo4SeqProvider }, + { k1AmuleteAnimSeq, k1AmuleteAnimSeqProvider }, + { k1OutroReunionSeq, k1OutroReunionSeqProvider }, + { k1IntroCPSStrings, k1IntroCPSStringsProvider }, + { k1IntroCOLStrings, k1IntroCOLStringsProvider }, + { k1IntroWSAStrings, k1IntroWSAStringsProvider }, + { k1IntroStrings, k1IntroStringsProvider }, + { k1OutroHomeString, k1OutroHomeStringProvider }, + { k1RoomFilenames, k1RoomFilenamesProvider }, + { k1RoomList, k1RoomListProvider }, + { k1CharacterImageFilenames, k1CharacterImageFilenamesProvider }, + { k1AudioTracks, k1AudioTracksProvider }, + { k1AudioTracksIntro, k1AudioTracksIntroProvider }, + { k1ItemNames, k1ItemNamesProvider }, + { k1TakenStrings, k1TakenStringsProvider }, + { k1PlacedStrings, k1PlacedStringsProvider }, + { k1DroppedStrings, k1DroppedStringsProvider }, + { k1NoDropStrings, k1NoDropStringsProvider }, + { k1PutDownString, k1PutDownStringProvider }, + { k1WaitAmuletString, k1WaitAmuletStringProvider }, + { k1BlackJewelString, k1BlackJewelStringProvider }, + { k1PoisonGoneString, k1PoisonGoneStringProvider }, + { k1HealingTipString, k1HealingTipStringProvider }, + { k1WispJewelStrings, k1WispJewelStringsProvider }, + { k1MagicJewelStrings, k1MagicJewelStringsProvider }, + { k1ThePoisonStrings, k1ThePoisonStringsProvider }, + { k1FluteStrings, k1FluteStringsProvider }, + { k1FlaskFullString, k1FlaskFullStringProvider }, + { k1FullFlaskString, k1FullFlaskStringProvider }, + { k1VeryCleverString, k1VeryCleverStringProvider }, + { k1NewGameString, k1NewGameStringProvider }, + { k1DefaultShapes, k1DefaultShapesProvider }, + { k1Healing1Shapes, k1Healing1ShapesProvider }, + { k1Healing2Shapes, k1Healing2ShapesProvider }, + { k1PoisonDeathShapes, k1PoisonDeathShapesProvider }, + { k1FluteShapes, k1FluteShapesProvider }, + { k1Winter1Shapes, k1Winter1ShapesProvider }, + { k1Winter2Shapes, k1Winter2ShapesProvider }, + { k1Winter3Shapes, k1Winter3ShapesProvider }, + { k1DrinkShapes, k1DrinkShapesProvider }, + { k1WispShapes, k1WispShapesProvider }, + { k1MagicAnimShapes, k1MagicAnimShapesProvider }, + { k1BranStoneShapes, k1BranStoneShapesProvider }, + { k1SpecialPalette1, k1SpecialPalette1Provider }, + { k1SpecialPalette2, k1SpecialPalette2Provider }, + { k1SpecialPalette3, k1SpecialPalette3Provider }, + { k1SpecialPalette4, k1SpecialPalette4Provider }, + { k1SpecialPalette5, k1SpecialPalette5Provider }, + { k1SpecialPalette6, k1SpecialPalette6Provider }, + { k1SpecialPalette7, k1SpecialPalette7Provider }, + { k1SpecialPalette8, k1SpecialPalette8Provider }, + { k1SpecialPalette9, k1SpecialPalette9Provider }, + { k1SpecialPalette10, k1SpecialPalette10Provider }, + { k1SpecialPalette11, k1SpecialPalette11Provider }, + { k1SpecialPalette12, k1SpecialPalette12Provider }, + { k1SpecialPalette13, k1SpecialPalette13Provider }, + { k1SpecialPalette14, k1SpecialPalette14Provider }, + { k1SpecialPalette15, k1SpecialPalette15Provider }, + { k1SpecialPalette16, k1SpecialPalette16Provider }, + { k1SpecialPalette17, k1SpecialPalette17Provider }, + { k1SpecialPalette18, k1SpecialPalette18Provider }, + { k1SpecialPalette19, k1SpecialPalette19Provider }, + { k1SpecialPalette20, k1SpecialPalette20Provider }, + { k1SpecialPalette21, k1SpecialPalette21Provider }, + { k1SpecialPalette22, k1SpecialPalette22Provider }, + { k1SpecialPalette23, k1SpecialPalette23Provider }, + { k1SpecialPalette24, k1SpecialPalette24Provider }, + { k1SpecialPalette25, k1SpecialPalette25Provider }, + { k1SpecialPalette26, k1SpecialPalette26Provider }, + { k1SpecialPalette27, k1SpecialPalette27Provider }, + { k1SpecialPalette28, k1SpecialPalette28Provider }, + { k1SpecialPalette29, k1SpecialPalette29Provider }, + { k1SpecialPalette30, k1SpecialPalette30Provider }, + { k1SpecialPalette31, k1SpecialPalette31Provider }, + { k1SpecialPalette32, k1SpecialPalette32Provider }, + { k1SpecialPalette33, k1SpecialPalette33Provider }, + { k1GUIStrings, k1GUIStringsProvider }, + { k1ConfigStrings, k1ConfigStringsProvider }, + { k1TownsMusicFadeTable, k1TownsMusicFadeTableProvider }, + { k1TownsSFXwdTable, k1TownsSFXwdTableProvider }, + { k1TownsSFXbtTable, k1TownsSFXbtTableProvider }, + { k1TownsCDATable, k1TownsCDATableProvider }, + { k1PC98StoryStrings, k1PC98StoryStringsProvider }, + { k1PC98IntroSfx, k1PC98IntroSfxProvider }, + { k1CreditsStrings, k1CreditsStringsProvider }, + { k1AmigaIntroSFXTable, k1AmigaIntroSFXTableProvider }, + { k1AmigaGameSFXTable, k1AmigaGameSFXTableProvider }, + { k2SeqplayPakFiles, k2SeqplayPakFilesProvider }, + { k2SeqplayStrings, k2SeqplayStringsProvider }, + { k2SeqplaySfxFiles, k2SeqplaySfxFilesProvider }, + { k2SeqplayTlkFiles, k2SeqplayTlkFilesProvider }, + { k2SeqplaySeqData, k2SeqplaySeqDataProvider }, + { k2SeqplayCredits, k2SeqplayCreditsProvider }, + { k2SeqplayCreditsSpecial, k2SeqplayCreditsSpecialProvider }, + { k2SeqplayIntroTracks, k2SeqplayIntroTracksProvider }, + { k2SeqplayFinaleTracks, k2SeqplayFinaleTracksProvider }, + { k2SeqplayIntroCDA, k2SeqplayIntroCDAProvider }, + { k2SeqplayFinaleCDA, k2SeqplayFinaleCDAProvider }, + { k2SeqplayShapeAnimData, k2SeqplayShapeAnimDataProvider }, + { k2IngamePakFiles, k2IngamePakFilesProvider }, + { k2IngameSfxFiles, k2IngameSfxFilesProvider }, + { k2IngameSfxIndex, k2IngameSfxIndexProvider }, + { k2IngameTracks, k2IngameTracksProvider }, + { k2IngameCDA, k2IngameCDAProvider }, + { k2IngameTalkObjIndex, k2IngameTalkObjIndexProvider }, + { k2IngameTimJpStrings, k2IngameTimJpStringsProvider }, + { k2IngameShapeAnimData, k2IngameShapeAnimDataProvider }, + { k2IngameTlkDemoStrings, k2IngameTlkDemoStringsProvider }, + { k3MainMenuStrings, k3MainMenuStringsProvider }, + { k3MusicFiles, k3MusicFilesProvider }, + { k3ScoreTable, k3ScoreTableProvider }, + { k3SfxFiles, k3SfxFilesProvider }, + { k3SfxMap, k3SfxMapProvider }, + { k3ItemAnimData, k3ItemAnimDataProvider }, + { k3ItemMagicTable, k3ItemMagicTableProvider }, + { k3ItemStringMap, k3ItemStringMapProvider }, + { kLolIngamePakFiles, kLolIngamePakFilesProvider }, + { kLolCharacterDefs, kLolCharacterDefsProvider }, + { kLolIngameSfxFiles, kLolIngameSfxFilesProvider }, + { kLolIngameSfxIndex, kLolIngameSfxIndexProvider }, + { kLolMusicTrackMap, kLolMusicTrackMapProvider }, + { kLolIngameGMSfxIndex, kLolIngameGMSfxIndexProvider }, + { kLolIngameMT32SfxIndex, kLolIngameMT32SfxIndexProvider }, + { kLolIngamePcSpkSfxIndex, kLolIngamePcSpkSfxIndexProvider }, + { kLolSpellProperties, kLolSpellPropertiesProvider }, + { kLolGameShapeMap, kLolGameShapeMapProvider }, + { kLolSceneItemOffs, kLolSceneItemOffsProvider }, + { kLolCharInvIndex, kLolCharInvIndexProvider }, + { kLolCharInvDefs, kLolCharInvDefsProvider }, + { kLolCharDefsMan, kLolCharDefsManProvider }, + { kLolCharDefsWoman, kLolCharDefsWomanProvider }, + { kLolCharDefsKieran, kLolCharDefsKieranProvider }, + { kLolCharDefsAkshel, kLolCharDefsAkshelProvider }, + { kLolExpRequirements, kLolExpRequirementsProvider }, + { kLolMonsterModifiers, kLolMonsterModifiersProvider }, + { kLolMonsterShiftOffsets, kLolMonsterShiftOffsetsProvider }, + { kLolMonsterDirFlags, kLolMonsterDirFlagsProvider }, + { kLolMonsterScaleY, kLolMonsterScaleYProvider }, + { kLolMonsterScaleX, kLolMonsterScaleXProvider }, + { kLolMonsterScaleWH, kLolMonsterScaleWHProvider }, + { kLolFlyingObjectShp, kLolFlyingObjectShpProvider }, + { kLolInventoryDesc, kLolInventoryDescProvider }, + { kLolLevelShpList, kLolLevelShpListProvider }, + { kLolLevelDatList, kLolLevelDatListProvider }, + { kLolCompassDefs, kLolCompassDefsProvider }, + { kLolItemPrices, kLolItemPricesProvider }, + { kLolStashSetup, kLolStashSetupProvider }, + { kLolDscUnk1, kLolDscUnk1Provider }, + { kLolDscShapeIndex, kLolDscShapeIndexProvider }, + { kLolDscOvlMap, kLolDscOvlMapProvider }, + { kLolDscScaleWidthData, kLolDscScaleWidthDataProvider }, + { kLolDscScaleHeightData, kLolDscScaleHeightDataProvider }, + { kLolDscX, kLolDscXProvider }, + { kLolDscY, kLolDscYProvider }, + { kLolDscTileIndex, kLolDscTileIndexProvider }, + { kLolDscUnk2, kLolDscUnk2Provider }, + { kLolDscDoorShapeIndex, kLolDscDoorShapeIndexProvider }, + { kLolDscDimData1, kLolDscDimData1Provider }, + { kLolDscDimData2, kLolDscDimData2Provider }, + { kLolDscBlockMap, kLolDscBlockMapProvider }, + { kLolDscDimMap, kLolDscDimMapProvider }, + { kLolDscOvlIndex, kLolDscOvlIndexProvider }, + { kLolDscBlockIndex, kLolDscBlockIndexProvider }, + { kLolDscDoor1, kLolDscDoor1Provider }, + { kLolDscDoorScale, kLolDscDoorScaleProvider }, + { kLolDscDoor4, kLolDscDoor4Provider }, + { kLolDscDoorX, kLolDscDoorXProvider }, + { kLolDscDoorY, kLolDscDoorYProvider }, + { kLolScrollXTop, kLolScrollXTopProvider }, + { kLolScrollYTop, kLolScrollYTopProvider }, + { kLolScrollXBottom, kLolScrollXBottomProvider }, + { kLolScrollYBottom, kLolScrollYBottomProvider }, + { kLolButtonDefs, kLolButtonDefsProvider }, + { kLolButtonList1, kLolButtonList1Provider }, + { kLolButtonList2, kLolButtonList2Provider }, + { kLolButtonList3, kLolButtonList3Provider }, + { kLolButtonList4, kLolButtonList4Provider }, + { kLolButtonList5, kLolButtonList5Provider }, + { kLolButtonList6, kLolButtonList6Provider }, + { kLolButtonList7, kLolButtonList7Provider }, + { kLolButtonList8, kLolButtonList8Provider }, + { kLolLegendData, kLolLegendDataProvider }, + { kLolMapCursorOvl, kLolMapCursorOvlProvider }, + { kLolMapStringId, kLolMapStringIdProvider }, + { kLolSpellbookAnim, kLolSpellbookAnimProvider }, + { kLolSpellbookCoords, kLolSpellbookCoordsProvider }, + { kLolHealShapeFrames, kLolHealShapeFramesProvider }, + { kLolLightningDefs, kLolLightningDefsProvider }, + { kLolFireballCoords, kLolFireballCoordsProvider }, + { kLolCredits, kLolCreditsProvider }, + { kLolHistory, kLolHistoryProvider }, + { -1, NULL } +}; + +} // end of anonymous namespace + +ExtractEntryList getProvidersForId(int id) { + ExtractEntryList list; + + for (const ExtractEntry *p = extractProviders; p->id != -1; ++p) { + if (p->id == id) { + for (const ExtractEntrySearchData *d = p->providers; d->hint.size != 0; ++d) + list.push_back(*d); + } + } + + return list; +} + diff --git a/devtools/create_kyradat/tables.h b/devtools/create_kyradat/tables.h new file mode 100644 index 0000000000..c990043f5d --- /dev/null +++ b/devtools/create_kyradat/tables.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef CREATE_KYRADAT_TABLES_H +#define CREATE_KYRADAT_TABLES_H + +#include "search.h" +#include "util.h" + +#include <list> + +struct ExtractEntrySearchData { + int lang; + int platform; + + SearchData hint; +}; + +typedef std::list<ExtractEntrySearchData> ExtractEntryList; +ExtractEntryList getProvidersForId(int id); + +#endif + diff --git a/devtools/create_kyradat/util.cpp b/devtools/create_kyradat/util.cpp new file mode 100644 index 0000000000..702a36bc0e --- /dev/null +++ b/devtools/create_kyradat/util.cpp @@ -0,0 +1,143 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "util.h" +#include <stdarg.h> + +#ifdef _MSC_VER + #define vsnprintf _vsnprintf +#endif + +void error(const char *s, ...) { + char buf[1024]; + va_list va; + + va_start(va, s); + vsnprintf(buf, 1024, s, va); + va_end(va); + + fprintf(stderr, "ERROR: %s!\n", buf); + + exit(1); +} + +void warning(const char *s, ...) { + char buf[1024]; + va_list va; + + va_start(va, s); + vsnprintf(buf, 1024, s, va); + va_end(va); + + fprintf(stderr, "WARNING: %s!\n", buf); +} + +void debug(int level, const char *s, ...) { + char buf[1024]; + va_list va; + + va_start(va, s); + vsnprintf(buf, 1024, s, va); + va_end(va); + + fprintf(stderr, "DEBUG: %s!\n", buf); +} + +uint8 readByte(FILE *fp) { + return fgetc(fp); +} + +uint16 readUint16BE(FILE *fp) { + uint16 ret = 0; + ret |= fgetc(fp) << 8; + ret |= fgetc(fp); + return ret; +} + +uint16 readUint16LE(FILE *fp) { + uint16 ret = 0; + ret |= fgetc(fp); + ret |= fgetc(fp) << 8; + return ret; +} + +uint32 readUint32BE(FILE *fp) { + uint32 ret = 0; + ret |= fgetc(fp) << 24; + ret |= fgetc(fp) << 16; + ret |= fgetc(fp) << 8; + ret |= fgetc(fp); + return ret; +} + +uint32 readUint32LE(FILE *fp) { + uint32 ret = 0; + ret |= fgetc(fp); + ret |= fgetc(fp) << 8; + ret |= fgetc(fp) << 16; + ret |= fgetc(fp) << 24; + return ret; +} + +void writeByte(FILE *fp, uint8 b) { + fwrite(&b, 1, 1, fp); +} + +void writeUint16BE(FILE *fp, uint16 value) { + writeByte(fp, (uint8)(value >> 8)); + writeByte(fp, (uint8)(value)); +} + +void writeUint16LE(FILE *fp, uint16 value) { + writeByte(fp, (uint8)(value)); + writeByte(fp, (uint8)(value >> 8)); +} + +void writeUint32BE(FILE *fp, uint32 value) { + writeByte(fp, (uint8)(value >> 24)); + writeByte(fp, (uint8)(value >> 16)); + writeByte(fp, (uint8)(value >> 8)); + writeByte(fp, (uint8)(value)); +} + +void writeUint32LE(FILE *fp, uint32 value) { + writeByte(fp, (uint8)(value)); + writeByte(fp, (uint8)(value >> 8)); + writeByte(fp, (uint8)(value >> 16)); + writeByte(fp, (uint8)(value >> 24)); +} + +uint32 fileSize(FILE *fp) { + uint32 sz; + uint32 pos = ftell(fp); + fseek(fp, 0, SEEK_END); + sz = ftell(fp); + fseek(fp, pos, SEEK_SET); + return sz; +} + diff --git a/devtools/create_kyradat/util.h b/devtools/create_kyradat/util.h new file mode 100644 index 0000000000..077597ac07 --- /dev/null +++ b/devtools/create_kyradat/util.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef UTIL_H +#define UTIL_H + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/util.h" + +#ifdef WIN32 +#include <io.h> +#include <process.h> +#endif + + +/* File I/O */ +uint8 readByte(FILE *fp); +uint16 readUint16BE(FILE *fp); +uint16 readUint16LE(FILE *fp); +uint32 readUint32BE(FILE *fp); +uint32 readUint32LE(FILE *fp); +void writeByte(FILE *fp, uint8 b); +void writeUint16BE(FILE *fp, uint16 value); +void writeUint16LE(FILE *fp, uint16 value); +void writeUint32BE(FILE *fp, uint32 value); +void writeUint32LE(FILE *fp, uint32 value); +uint32 fileSize(FILE *fp); + +/* Misc stuff */ +void NORETURN_PRE error(const char *s, ...) NORETURN_POST; +void warning(const char *s, ...); +void debug(int level, const char *s, ...); + +using namespace Common; + +#endif |