aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2007-02-03 14:52:02 +0000
committerJohannes Schickel2007-02-03 14:52:02 +0000
commitde19c946282256074c121b8f893e717574dc9d2f (patch)
treef91372e7f0a8bdf906d67f6f1bbab6bd0d559651
parenta8ea78ce73f8061201995d012573da46b58d1575 (diff)
downloadscummvm-rg350-de19c946282256074c121b8f893e717574dc9d2f.tar.gz
scummvm-rg350-de19c946282256074c121b8f893e717574dc9d2f.tar.bz2
scummvm-rg350-de19c946282256074c121b8f893e717574dc9d2f.zip
Adding create_kyradat here now.
svn-id: r25349
-rw-r--r--tools/create_kyradat/Makefile29
-rw-r--r--tools/create_kyradat/create_kyradat.cpp601
-rw-r--r--tools/create_kyradat/create_kyradat.h202
-rw-r--r--tools/create_kyradat/eng.h190
-rw-r--r--tools/create_kyradat/esp.h39
-rw-r--r--tools/create_kyradat/fre.h79
-rw-r--r--tools/create_kyradat/ger.h80
-rw-r--r--tools/create_kyradat/md5.cpp261
-rw-r--r--tools/create_kyradat/md5.h40
-rw-r--r--tools/create_kyradat/misc.h207
-rw-r--r--tools/create_kyradat/pak.cpp244
-rw-r--r--tools/create_kyradat/pak.h107
-rw-r--r--tools/create_kyradat/util.c137
-rw-r--r--tools/create_kyradat/util.h265
14 files changed, 2481 insertions, 0 deletions
diff --git a/tools/create_kyradat/Makefile b/tools/create_kyradat/Makefile
new file mode 100644
index 0000000000..b90f8940b7
--- /dev/null
+++ b/tools/create_kyradat/Makefile
@@ -0,0 +1,29 @@
+CXX ?= g++
+CC ?= gcc
+
+LDFLAGS ?=
+CXXFLAGS ?= -O2
+CFLAGS ?= -O2
+CPPFLAGS ?=
+
+BIN=create_kyradat
+
+OBJS=create_kyradat.o pak.o md5.o util.o
+
+all: $(BIN)
+
+$(BIN): $(OBJS)
+ $(CXX) $(OBJS) $(LDFLAGS) -o $(BIN)
+
+clean:
+ rm -f $(BIN)
+ rm -f $(OBJS)
+
+create_kyradat.o: eng.h esp.h fre.h ger.h misc.h pak.h util.h md5.h
+pak.o: pak.h util.h
+
+%.o: %.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
+
+%.o: %.c
+ $(CXX) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
new file mode 100644
index 0000000000..5210dd2054
--- /dev/null
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -0,0 +1,601 @@
+/* ScummVM Tools
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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$
+ *
+ */
+
+#include "create_kyradat.h"
+
+#include "md5.h"
+
+enum {
+ kKyraDatVersion = 14,
+ kIndexSize = 12
+};
+
+// tables
+
+#include "misc.h"
+#include "eng.h"
+#include "esp.h"
+#include "fre.h"
+#include "ger.h"
+
+bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+
+void createFilename(char *dstFilename, const int lang, const int special, const char *filename);
+void createLangFilename(char *dstFilename, const int lang, const int special, const char *filename);
+
+const ExtractType extractTypeTable[] = {
+ { kTypeLanguageList, extractStrings, createLangFilename },
+ { kTypeStringList, extractStrings, createFilename },
+ { kTypeRoomList, extractRooms, createFilename },
+ { kTypeShapeList, extractShapes, createFilename },
+ { kTypeRawData, extractRaw, createFilename },
+ { -1, 0 }
+};
+
+const ExtractFilename extractFilenames[] = {
+ // INTRO / OUTRO sequences
+ { kForestSeq, kTypeRawData, "FOREST.SEQ" },
+ { kKallakWritingSeq, kTypeRawData, "KALLAK-WRITING.SEQ" },
+ { kKyrandiaLogoSeq, kTypeRawData, "KYRANDIA-LOGO.SEQ" },
+ { kKallakMalcolmSeq, kTypeRawData, "KALLAK-MALCOLM.SEQ" },
+ { kMalcolmTreeSeq, kTypeRawData, "MALCOLM-TREE.SEQ" },
+ { kWestwoodLogoSeq, kTypeRawData, "WESTWOOD-LOGO.SEQ" },
+ { kDemo1Seq, kTypeRawData, "DEMO1.SEQ" },
+ { kDemo2Seq, kTypeRawData, "DEMO2.SEQ" },
+ { kDemo3Seq, kTypeRawData, "DEMO3.SEQ" },
+ { kDemo4Seq, kTypeRawData, "DEMO4.SEQ" },
+ { kOutroReunionSeq, kTypeRawData, "REUNION.SEQ" },
+
+ // INTRO / OUTRO strings
+ { kIntroCPSStrings, kTypeStringList, "INTRO-CPS.TXT" },
+ { kIntroCOLStrings, kTypeStringList, "INTRO-COL.TXT" },
+ { kIntroWSAStrings, kTypeStringList, "INTRO-WSA.TXT" },
+ { kIntroStrings, kTypeLanguageList, "INTRO-STRINGS" },
+ { kOutroHomeString, kTypeLanguageList, "HOME" },
+
+ // INGAME strings
+ { kItemNames, kTypeLanguageList, "ITEMLIST" },
+ { kTakenStrings, kTypeLanguageList, "TAKEN" },
+ { kPlacedStrings, kTypeLanguageList, "PLACED" },
+ { kDroppedStrings, kTypeLanguageList, "DROPPED" },
+ { kNoDropStrings, kTypeLanguageList, "NODROP" },
+ { kPutDownString, kTypeLanguageList, "PUTDOWN" },
+ { kWaitAmuletString, kTypeLanguageList, "WAITAMUL" },
+ { kBlackJewelString, kTypeLanguageList, "BLACKJEWEL" },
+ { kPoisonGoneString, kTypeLanguageList, "POISONGONE" },
+ { kHealingTipString, kTypeLanguageList, "HEALINGTIP" },
+ { kThePoisonStrings, kTypeLanguageList, "THEPOISON" },
+ { kFluteStrings, kTypeLanguageList, "FLUTE" },
+ { kWispJewelStrings, kTypeLanguageList, "WISPJEWEL" },
+ { kMagicJewelStrings, kTypeLanguageList, "MAGICJEWEL" },
+ { kFlaskFullString, kTypeLanguageList, "FLASKFULL" },
+ { kFullFlaskString, kTypeLanguageList, "FULLFLASK" },
+ { kVeryCleverString, kTypeLanguageList, "VERYCLEVER" },
+ { kNewGameString, kTypeLanguageList, "NEWGAME" },
+
+ // GUI strings table
+ { kGUIStrings, kTypeLanguageList, "GUISTRINGS" },
+ { kConfigStrings, kTypeLanguageList, "CONFIGSTRINGS" },
+
+ // ROOM table/filenames
+ { kRoomList, kTypeRoomList, "ROOM-TABLE.ROOM" },
+ { kRoomFilenames, kTypeStringList, "ROOM-FILENAMES.TXT" },
+
+ // SHAPE tables
+ { kDefaultShapes, kTypeShapeList, "SHAPES-DEFAULT.SHP" },
+ { kHealing1Shapes, kTypeShapeList, "HEALING.SHP" },
+ { kHealing2Shapes, kTypeShapeList, "HEALING2.SHP" },
+ { kPoisonDeathShapes, kTypeShapeList, "POISONDEATH.SHP" },
+ { kFluteShapes, kTypeShapeList, "FLUTE.SHP" },
+ { kWinter1Shapes, kTypeShapeList, "WINTER1.SHP" },
+ { kWinter2Shapes, kTypeShapeList, "WINTER2.SHP" },
+ { kWinter3Shapes, kTypeShapeList, "WINTER3.SHP" },
+ { kDrinkShapes, kTypeShapeList, "DRINK.SHP" },
+ { kWispShapes, kTypeShapeList, "WISP.SHP" },
+ { kMagicAnimShapes, kTypeShapeList, "MAGICANIM.SHP" },
+ { kBranStoneShapes, kTypeShapeList, "BRANSTONE.SHP" },
+
+ // IMAGE filename table
+ { kCharacterImageFilenames, kTypeStringList, "CHAR-IMAGE.TXT" },
+
+ // AMULET anim
+ { kAmuleteAnimSeq, kTypeRawData, "AMULETEANIM.SEQ" },
+
+ // PALETTE table
+ { kPaletteList1, kTypeRawData, "PALTABLE1.PAL" },
+ { kPaletteList2, kTypeRawData, "PALTABLE2.PAL" },
+ { kPaletteList3, kTypeRawData, "PALTABLE3.PAL" },
+ { kPaletteList4, kTypeRawData, "PALTABLE4.PAL" },
+ { kPaletteList5, kTypeRawData, "PALTABLE5.PAL" },
+ { kPaletteList6, kTypeRawData, "PALTABLE6.PAL" },
+ { kPaletteList7, kTypeRawData, "PALTABLE7.PAL" },
+ { kPaletteList8, kTypeRawData, "PALTABLE8.PAL" },
+ { kPaletteList9, kTypeRawData, "PALTABLE9.PAL" },
+ { kPaletteList10, kTypeRawData, "PALTABLE10.PAL" },
+ { kPaletteList11, kTypeRawData, "PALTABLE11.PAL" },
+ { kPaletteList12, kTypeRawData, "PALTABLE12.PAL" },
+ { kPaletteList13, kTypeRawData, "PALTABLE13.PAL" },
+ { kPaletteList14, kTypeRawData, "PALTABLE14.PAL" },
+ { kPaletteList15, kTypeRawData, "PALTABLE15.PAL" },
+ { kPaletteList16, kTypeRawData, "PALTABLE16.PAL" },
+ { kPaletteList17, kTypeRawData, "PALTABLE17.PAL" },
+ { kPaletteList18, kTypeRawData, "PALTABLE18.PAL" },
+ { kPaletteList19, kTypeRawData, "PALTABLE19.PAL" },
+ { kPaletteList20, kTypeRawData, "PALTABLE20.PAL" },
+ { kPaletteList21, kTypeRawData, "PALTABLE21.PAL" },
+ { kPaletteList22, kTypeRawData, "PALTABLE22.PAL" },
+ { kPaletteList23, kTypeRawData, "PALTABLE23.PAL" },
+ { kPaletteList24, kTypeRawData, "PALTABLE24.PAL" },
+ { kPaletteList25, kTypeRawData, "PALTABLE25.PAL" },
+ { kPaletteList26, kTypeRawData, "PALTABLE26.PAL" },
+ { kPaletteList27, kTypeRawData, "PALTABLE27.PAL" },
+ { kPaletteList28, kTypeRawData, "PALTABLE28.PAL" },
+ { kPaletteList29, kTypeRawData, "PALTABLE29.PAL" },
+ { kPaletteList30, kTypeRawData, "PALTABLE30.PAL" },
+ { kPaletteList31, kTypeRawData, "PALTABLE31.PAL" },
+ { kPaletteList32, kTypeRawData, "PALTABLE32.PAL" },
+ { kPaletteList33, kTypeRawData, "PALTABLE33.PAL" },
+
+ // FM-TOWNS specific
+ { kKyra1TownsSFXTable, kTypeRawData, "SFXTABLE.TSX" },
+
+ { -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;
+}
+
+// type processing
+
+const ExtractType *findExtractType(const int type) {
+ for (const ExtractType *i = extractTypeTable; i->type != -1; ++i) {
+ if (i->type == type)
+ return i;
+ }
+ return 0;
+}
+
+// filename processing
+
+bool getFilename(char *dstFilename, const Game *g, const int id) {
+ const ExtractFilename *i = getFilenameDesc(id);
+
+ if (!i)
+ return false;
+
+ const ExtractType *type = findExtractType(i->type);
+ type->createFilename(dstFilename, g->lang, g->special, i->filename);
+ return true;
+}
+
+void createFilename(char *dstFilename, const int lang, const int special, const char *filename) {
+ strcpy(dstFilename, filename);
+
+ for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
+ if (specialE->special == special) {
+ strcat(dstFilename, ".");
+ strcat(dstFilename, specialE->ext);
+ break;
+ }
+ }
+}
+
+void createLangFilename(char *dstFilename, const int lang, const int special, const char *filename) {
+ strcpy(dstFilename, filename);
+
+ for (const Language *langE = languageTable; langE->lang != -1; ++langE) {
+ if (langE->lang == lang) {
+ strcat(dstFilename, ".");
+ strcat(dstFilename, langE->ext);
+ break;
+ }
+ }
+
+ for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
+ if (specialE->special == special) {
+ strcat(dstFilename, ".");
+ strcat(dstFilename, specialE->ext);
+ break;
+ }
+ }
+}
+
+// entry checking
+
+int hashEntries(const int *entries) {
+ int hash = 0;
+ for (const int *i = entries; *i != -1; ++i) {
+ hash += *i;
+ }
+ return hash;
+}
+
+bool hasEntry(const ExtractEntry *entries, const int id) {
+ for (const ExtractEntry *i = entries; i->id != -1; ++i) {
+ if (i->id == id)
+ return true;
+ }
+ return false;
+}
+
+int hashEntries(const Game *game, const GameNeed *need, const PAKFile *file) {
+ int hash = 0;
+ char filename[128];
+ for (const int *i = need->entries; *i != -1; ++i) {
+ if (hasEntry(game->entries, *i)) {
+ hash += *i;
+ continue;
+ }
+
+ if (file) {
+ filename[0] = 0;
+
+ if (!getFilename(filename, game, *i))
+ error("couldn't find filename for id %d", *i);
+
+ PAKFile::cFileList *list = file->getFileList();
+ if (list && list->findEntry(filename) != 0)
+ hash += *i;
+ }
+ }
+
+ return hash;
+}
+
+bool hasNeededEntries(const Game *game, const PAKFile *file) {
+ for (const GameNeed *need = gameNeedTable; need->game != -1; ++need) {
+ if (need->game == game->game && need->special == game->special) {
+ if (hashEntries(need->entries) == hashEntries(game, need, file))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// extraction
+
+bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename) {
+ uint8 *buffer = new uint8[size];
+ assert(buffer);
+ memcpy(buffer, data, size);
+ return out.addFile(filename, buffer, size);
+}
+
+bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename) {
+ uint32 entries = 0;
+ for (uint32 i = 0; i < size; ++i) {
+ if (!data[i])
+ ++entries;
+ }
+
+ uint8 *buffer = new uint8[size + 4];
+ assert(buffer);
+ uint8 *output = buffer;
+
+ WRITE_BE_UINT32(output, entries); output += 4;
+ memcpy(output, data, size);
+
+ return out.addFile(filename, buffer, size + 4);
+}
+
+bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename) {
+ const int countRooms = size / 0x51;
+
+ uint8 *buffer = new uint8[countRooms * 9 + 4];
+ assert(buffer);
+ uint8 *output = buffer;
+
+ WRITE_BE_UINT32(output, countRooms); output += 4;
+
+ const byte *src = data;
+ 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 += (0x51 - 9);
+ }
+
+ return out.addFile(filename, buffer, countRooms * 9 + 4);
+}
+
+bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename) {
+ 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);
+}
+
+// index generation
+
+enum {
+ GF_FLOPPY = 1 << 0,
+ GF_TALKIE = 1 << 1,
+ GF_FMTOWNS = 1 << 2,
+ GF_DEMO = 1 << 3,
+ GF_ENGLISH = 1 << 4,
+ GF_FRENCH = 1 << 5,
+ GF_GERMAN = 1 << 6,
+ GF_SPANISH = 1 << 7,
+ GF_ITALIAN = 1 << 8,
+ GF_JAPANESE = 1 << 9,
+ // ...
+ GF_LNGUNK = 1 << 16,
+ GF_AMIGA = 1 << 17
+};
+
+uint32 getFeatures(const Game *g) {
+ uint32 features = 0;
+
+ if (g->special == kTalkieVersion)
+ features |= GF_TALKIE;
+ else if (g->special == kDemoVersion)
+ features |= GF_DEMO;
+ else if (g->special == kFMTownsVersion)
+ features |= GF_FMTOWNS;
+ else
+ features |= GF_FLOPPY;
+
+ if (g->lang == EN_ANY)
+ features |= GF_ENGLISH;
+ else if (g->lang == DE_DEU)
+ features |= GF_GERMAN;
+ else if (g->lang == FR_FRA)
+ features |= GF_FRENCH;
+ else if (g->lang == ES_ESP)
+ features |= GF_SPANISH;
+ else if (g->lang == IT_ITA)
+ features |= GF_ITALIAN;
+
+ return features;
+}
+
+bool updateIndex(byte *dst, const int dstSize, const Game *g) {
+ if ((size_t)dstSize < kIndexSize)
+ return false;
+
+ WRITE_BE_UINT32(dst, kKyraDatVersion); dst += 4;
+ WRITE_BE_UINT32(dst, g->game); dst += 4;
+ uint32 features = READ_BE_UINT32(dst);
+ features |= getFeatures(g);
+ WRITE_BE_UINT32(dst, features); dst += 4;
+
+ return true;
+}
+
+bool checkIndex(const byte *s, const int srcSize) {
+ if ((size_t)srcSize < sizeof(uint32))
+ return false;
+ uint32 version = READ_BE_UINT32(s);
+ return (version == kKyraDatVersion);
+}
+
+bool updateIndex(PAKFile &out, const Game *g) {
+ char filename[32];
+ createFilename(filename, -1, g->special, "INDEX");
+
+ byte *index = new byte[kIndexSize];
+ assert(index);
+ memset(index, 0, kIndexSize);
+
+ uint32 size = 0;
+ const uint8 *data = out.getFileData(filename, &size);
+ if (data)
+ memcpy(index, data, size);
+
+ if (!updateIndex(index, kIndexSize, g)) {
+ delete [] index;
+ return false;
+ }
+
+ out.removeFile(filename);
+ if (!out.addFile(filename, index, kIndexSize)) {
+ fprintf(stderr, "ERROR: couldn't update %s file", filename);
+ delete [] index;
+ return false;
+ }
+
+ return true;
+}
+
+bool checkIndex(PAKFile &out, const Game *g) {
+ char filename[32];
+ createFilename(filename, -1, g->special, "INDEX");
+
+ uint32 size = 0;
+ const uint8 *data = out.getFileData(filename, &size);
+ if (!data)
+ return true;
+
+ return checkIndex(data, size);
+}
+
+// main processing
+
+void printHelp(const char *f) {
+ printf("Usage:\n");
+ printf("%s output inputfiles ...", f);
+}
+
+bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size);
+const Game *findGame(const byte *buffer, const uint32 size);
+
+int main(int argc, char *argv[]) {
+ if (argc < 3) {
+ printHelp(argv[0]);
+ return -1;
+ }
+
+ PAKFile out;
+ out.loadFile(argv[1], false);
+
+ for (int i = 2; i < argc; ++i) {
+ FILE *input = fopen(argv[i], "rb");
+
+ if (!input) {
+ warning("skipping missing file '%s'", argv[i]);
+ continue;
+ }
+
+ 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", argv[i]);
+ delete [] buffer;
+ fclose(input);
+ continue;
+ }
+ fclose(input);
+
+ const Game *g = findGame(buffer, size);
+ if (!g) {
+ warning("skipping unknown file '%s'", argv[i]);
+ delete [] buffer;
+ continue;
+ }
+
+ if (!hasNeededEntries(g, &out)) {
+ warning("file '%s' is missing offset entries and thus can't be processed", argv[i]);
+ delete [] buffer;
+ continue;
+ }
+
+ if (!process(out, g, buffer, size))
+ fprintf(stderr, "ERROR: couldn't process file '%s'", argv[i]);
+
+ delete [] buffer;
+ }
+
+ 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;
+}
+
+bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
+ char filename[128];
+
+ if (!checkIndex(out, g)) {
+ fprintf(stderr, "ERROR: corrupted INDEX file\n");
+ return false;
+ }
+
+ for (const ExtractEntry *i = g->entries; i->id != -1; ++i) {
+ if (!getFilename(filename, g, i->id)) {
+ fprintf(stderr, "ERROR: couldn't get filename for id %d\n", i->id);
+ return false;
+ }
+
+ const ExtractFilename *fDesc = getFilenameDesc(i->id);
+
+ if (!fDesc) {
+ fprintf(stderr, "ERROR: couldn't find file description for id %d\n", i->id);
+ return false;
+ }
+
+ const ExtractType *tDesc = findExtractType(fDesc->type);
+
+ if (!tDesc) {
+ fprintf(stderr, "ERROR: couldn't find type description for id %d\n", i->id);
+ return false;
+ }
+
+ PAKFile::cFileList *list = out.getFileList();
+ if (list && list->findEntry(filename) != 0)
+ continue;
+
+ if (!tDesc->extract(out, g, data + i->startOff, i->endOff - i->startOff, filename)) {
+ fprintf(stderr, "ERROR: couldn't extract id %d\n", i->id);
+ return false;
+ }
+ }
+
+ if (!updateIndex(out, g)) {
+ error("couldn't update INDEX file, stop processing of all files");
+ return false;
+ }
+
+ return true;
+}
+
+// game data detection
+
+const Game *gameDescs[] = {
+ kyra1EngGames,
+ kyra1EspGames,
+ kyra1FreGames,
+ kyra1GerGames,
+ 0
+};
+
+const Game *findGame(const byte *buffer, const uint32 size) {
+ 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]);
+ }
+
+ for (const Game **i = gameDescs; *i != 0; ++i) {
+ for (const Game *p = *i; p->game != -1; ++p) {
+ if (strcmp(md5str, p->md5) == 0)
+ return p;
+ }
+ }
+
+ printf("file is not supported (unknown md5 \"%s\")\n", md5str);
+ return 0;
+}
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
new file mode 100644
index 0000000000..4bcf289fad
--- /dev/null
+++ b/tools/create_kyradat/create_kyradat.h
@@ -0,0 +1,202 @@
+/* ScummVM Tools
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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_H
+#define CREATE_KYRADAT_H
+
+#include "util.h"
+#include "pak.h"
+
+struct Language {
+ int lang;
+ const char *ext;
+};
+
+enum kExtractID {
+ kForestSeq = 1,
+ kKallakWritingSeq,
+ kKyrandiaLogoSeq,
+ kKallakMalcolmSeq,
+ kMalcolmTreeSeq,
+ kWestwoodLogoSeq,
+
+ kDemo1Seq,
+ kDemo2Seq,
+ kDemo3Seq,
+ kDemo4Seq,
+
+ kAmuleteAnimSeq,
+
+ kOutroReunionSeq,
+
+ kIntroCPSStrings,
+ kIntroCOLStrings,
+ kIntroWSAStrings,
+ kIntroStrings,
+
+ kOutroHomeString,
+
+ kRoomFilenames,
+ kRoomList,
+
+ kCharacterImageFilenames,
+
+ kItemNames,
+ kTakenStrings,
+ kPlacedStrings,
+ kDroppedStrings,
+ kNoDropStrings,
+
+ kPutDownString,
+ kWaitAmuletString,
+ kBlackJewelString,
+ kPoisonGoneString,
+ kHealingTipString,
+ kWispJewelStrings,
+ kMagicJewelStrings,
+
+ kThePoisonStrings,
+ kFluteStrings,
+
+ kFlaskFullString,
+ kFullFlaskString,
+
+ kVeryCleverString,
+ kNewGameString,
+
+ kDefaultShapes,
+ kHealing1Shapes,
+ kHealing2Shapes,
+ kPoisonDeathShapes,
+ kFluteShapes,
+ kWinter1Shapes,
+ kWinter2Shapes,
+ kWinter3Shapes,
+ kDrinkShapes,
+ kWispShapes,
+ kMagicAnimShapes,
+ kBranStoneShapes,
+
+ kPaletteList1,
+ kPaletteList2,
+ kPaletteList3,
+ kPaletteList4,
+ kPaletteList5,
+ kPaletteList6,
+ kPaletteList7,
+ kPaletteList8,
+ kPaletteList9,
+ kPaletteList10,
+ kPaletteList11,
+ kPaletteList12,
+ kPaletteList13,
+ kPaletteList14,
+ kPaletteList15,
+ kPaletteList16,
+ kPaletteList17,
+ kPaletteList18,
+ kPaletteList19,
+ kPaletteList20,
+ kPaletteList21,
+ kPaletteList22,
+ kPaletteList23,
+ kPaletteList24,
+ kPaletteList25,
+ kPaletteList26,
+ kPaletteList27,
+ kPaletteList28,
+ kPaletteList29,
+ kPaletteList30,
+ kPaletteList31,
+ kPaletteList32,
+ kPaletteList33,
+
+ kGUIStrings,
+ kConfigStrings,
+
+ kKyra1TownsSFXTable,
+
+ kMaxResIDs
+};
+
+struct ExtractEntry {
+ int id;
+ uint32 startOff;
+ uint32 endOff;
+};
+
+struct ExtractFilename {
+ int id;
+ int type;
+ const char *filename;
+};
+
+enum kSpecial {
+ kTalkieVersion = 0,
+ kDemoVersion = 1,
+ kFMTownsVersion = 2
+};
+
+struct SpecialExtension {
+ int special;
+ const char *ext;
+};
+
+enum kGame {
+ kKyra1 = 0,
+ kKyra2,
+ kKyra3
+};
+
+struct Game {
+ int game;
+ int lang;
+ int special;
+
+ const char *md5;
+ const ExtractEntry *entries;
+};
+
+#define GAME_DUMMY_ENTRY { -1, -1, -1, 0, 0 }
+
+struct GameNeed {
+ int game;
+ int special;
+
+ const int *entries;
+};
+
+enum kExtractType {
+ kTypeLanguageList = 0,
+ kTypeStringList,
+ kTypeRoomList,
+ kTypeShapeList,
+ kTypeRawData
+};
+
+struct ExtractType {
+ int type;
+ bool (*extract)(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+ void (*createFilename)(char *dstFilename, const int lang, const int special, const char *filename);
+};
+
+#endif
diff --git a/tools/create_kyradat/eng.h b/tools/create_kyradat/eng.h
new file mode 100644
index 0000000000..72feff62e7
--- /dev/null
+++ b/tools/create_kyradat/eng.h
@@ -0,0 +1,190 @@
+const ExtractEntry kyra1EngFloppy[] = {
+ { kKallakWritingSeq, 0x0002FE5E, 0x00030653 },
+ { kMalcolmTreeSeq, 0x00030653, 0x00030869 },
+ { kWestwoodLogoSeq, 0x00030869, 0x000308B4 },
+ { kKyrandiaLogoSeq, 0x000308B4, 0x00030910 },
+ { kKallakMalcolmSeq, 0x00030910, 0x00030B7B },
+ { kForestSeq, 0x00030B7B, 0x00030D10 },
+ { kIntroCPSStrings, 0x00030D10, 0x00030D24 },
+ { kIntroWSAStrings, 0x00030D24, 0x00030DA4 },
+ { kIntroCOLStrings, 0x00030DA4, 0x00030DCF },
+ { kIntroStrings, 0x00030DCF, 0x000312C4 },
+ { kRoomList, 0x00028020, 0x0002CDF6 },
+ { kRoomFilenames, 0x0003386A, 0x00033B46 },
+ { kCharacterImageFilenames, 0x0003268D, 0x00032771 },
+ { kDefaultShapes, 0x0002CFB0, 0x0002D43A },
+ { kItemNames, 0x00033F2E, 0x00034396 },
+ { kTakenStrings, 0x00033822, 0x00033832 },
+ { kPlacedStrings, 0x00033832, 0x0003383B },
+ { kDroppedStrings, 0x00033860, 0x0003386A },
+ { kNoDropStrings, 0x000337DA, 0x00033821 },
+ { kAmuleteAnimSeq, 0x0002EA9C, 0x0002EAC6 },
+ { kPaletteList1, 0x00025100, 0x00025115 },
+ { kPaletteList2, 0x00025115, 0x00025148 },
+ { kPaletteList3, 0x00025148, 0x0002517B },
+ { kPaletteList4, 0x0002517B, 0x000251AE },
+ { kPaletteList5, 0x000251AE, 0x000251E1 },
+ { kPaletteList6, 0x000251E1, 0x00025214 },
+ { kPaletteList7, 0x00025214, 0x0002524A },
+ { kPaletteList8, 0x0002524A, 0x00025280 },
+ { kPaletteList9, 0x00025280, 0x000252AD },
+ { kPaletteList10, 0x000252AD, 0x000252DA },
+ { kPaletteList11, 0x000252DA, 0x00025307 },
+ { kPaletteList12, 0x00025307, 0x00025334 },
+ { kPaletteList13, 0x00025334, 0x00025361 },
+ { kPaletteList14, 0x00025361, 0x0002539D },
+ { kPaletteList15, 0x0002539D, 0x000253CA },
+ { kPaletteList16, 0x000253CA, 0x000253EB },
+ { kPaletteList17, 0x000253EB, 0x0002540C },
+ { kPaletteList18, 0x0002540C, 0x00025421 },
+ { kPaletteList19, 0x00025421, 0x00025436 },
+ { kPaletteList20, 0x00025436, 0x0002544B },
+ { kPaletteList21, 0x0002544B, 0x00025460 },
+ { kPaletteList22, 0x00025460, 0x00025475 },
+ { kPaletteList23, 0x00025475, 0x0002548A },
+ { kPaletteList24, 0x0002548A, 0x000254BA },
+ { kPaletteList25, 0x000254BA, 0x000254EA },
+ { kPaletteList26, 0x000254EA, 0x0002551A },
+ { kPaletteList27, 0x0002551A, 0x0002554A },
+ { kPaletteList28, 0x0002554A, 0x0002557A },
+ { kPaletteList29, 0x0002557A, 0x000255AA },
+ { kPaletteList30, 0x000255AA, 0x000255E6 },
+ { kPaletteList31, 0x000255E6, 0x0002560D },
+ { kPaletteList32, 0x0002560D, 0x00025634 },
+ { kPaletteList33, 0x00025634, 0x00025670 },
+ { kPutDownString, 0x0002EBCE, 0x0002EBF4 },
+ { kWaitAmuletString, 0x0002EBF4, 0x0002EC31 },
+ { kBlackJewelString, 0x0002EC31, 0x0002EC54 },
+ { kHealingTipString, 0x0002EC54, 0x0002EC81 },
+ { kPoisonGoneString, 0x0002ECE7, 0x0002ED14 },
+ { kHealing1Shapes, 0x0002D4A3, 0x0002D53D },
+ { kHealing2Shapes, 0x0002D53D, 0x0002D60F },
+ { kThePoisonStrings, 0x0002F8DC, 0x0002F933 },
+ { kFluteStrings, 0x00031C7B, 0x00031CB7 },
+ { kPoisonDeathShapes, 0x0002D903, 0x0002D98F },
+ { kFluteShapes, 0x0002D807, 0x0002D903 },
+ { kWinter1Shapes, 0x0002D60F, 0x0002D640 },
+ { kWinter2Shapes, 0x0002D640, 0x0002D735 },
+ { kWinter3Shapes, 0x0002D735, 0x0002D751 },
+ { kDrinkShapes, 0x0002D43A, 0x0002D4A3 },
+ { kWispShapes, 0x0002D751, 0x0002D807 },
+ { kMagicAnimShapes, 0x0002D98F, 0x0002D9B2 },
+ { kBranStoneShapes, 0x0002D9B2, 0x0002DA20 },
+ { kWispJewelStrings, 0x0002EC81, 0x0002ECD4 },
+ { kMagicJewelStrings, 0x0002ECD4, 0x0002ECE7 },
+ { kFlaskFullString, 0x0002F9EB, 0x0002FA07 },
+ { kFullFlaskString, 0x0002F954, 0x0002F9EB },
+ { kOutroReunionSeq, 0x000313C1, 0x00031908 },
+ { kOutroHomeString, 0x000319C2, 0x000319C7 },
+ { kVeryCleverString, 0x00031922, 0x00031954 },
+ { kGUIStrings, 0x0002EE7A, 0x0002F02A },
+ { kNewGameString, 0x00032466, 0x0003247B },
+ { kConfigStrings, 0x0002f870, 0x0002f8af },
+ { -1, 0, 0 }
+};
+
+const ExtractEntry kyra1EngCD[] = {
+ { kKallakWritingSeq, 0x0003008F, 0x00030894 },
+ { kMalcolmTreeSeq, 0x00030894, 0x00030AC4 },
+ { kWestwoodLogoSeq, 0x00030AC4, 0x00030B0F },
+ { kKyrandiaLogoSeq, 0x00030B0F, 0x00030BB5 },
+ { kKallakMalcolmSeq, 0x00030BB5, 0x00030E6D },
+ { kForestSeq, 0x00030E6D, 0x000310E0 },
+ { kIntroCPSStrings, 0x000310E0, 0x000310F5 },
+ { kIntroWSAStrings, 0x000310F5, 0x00031175 },
+ { kIntroCOLStrings, 0x00031175, 0x000311A0 },
+ { kIntroStrings, 0x000311A0, 0x00031696 },
+ { kRoomList, 0x00028280, 0x0002D056 },
+ { kRoomFilenames, 0x00033F2C, 0x00034208 },
+ { kCharacterImageFilenames, 0x00032F22, 0x00033006 },
+ { kDefaultShapes, 0x0002D210, 0x0002D69A },
+ { kItemNames, 0x00034442, 0x000348AA },
+ { kTakenStrings, 0x00033EE4, 0x00033EF4 },
+ { kPlacedStrings, 0x00033EF4, 0x00033EFD },
+ { kDroppedStrings, 0x00033F22, 0x00033F2C },
+ { kNoDropStrings, 0x00033E9C, 0x00033EE3 },
+ { kAmuleteAnimSeq, 0x0002EE1C, 0x0002EE46 },
+ { kPaletteList1, 0x00025530, 0x00025545 },
+ { kPaletteList2, 0x00025545, 0x00025578 },
+ { kPaletteList3, 0x00025578, 0x000255AB },
+ { kPaletteList4, 0x000255AB, 0x000255DE },
+ { kPaletteList5, 0x000255DE, 0x00025611 },
+ { kPaletteList6, 0x00025611, 0x00025644 },
+ { kPaletteList7, 0x00025644, 0x0002567A },
+ { kPaletteList8, 0x0002567A, 0x000256B0 },
+ { kPaletteList9, 0x000256B0, 0x000256DD },
+ { kPaletteList10, 0x000256DD, 0x0002570A },
+ { kPaletteList11, 0x0002570A, 0x00025737 },
+ { kPaletteList12, 0x00025737, 0x00025764 },
+ { kPaletteList13, 0x00025764, 0x00025791 },
+ { kPaletteList14, 0x00025791, 0x000257CD },
+ { kPaletteList15, 0x000257CD, 0x000257FA },
+ { kPaletteList16, 0x000257FA, 0x0002581B },
+ { kPaletteList17, 0x0002581B, 0x0002583C },
+ { kPaletteList18, 0x0002583C, 0x00025851 },
+ { kPaletteList19, 0x00025851, 0x00025866 },
+ { kPaletteList20, 0x00025866, 0x0002587B },
+ { kPaletteList21, 0x0002587B, 0x00025890 },
+ { kPaletteList22, 0x00025890, 0x000258A5 },
+ { kPaletteList23, 0x000258A5, 0x000258BA },
+ { kPaletteList24, 0x000258BA, 0x000258EA },
+ { kPaletteList25, 0x000258EA, 0x0002591A },
+ { kPaletteList26, 0x0002591A, 0x0002594A },
+ { kPaletteList27, 0x0002594A, 0x0002597A },
+ { kPaletteList28, 0x0002597A, 0x000259AA },
+ { kPaletteList29, 0x000259AA, 0x000259DA },
+ { kPaletteList30, 0x000259DA, 0x00025A16 },
+ { kPaletteList31, 0x00025A16, 0x00025A3D },
+ { kPaletteList32, 0x00025A3D, 0x00025A64 },
+ { kPaletteList33, 0x00025A64, 0x00025AA0 },
+ { kPutDownString, 0x0002EF50, 0x0002EF76 },
+ { kWaitAmuletString, 0x0002EF76, 0x0002EFB3 },
+ { kBlackJewelString, 0x0002EFB3, 0x0002EFD6 },
+ { kHealingTipString, 0x0002EFD6, 0x0002F003 },
+ { kPoisonGoneString, 0x0002F068, 0x0002F095 },
+ { kHealing1Shapes, 0x0002D703, 0x0002D79D },
+ { kHealing2Shapes, 0x0002D79D, 0x0002D86F },
+ { kThePoisonStrings, 0x0002FCCA, 0x0002FD21 },
+ { kFluteStrings, 0x00032510, 0x000325AC },
+ { kPoisonDeathShapes, 0x0002DB63, 0x0002DBEF },
+ { kFluteShapes, 0x0002DA67, 0x0002DB63 },
+ { kWinter1Shapes, 0x0002D86F, 0x0002D8A0 },
+ { kWinter2Shapes, 0x0002D8A0, 0x0002D995 },
+ { kWinter3Shapes, 0x0002D995, 0x0002D9B1 },
+ { kDrinkShapes, 0x0002D69A, 0x0002D703 },
+ { kWispShapes, 0x0002D9B1, 0x0002DA67 },
+ { kMagicAnimShapes, 0x0002DBEF, 0x0002DC12 },
+ { kBranStoneShapes, 0x0002DC12, 0x0002DC80 },
+ { kWispJewelStrings, 0x0002F003, 0x0002F055 },
+ { kMagicJewelStrings, 0x0002F055, 0x0002F068 },
+ { kFlaskFullString, 0x0002FDE1, 0x0002FDFD },
+ { kFullFlaskString, 0x0002FD4A, 0x0002FDE1 },
+ { kOutroReunionSeq, 0x00031791, 0x00031D76 },
+ { kOutroHomeString, 0x00031E3A, 0x00031E3F },
+ { kVeryCleverString, 0x00031D90, 0x00031DC2 },
+ { kGUIStrings, 0x0002F1EE, 0x0002F3F7 },
+ { kNewGameString, 0x00032CFB, 0x00032D10 },
+ { kConfigStrings, 0x0002fc3d, 0x0002fc9e },
+ { -1, 0, 0 }
+};
+
+const ExtractEntry kyra1EngDemo[] = {
+ { kWestwoodLogoSeq, 0x00015327, 0x0001536B },
+ { kKyrandiaLogoSeq, 0x0001536B, 0x000153BF },
+ { kIntroCPSStrings, 0x000154B1, 0x000154BD },
+ { kIntroWSAStrings, 0x000154BD, 0x0001550A },
+ { kIntroCOLStrings, 0x0001550A, 0x00015550 },
+ { kIntroStrings, 0x00015550, 0x0001584A },
+ { kDemo1Seq, 0x000153BF, 0x000153E5 },
+ { kDemo2Seq, 0x000153E5, 0x00015408 },
+ { kDemo3Seq, 0x00015408, 0x00015461 },
+ { kDemo4Seq, 0x00015461, 0x00015481 },
+ { -1, 0, 0 }
+};
+
+const Game kyra1EngGames[] = {
+ { kKyra1, EN_ANY, -1, "76a4fc84e173cadb6369785787e1546e", kyra1EngFloppy },
+ { kKyra1, EN_ANY, kTalkieVersion, "1ebc18f3e7fbb72474a55cb0fa089ed4", kyra1EngCD },
+ { kKyra1, EN_ANY, kDemoVersion, "7b7504c8560ffc914d34c44c71b3094c", kyra1EngDemo },
+ GAME_DUMMY_ENTRY
+};
diff --git a/tools/create_kyradat/esp.h b/tools/create_kyradat/esp.h
new file mode 100644
index 0000000000..79d8bd00e7
--- /dev/null
+++ b/tools/create_kyradat/esp.h
@@ -0,0 +1,39 @@
+const ExtractEntry kyra1EspFloppy[] = {
+ { kKallakWritingSeq, 0x00030462, 0x00030C57 },
+ { kMalcolmTreeSeq, 0x00030C57, 0x00030E6D },
+ { kWestwoodLogoSeq, 0x00030E6D, 0x00030EB8 },
+ { kKyrandiaLogoSeq, 0x00030EB8, 0x00030F14 },
+ { kKallakMalcolmSeq, 0x00030F14, 0x0003117F },
+ { kForestSeq, 0x0003117F, 0x00031314 },
+ { kIntroCPSStrings, 0x00031314, 0x00031328 },
+ { kIntroWSAStrings, 0x00031328, 0x000313A8 },
+ { kIntroCOLStrings, 0x000313A8, 0x000313D3 },
+ { kIntroStrings, 0x000313D3, 0x000319A2 },
+ { kItemNames, 0x0003467A, 0x00034BAA },
+ { kTakenStrings, 0x00033F14, 0x00033F28 },
+ { kPlacedStrings, 0x00033F28, 0x00033F35 },
+ { kDroppedStrings, 0x00033F5E, 0x00033F66 },
+ { kNoDropStrings, 0x00033ED6, 0x00033F13 },
+ { kPutDownString, 0x0002F100, 0x0002F12D },
+ { kWaitAmuletString, 0x0002F12D, 0x0002F16F },
+ { kBlackJewelString, 0x0002F16F, 0x0002F194 },
+ { kHealingTipString, 0x0002F194, 0x0002F1BC },
+ { kPoisonGoneString, 0x0002F22C, 0x0002F25F },
+ { kThePoisonStrings, 0x0002FEC6, 0x0002FF1F },
+ { kFluteStrings, 0x00032361, 0x000323B3 },
+ { kWispJewelStrings, 0x0002F1BC, 0x0002F21B },
+ { kMagicJewelStrings, 0x0002F21B, 0x0002F22C },
+ { kFlaskFullString, 0x0002FFDA, 0x0002FFF5 },
+ { kFullFlaskString, 0x0002FF40, 0x0002FFDA },
+ { kOutroHomeString, 0x000320A8, 0x000320AD },
+ { kVeryCleverString, 0x00032004, 0x0003203A },
+ { kGUIStrings, 0x0002f3d0, 0x0002f60a },
+ { kNewGameString, 0x00032b62, 0x00032b7d },
+ { kConfigStrings, 0x0002fe50, 0x0002fe9a },
+ { -1, 0, 0 }
+};
+
+const Game kyra1EspGames[] = {
+ { kKyra1, ES_ESP, -1, "9ff130d2558bcd674d4074849d93c362", kyra1EspFloppy },
+ GAME_DUMMY_ENTRY
+};
diff --git a/tools/create_kyradat/fre.h b/tools/create_kyradat/fre.h
new file mode 100644
index 0000000000..970769f95a
--- /dev/null
+++ b/tools/create_kyradat/fre.h
@@ -0,0 +1,79 @@
+const ExtractEntry kyra1FreFloppy[] = {
+ { kKallakWritingSeq, 0x00030598, 0x00030D8D },
+ { kMalcolmTreeSeq, 0x00030D8D, 0x00030FA3 },
+ { kWestwoodLogoSeq, 0x00030FA3, 0x00030FEE },
+ { kKyrandiaLogoSeq, 0x00030FEE, 0x0003104A },
+ { kKallakMalcolmSeq, 0x0003104A, 0x000312B5 },
+ { kForestSeq, 0x000312B5, 0x0003144A },
+ { kIntroCPSStrings, 0x0003144A, 0x0003145E },
+ { kIntroWSAStrings, 0x0003145E, 0x000314DE },
+ { kIntroCOLStrings, 0x000314DE, 0x00031509 },
+ { kIntroStrings, 0x00031509, 0x00031AF8 },
+ { kItemNames, 0x00034862, 0x00034d68 },
+ { kTakenStrings, 0x00034062, 0x00034080 },
+ { kPlacedStrings, 0x00034080, 0x00034091 },
+ { kDroppedStrings, 0x0003412f, 0x00034140 },
+ { kNoDropStrings, 0x00034016, 0x00034062 },
+ { kPutDownString, 0x0002f240, 0x0002f26e },
+ { kWaitAmuletString, 0x0002f26e, 0x0002f2b7 },
+ { kBlackJewelString, 0x0002f2b7, 0x0002f2e2 },
+ { kHealingTipString, 0x0002f2e2, 0x0002f318 },
+ { kPoisonGoneString, 0x0002f384, 0x0002f3dd },
+ { kThePoisonStrings, 0x0003000e, 0x00030076 },
+ { kFluteStrings, 0x000324af, 0x000324f4 },
+ { kWispJewelStrings, 0x0002f318, 0x0002f373 },
+ { kMagicJewelStrings, 0x0002f373, 0x0002f384 },
+ { kFlaskFullString, 0x0003011c, 0x0003013a },
+ { kFullFlaskString, 0x00030096, 0x0003011c },
+ { kOutroHomeString, 0x000321f4, 0x000321fb },
+ { kVeryCleverString, 0x0003215e, 0x00032185 },
+ { kGUIStrings, 0x0002f51c, 0x0002f750 },
+ { kNewGameString, 0x00032ca2, 0x00032cbf },
+ { kConfigStrings, 0x0002ff96, 0x0002ffe1 },
+ { -1, 0, 0 }
+};
+
+const ExtractEntry kyra1FreCD[] = {
+ { kKallakWritingSeq, 0x0003023D, 0x00030A42 },
+ { kMalcolmTreeSeq, 0x00030A42, 0x00030C72 },
+ { kWestwoodLogoSeq, 0x00030C72, 0x00030CBD },
+ { kKyrandiaLogoSeq, 0x00030CBD, 0x00030D63 },
+ { kKallakMalcolmSeq, 0x00030D63, 0x0003101B },
+ { kForestSeq, 0x0003101B, 0x0003128E },
+ { kIntroCPSStrings, 0x0003128E, 0x000312A3 },
+ { kIntroWSAStrings, 0x000312A3, 0x00031323 },
+ { kIntroCOLStrings, 0x00031323, 0x0003134E },
+ { kIntroStrings, 0x0003134E, 0x0003193E },
+ { kRoomList, 0x000283A0, 0x0002D176 },
+ { kRoomFilenames, 0x000342AA, 0x00034586 },
+ { kCharacterImageFilenames, 0x00033206, 0x000332EA },
+ { kDefaultShapes, 0x0002D330, 0x0002D823 },
+ { kItemNames, 0x000347C0, 0x00034CC6 },
+ { kTakenStrings, 0x0003427B, 0x0003428A },
+ { kPlacedStrings, 0x000341EA, 0x000341FB },
+ { kDroppedStrings, 0x00034299, 0x000342AA },
+ { kNoDropStrings, 0x00034180, 0x000341CC },
+ { kPutDownString, 0x0002F070, 0x0002F09E },
+ { kWaitAmuletString, 0x0002F09E, 0x0002F0E7 },
+ { kBlackJewelString, 0x0002F0E7, 0x0002F112 },
+ { kHealingTipString, 0x0002F112, 0x0002F148 },
+ { kPoisonGoneString, 0x0002F1A9, 0x0002F1D3 },
+ { kThePoisonStrings, 0x0002FE76, 0x0002FEDE },
+ { kFluteStrings, 0x000327EA, 0x0003282F },
+ { kWispJewelStrings, 0x0002F148, 0x0002F198 },
+ { kMagicJewelStrings, 0x0002F198, 0x0002F1A9 },
+ { kFlaskFullString, 0x0002FF8C, 0x0002FFAA },
+ { kFullFlaskString, 0x0002FF06, 0x0002FF8C },
+ { kOutroHomeString, 0x000320D6, 0x000320DD },
+ { kVeryCleverString, 0x00032038, 0x0003205F },
+ { kGUIStrings, 0x0002f32c, 0x0002f589 },
+ { kNewGameString, 0x00032FDF, 0x00032FFC },
+ { kConfigStrings, 0x0002fdcf, 0x0002fe49 },
+ { -1, 0, 0 }
+};
+
+const Game kyra1FreGames[] = {
+ { kKyra1, FR_FRA, -1, "aa9d6d78d8b199deaf48efeca6d19af2", kyra1FreFloppy },
+ { kKyra1, FR_FRA, kTalkieVersion, "307c5d4a554d9068ac3d326e350ae4a6", kyra1FreCD },
+ GAME_DUMMY_ENTRY
+};
diff --git a/tools/create_kyradat/ger.h b/tools/create_kyradat/ger.h
new file mode 100644
index 0000000000..5ecfc7e644
--- /dev/null
+++ b/tools/create_kyradat/ger.h
@@ -0,0 +1,80 @@
+const ExtractEntry kyra1GerFloppy[] = {
+ { kKallakWritingSeq, 0x000304F2, 0x00030CE7 },
+ { kMalcolmTreeSeq, 0x00030CE7, 0x00030EFD },
+ { kWestwoodLogoSeq, 0x00030EFD, 0x00030F48 },
+ { kKyrandiaLogoSeq, 0x00030F48, 0x00030FA4 },
+ { kKallakMalcolmSeq, 0x00030FA4, 0x0003120F },
+ { kForestSeq, 0x0003120F, 0x000313A4 },
+ { kIntroCPSStrings, 0x000313A4, 0x000313B8 },
+ { kIntroWSAStrings, 0x000313B8, 0x00031438 },
+ { kIntroCOLStrings, 0x00031438, 0x00031463 },
+ { kIntroStrings, 0x00031463, 0x00031A68 },
+ { kRoomFilenames, 0x00034058, 0x00034334 },
+ { kItemNames, 0x00034776, 0x00034C88 },
+ { kTakenStrings, 0x00033FEE, 0x0003400A },
+ { kPlacedStrings, 0x0003400A, 0x00034015 },
+ { kDroppedStrings, 0x00034046, 0x00034057 },
+ { kNoDropStrings, 0x00033FA2, 0x00033FEE },
+ { kPutDownString, 0x0002F100, 0x0002F128 },
+ { kWaitAmuletString, 0x0002F128, 0x0002F170 },
+ { kBlackJewelString, 0x0002F170, 0x0002F1A1 },
+ { kHealingTipString, 0x0002F1A1, 0x0002F1DD },
+ { kPoisonGoneString, 0x0002F252, 0x0002F288 },
+ { kThePoisonStrings, 0x0002FF00, 0x0002FF72 },
+ { kFluteStrings, 0x0003243F, 0x0003247F },
+ { kWispJewelStrings, 0x0002F1DD, 0x0002F23E },
+ { kMagicJewelStrings, 0x0002F23E, 0x0002F252 },
+ { kFlaskFullString, 0x00030041, 0x0003005F },
+ { kFullFlaskString, 0x0002FF92, 0x00030041 },
+ { kOutroHomeString, 0x0003217E, 0x0003218C },
+ { kVeryCleverString, 0x000320CC, 0x0003210F },
+ { kGUIStrings, 0x0002f3fa, 0x0002f630 },
+ { kNewGameString, 0x00032c2e, 0x00032c4b },
+ { kConfigStrings, 0x0002fe76, 0x0002fed4 },
+ { -1, 0, 0 }
+};
+
+const ExtractEntry kyra1GerCD[] = {
+ { kKallakWritingSeq, 0x0003018F, 0x00030994 },
+ { kMalcolmTreeSeq, 0x00030994, 0x00030BC4 },
+ { kWestwoodLogoSeq, 0x00030BC4, 0x00030C0F },
+ { kKyrandiaLogoSeq, 0x00030C0F, 0x00030CB5 },
+ { kKallakMalcolmSeq, 0x00030CB5, 0x00030F6D },
+ { kForestSeq, 0x00030F6D, 0x000311E0 },
+ { kIntroCPSStrings, 0x000311E0, 0x000311F5 },
+ { kIntroWSAStrings, 0x000311F5, 0x00031275 },
+ { kIntroCOLStrings, 0x00031275, 0x000312A0 },
+ { kIntroStrings, 0x000312A0, 0x000318A6 },
+ { kRoomList, 0x00028280, 0x0002D056 },
+ { kRoomFilenames, 0x000341FA, 0x000344D6 },
+ { kCharacterImageFilenames, 0x000331CA, 0x000332AE },
+ { kDefaultShapes, 0x0002D210, 0x0002D703 },
+ { kItemNames, 0x00034710, 0x00034C22 },
+ { kTakenStrings, 0x00034190, 0x000341AC },
+ { kPlacedStrings, 0x000341AC, 0x000341B7 },
+ { kDroppedStrings, 0x000341E8, 0x000341F9 },
+ { kNoDropStrings, 0x00034144, 0x00034190 },
+ { kPutDownString, 0x0002EF50, 0x0002EF78 },
+ { kWaitAmuletString, 0x0002EF78, 0x0002EFC0 },
+ { kBlackJewelString, 0x0002EFC0, 0x0002EFF1 },
+ { kHealingTipString, 0x0002EFF1, 0x0002F02D },
+ { kPoisonGoneString, 0x0002F099, 0x0002F0CF },
+ { kThePoisonStrings, 0x0002FD82, 0x0002FDF4 },
+ { kFluteStrings, 0x000327B4, 0x000327F4 },
+ { kWispJewelStrings, 0x0002F02D, 0x0002F085 },
+ { kMagicJewelStrings, 0x0002F085, 0x0002F099 },
+ { kFlaskFullString, 0x0002FECB, 0x0002FEE9 },
+ { kFullFlaskString, 0x0002FE1C, 0x0002FECB },
+ { kOutroHomeString, 0x0003205A, 0x00032068 },
+ { kVeryCleverString, 0x00031FA0, 0x00031FE3 },
+ { kGUIStrings, 0x0002F22C, 0x0002F48D },
+ { kNewGameString, 0x00032FA3, 0x00032FC0 },
+ { kConfigStrings, 0x0002fcd3, 0x0002fd55 },
+ { -1, 0, 0 }
+};
+
+const Game kyra1GerGames[] = {
+ { kKyra1, DE_DEU, -1, "9442d6f7db6a41f3dd4aa4de5d36e107", kyra1GerFloppy },
+ { kKyra1, DE_DEU, kTalkieVersion, "c65d381184f98ac26d9efd2d45baef51", kyra1GerCD },
+ GAME_DUMMY_ENTRY
+};
diff --git a/tools/create_kyradat/md5.cpp b/tools/create_kyradat/md5.cpp
new file mode 100644
index 0000000000..abdc002eb0
--- /dev/null
+++ b/tools/create_kyradat/md5.cpp
@@ -0,0 +1,261 @@
+/* Scumm Tools
+ * Copyright (C) 2004-2006 The ScummVM Team
+ *
+ * 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/tools/trunk/utils/md5.cpp $
+ * $Id: md5.cpp 23138 2006-06-15 15:44:06Z h00ligan $
+ *
+ */
+
+#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'", 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/tools/create_kyradat/md5.h b/tools/create_kyradat/md5.h
new file mode 100644
index 0000000000..c945684d83
--- /dev/null
+++ b/tools/create_kyradat/md5.h
@@ -0,0 +1,40 @@
+/* Scumm Tools
+ * Copyright (C) 2004-2006 The ScummVM Team
+ *
+ * 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/tools/trunk/utils/md5.h $
+ * $Id: md5.h 23138 2006-06-15 15:44:06Z h00ligan $
+ *
+ */
+
+#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/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h
new file mode 100644
index 0000000000..191abf3370
--- /dev/null
+++ b/tools/create_kyradat/misc.h
@@ -0,0 +1,207 @@
+const int kyra1FloppyNeed[] = {
+ kKallakWritingSeq,
+ kMalcolmTreeSeq,
+ kWestwoodLogoSeq,
+ kKyrandiaLogoSeq,
+ kKallakMalcolmSeq,
+ kForestSeq,
+ kIntroCPSStrings,
+ kIntroCOLStrings,
+ kIntroWSAStrings,
+ kIntroStrings,
+ kRoomList,
+ kRoomFilenames,
+ kCharacterImageFilenames,
+ kDefaultShapes,
+ kItemNames,
+ kTakenStrings,
+ kPlacedStrings,
+ kDroppedStrings,
+ kNoDropStrings,
+ kAmuleteAnimSeq,
+ kPaletteList1,
+ kPaletteList2,
+ kPaletteList3,
+ kPaletteList4,
+ kPaletteList5,
+ kPaletteList6,
+ kPaletteList7,
+ kPaletteList8,
+ kPaletteList9,
+ kPaletteList10,
+ kPaletteList11,
+ kPaletteList12,
+ kPaletteList13,
+ kPaletteList14,
+ kPaletteList15,
+ kPaletteList16,
+ kPaletteList17,
+ kPaletteList18,
+ kPaletteList19,
+ kPaletteList20,
+ kPaletteList21,
+ kPaletteList22,
+ kPaletteList23,
+ kPaletteList24,
+ kPaletteList25,
+ kPaletteList26,
+ kPaletteList27,
+ kPaletteList28,
+ kPaletteList29,
+ kPaletteList30,
+ kPaletteList31,
+ kPaletteList32,
+ kPaletteList33,
+ kPutDownString,
+ kWaitAmuletString,
+ kBlackJewelString,
+ kHealingTipString,
+ kPoisonGoneString,
+ kHealing1Shapes,
+ kHealing2Shapes,
+ kThePoisonStrings,
+ kFluteStrings,
+ kPoisonDeathShapes,
+ kFluteShapes,
+ kWinter1Shapes,
+ kWinter2Shapes,
+ kWinter3Shapes,
+ kDrinkShapes,
+ kWispShapes,
+ kMagicAnimShapes,
+ kBranStoneShapes,
+ kWispJewelStrings,
+ kMagicJewelStrings,
+ kFlaskFullString,
+ kFullFlaskString,
+ kOutroReunionSeq,
+ kOutroHomeString,
+ kVeryCleverString,
+ kGUIStrings,
+ kNewGameString,
+ kConfigStrings,
+ -1
+};
+
+const int kyra1CDNeed[] = {
+ kKallakWritingSeq,
+ kMalcolmTreeSeq,
+ kWestwoodLogoSeq,
+ kKyrandiaLogoSeq,
+ kKallakMalcolmSeq,
+ kForestSeq,
+ kIntroCPSStrings,
+ kIntroCOLStrings,
+ kIntroWSAStrings,
+ kIntroStrings,
+ kRoomList,
+ kRoomFilenames,
+ kCharacterImageFilenames,
+ kDefaultShapes,
+ kItemNames,
+ kTakenStrings,
+ kPlacedStrings,
+ kDroppedStrings,
+ kNoDropStrings,
+ kAmuleteAnimSeq,
+ kPaletteList1,
+ kPaletteList2,
+ kPaletteList3,
+ kPaletteList4,
+ kPaletteList5,
+ kPaletteList6,
+ kPaletteList7,
+ kPaletteList8,
+ kPaletteList9,
+ kPaletteList10,
+ kPaletteList11,
+ kPaletteList12,
+ kPaletteList13,
+ kPaletteList14,
+ kPaletteList15,
+ kPaletteList16,
+ kPaletteList17,
+ kPaletteList18,
+ kPaletteList19,
+ kPaletteList20,
+ kPaletteList21,
+ kPaletteList22,
+ kPaletteList23,
+ kPaletteList24,
+ kPaletteList25,
+ kPaletteList26,
+ kPaletteList27,
+ kPaletteList28,
+ kPaletteList29,
+ kPaletteList30,
+ kPaletteList31,
+ kPaletteList32,
+ kPaletteList33,
+ kPutDownString,
+ kWaitAmuletString,
+ kBlackJewelString,
+ kHealingTipString,
+ kPoisonGoneString,
+ kHealing1Shapes,
+ kHealing2Shapes,
+ kThePoisonStrings,
+ kFluteStrings,
+ kPoisonDeathShapes,
+ kFluteShapes,
+ kWinter1Shapes,
+ kWinter2Shapes,
+ kWinter3Shapes,
+ kDrinkShapes,
+ kWispShapes,
+ kMagicAnimShapes,
+ kBranStoneShapes,
+ kWispJewelStrings,
+ kMagicJewelStrings,
+ kFlaskFullString,
+ kFullFlaskString,
+ kOutroReunionSeq,
+ kOutroHomeString,
+ kVeryCleverString,
+ kGUIStrings,
+ kNewGameString,
+ kConfigStrings,
+ -1
+};
+
+const int kyra1DemoNeed[] = {
+ kWestwoodLogoSeq,
+ kKyrandiaLogoSeq,
+ kIntroCPSStrings,
+ kIntroCOLStrings,
+ kIntroWSAStrings,
+ kIntroStrings,
+ kDemo1Seq,
+ kDemo2Seq,
+ kDemo3Seq,
+ kDemo4Seq,
+ -1
+};
+
+const GameNeed gameNeedTable[] = {
+ { kKyra1, -1, kyra1FloppyNeed },
+ { kKyra1, kTalkieVersion, kyra1CDNeed },
+ { kKyra1, kDemoVersion, kyra1DemoNeed },
+ { -1, -1, 0 }
+};
+
+const SpecialExtension specialTable[] = {
+ { kTalkieVersion, "CD" },
+ { kDemoVersion, "DEM" },
+ { kFMTownsVersion, "TNS" },
+ { -1, 0 }
+};
+
+const Language languageTable[] = {
+ { EN_ANY, "ENG" },
+ { DE_DEU, "GER" },
+ { FR_FRA, "FRE" },
+ { IT_ITA, "ITA" },
+ { ES_ESP, "SPA" },
+ { JA_JPN, "JPN" },
+ { -1, 0 }
+};
diff --git a/tools/create_kyradat/pak.cpp b/tools/create_kyradat/pak.cpp
new file mode 100644
index 0000000000..63e9792d23
--- /dev/null
+++ b/tools/create_kyradat/pak.cpp
@@ -0,0 +1,244 @@
+/* Scumm Tools
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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$
+ *
+ */
+
+#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");
+ 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");
+ 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");
+ 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/tools/create_kyradat/pak.h b/tools/create_kyradat/pak.h
new file mode 100644
index 0000000000..f81e0be011
--- /dev/null
+++ b/tools/create_kyradat/pak.h
@@ -0,0 +1,107 @@
+/* Scumm Tools
+ * Copyright (C) 2007 The ScummVM project
+ *
+ * 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; }
+
+ const 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/tools/create_kyradat/util.c b/tools/create_kyradat/util.c
new file mode 100644
index 0000000000..a2680e6a26
--- /dev/null
+++ b/tools/create_kyradat/util.c
@@ -0,0 +1,137 @@
+/* Scumm Tools
+ * Copyright (C) 2003-2006 The ScummVM Team
+ *
+ * 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/tools/trunk/util.c $
+ * $Id: util.c 23136 2006-06-15 14:34:46Z h00ligan $
+ *
+ */
+
+#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/tools/create_kyradat/util.h b/tools/create_kyradat/util.h
new file mode 100644
index 0000000000..9826e22f70
--- /dev/null
+++ b/tools/create_kyradat/util.h
@@ -0,0 +1,265 @@
+/* Scumm Tools
+ * Copyright (C) 2002-2006 The ScummVM project
+ *
+ * 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/tools/trunk/util.h $
+ * $Id: util.h 23139 2006-06-15 16:58:09Z eriktorbjorn $
+ *
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#if !defined(_MSC_VER)
+#include <unistd.h>
+#endif
+
+#ifdef WIN32
+#include <io.h>
+#include <process.h>
+#endif
+
+
+/*
+ * Some useful types
+ */
+
+typedef unsigned char byte;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+
+#if !defined(__cplusplus)
+typedef uint8 bool;
+#define false 0
+#define true 1
+
+/* If your C compiler doesn't support 'inline', please add a check for it. */
+#if defined(_MSC_VER)
+#define inline __inline
+#endif
+
+#endif
+
+
+/*
+ * Various utility macros
+ */
+
+#if defined(_MSC_VER)
+
+ #define scumm_stricmp stricmp
+ #define scumm_strnicmp _strnicmp
+ #define snprintf _snprintf
+
+ #define SCUMM_LITTLE_ENDIAN
+
+ #define START_PACK_STRUCTS pack(push, 1)
+ #define END_PACK_STRUCTS pack(pop)
+
+
+#elif defined(__MINGW32__)
+
+ #define scumm_stricmp stricmp
+ #define scumm_strnicmp strnicmp
+
+ #define SCUMM_LITTLE_ENDIAN
+
+ #define START_PACK_STRUCTS pack(push, 1)
+ #define END_PACK_STRUCTS pack(pop)
+
+
+ #ifndef _HEAPOK
+ #define _HEAPOK (-2)
+ #endif
+
+#elif defined(UNIX)
+
+ #define scumm_stricmp strcasecmp
+ #define scumm_strnicmp strncasecmp
+
+ #if defined(__DECCXX) /* Assume alpha architecture */
+ #define INVERSE_MKID
+ #define SCUMM_NEED_ALIGNMENT
+ #endif
+
+ #if !defined(__GNUC__)
+ #define START_PACK_STRUCTS pack (1)
+ #define END_PACK_STRUCTS pack ()
+ #endif
+
+#else
+
+ #error No system type defined
+
+#endif
+
+
+/*
+ * GCC specific stuff
+ */
+#if defined(__GNUC__)
+ #define GCC_PACK __attribute__((packed))
+ #define NORETURN __attribute__((__noreturn__))
+ #define GCC_PRINTF(x,y) __attribute__((format(printf, x, y)))
+#else
+ #define GCC_PACK
+ #define GCC_PRINTF(x,y)
+#endif
+
+#define READ_UINT16(a) READ_LE_UINT16(a)
+#define READ_UINT32(a) READ_LE_UINT32(a)
+
+#define WRITE_UINT16(a, v) WRITE_LE_UINT16(a, v)
+#define WRITE_UINT32(a, v) WRITE_LE_UINT32(a, v)
+
+#define FROM_LE_32(a) ((uint32)(a))
+#define FROM_LE_16(a) ((uint16)(a))
+
+#define TO_LE_32(a) ((uint32)(a))
+#define TO_LE_16(a) ((uint16)(a))
+
+#define TO_BE_32(a) SWAP_BYTES_32(a)
+#define TO_BE_16(a) SWAP_BYTES_16(a)
+
+#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
+
+static inline uint32 SWAP_32(uint32 a) {
+ return ((a >> 24) & 0xFF) | ((a >> 8) & 0xFF00) | ((a << 8) & 0xFF0000) |
+ ((a << 24) & 0xFF000000);
+}
+
+static inline uint16 SWAP_16(uint16 a) {
+ return ((a >> 8) & 0xFF) | ((a << 8) & 0xFF00);
+}
+
+#define FORCEINLINE static inline
+
+FORCEINLINE uint16 READ_LE_UINT16(const void *ptr) {
+ const byte *b = (const byte *)ptr;
+ return (b[1] << 8) + b[0];
+}
+FORCEINLINE uint32 READ_LE_UINT32(const void *ptr) {
+ const byte *b = (const byte *)ptr;
+ return (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0]);
+}
+FORCEINLINE void WRITE_LE_UINT16(void *ptr, uint16 value) {
+ byte *b = (byte *)ptr;
+ b[0] = (byte)(value >> 0);
+ b[1] = (byte)(value >> 8);
+}
+FORCEINLINE void WRITE_LE_UINT32(void *ptr, uint32 value) {
+ byte *b = (byte *)ptr;
+ b[0] = (byte)(value >> 0);
+ b[1] = (byte)(value >> 8);
+ b[2] = (byte)(value >> 16);
+ b[3] = (byte)(value >> 24);
+}
+
+FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) {
+ const byte *b = (const byte *)ptr;
+ return (b[0] << 8) + b[1];
+}
+FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) {
+ const byte *b = (const byte*)ptr;
+ return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3]);
+}
+FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) {
+ byte *b = (byte *)ptr;
+ b[0] = (byte)(value >> 8);
+ b[1] = (byte)(value >> 0);
+}
+FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) {
+ byte *b = (byte *)ptr;
+ b[0] = (byte)(value >> 24);
+ b[1] = (byte)(value >> 16);
+ b[2] = (byte)(value >> 8);
+ b[3] = (byte)(value >> 0);
+}
+
+#if defined(__GNUC__)
+#define NORETURN_PRE
+#define NORETURN_POST __attribute__((__noreturn__))
+#elif defined(_MSC_VER)
+#define NORETURN_PRE _declspec(noreturn)
+#define NORETURN_POST
+#else
+#define NORETURN_PRE
+#define NORETURN_POST
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#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, ...);
+
+enum {
+ EN_ANY, // Generic English (when only one game version exist)
+ EN_USA,
+ EN_GRB,
+
+ DE_DEU,
+ FR_FRA,
+ IT_ITA,
+ PT_BRA,
+ ES_ESP,
+ JA_JPN,
+ ZH_TWN,
+ KO_KOR,
+ SE_SWE,
+ HB_ISR,
+ RU_RUS,
+ CZ_CZE,
+ NL_NLD,
+ NB_NOR,
+ PL_POL,
+
+ UNK_LANG = -1 // Use default language (i.e. none specified)
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif