aboutsummaryrefslogtreecommitdiff
path: root/devtools/create_kyradat
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/create_kyradat')
-rw-r--r--devtools/create_kyradat/create_kyradat.cpp1439
-rw-r--r--devtools/create_kyradat/create_kyradat.h315
-rw-r--r--devtools/create_kyradat/extract.cpp987
-rw-r--r--devtools/create_kyradat/extract.h78
-rw-r--r--devtools/create_kyradat/games.cpp990
-rw-r--r--devtools/create_kyradat/md5.cpp267
-rw-r--r--devtools/create_kyradat/md5.h43
-rw-r--r--devtools/create_kyradat/module.mk20
-rw-r--r--devtools/create_kyradat/pak.cpp250
-rw-r--r--devtools/create_kyradat/pak.h110
-rw-r--r--devtools/create_kyradat/search.cpp219
-rw-r--r--devtools/create_kyradat/search.h120
-rw-r--r--devtools/create_kyradat/tables.cpp1968
-rw-r--r--devtools/create_kyradat/tables.h45
-rw-r--r--devtools/create_kyradat/util.cpp143
-rw-r--r--devtools/create_kyradat/util.h59
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