aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/create_kyradat/Makefile2
-rw-r--r--tools/create_kyradat/create_kyradat.cpp154
-rw-r--r--tools/create_kyradat/create_kyradat.h8
-rw-r--r--tools/create_kyradat/misc.h122
-rw-r--r--tools/create_kyradat/towns.h121
5 files changed, 381 insertions, 26 deletions
diff --git a/tools/create_kyradat/Makefile b/tools/create_kyradat/Makefile
index b90f8940b7..ce4fa5ca91 100644
--- a/tools/create_kyradat/Makefile
+++ b/tools/create_kyradat/Makefile
@@ -19,7 +19,7 @@ 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
+create_kyradat.o: eng.h esp.h fre.h ger.h misc.h pak.h towns.h util.h md5.h
pak.o: pak.h util.h
%.o: %.cpp
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index 5210dd2054..8a58436614 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -25,7 +25,7 @@
#include "md5.h"
enum {
- kKyraDatVersion = 14,
+ kKyraDatVersion = 15,
kIndexSize = 12
};
@@ -36,11 +36,12 @@ enum {
#include "esp.h"
#include "fre.h"
#include "ger.h"
+#include "towns.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);
+bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
+bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
+bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
+bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
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);
@@ -159,7 +160,10 @@ const ExtractFilename extractFilenames[] = {
{ kPaletteList33, kTypeRawData, "PALTABLE33.PAL" },
// FM-TOWNS specific
- { kKyra1TownsSFXTable, kTypeRawData, "SFXTABLE.TSX" },
+ { kKyra1TownsSFXTable, kTypeRawData, "SFXTABLE" },
+ { kCreditsStrings, kTypeRawData, "CREDITS" },
+ { kMenuSKB, kTypeStringList, "MENUSKB" },
+ { kSjisVTable, kTypeRawData, "SJISTABLE" },
{ -1, 0, 0 }
};
@@ -282,32 +286,111 @@ bool hasNeededEntries(const Game *game, const PAKFile *file) {
// 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);
+bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
+ uint8 *buffer = 0;
+
+ if (fmtPatch == 2) {
+ buffer = new uint8[0x12602];
+ assert(buffer);
+ memcpy(buffer, data, 0x7EE5);
+ memcpy(buffer + 0x7EE5, data + 0x7EE7, 0x7FFF);
+ memcpy(buffer + 0xFEE4, data + 0xFEE8, 0x271E);
+ } else {
+ 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) {
+bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
uint32 entries = 0;
+ uint32 targetsize = size + 4;
for (uint32 i = 0; i < size; ++i) {
- if (!data[i])
+ if (!data[i]) {
++entries;
+ if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
+ // 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 size = strlen((const char*) data + i);
+ i += size; targetsize = --targetsize - size;
+ while (!data[++i]) {
+ if (i == size)
+ break;
+ targetsize--;
+ }
+ }
+ }
+ }
+ }
+
+ if (fmtPatch == 2) {
+ targetsize++;
+ entries++;
}
- uint8 *buffer = new uint8[size + 4];
+ uint8 *buffer = new uint8[targetsize];
assert(buffer);
uint8 *output = buffer;
+ uint8 *input = (uint8*) data;
WRITE_BE_UINT32(output, entries); output += 4;
- memcpy(output, data, size);
+ if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
+ const byte * c = data + size;
+ do {
+ 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 ((g->special == kFMTownsVersionE && input - data == 0x260) ||
+ (g->special == kFMTownsVersionJ && input - data == 0x265))
+ *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 {
+ memcpy(output, data, size);
+ }
- return out.addFile(filename, buffer, size + 4);
+ return out.addFile(filename, buffer, targetsize);
}
-bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename) {
- const int countRooms = size / 0x51;
+bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
+ // different entry size for the fm-towns version
+ const int countRooms = (g->special == kFMTownsVersionE) ? (size / 0x69) : (size / 0x51);
uint8 *buffer = new uint8[countRooms * 9 + 4];
assert(buffer);
@@ -322,13 +405,14 @@ bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 si
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);
+ // different entry size for the fm-towns version
+ src += (g->special == kFMTownsVersionE) ? 0x60 : (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) {
+bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
byte *buffer = new byte[size + 1 * 4];
assert(buffer);
byte *output = buffer;
@@ -365,7 +449,7 @@ uint32 getFeatures(const Game *g) {
features |= GF_TALKIE;
else if (g->special == kDemoVersion)
features |= GF_DEMO;
- else if (g->special == kFMTownsVersion)
+ else if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ)
features |= GF_FMTOWNS;
else
features |= GF_FLOPPY;
@@ -380,6 +464,8 @@ uint32 getFeatures(const Game *g) {
features |= GF_SPANISH;
else if (g->lang == IT_ITA)
features |= GF_ITALIAN;
+ else if (g->lang == JA_JPN)
+ features |= GF_JAPANESE;
return features;
}
@@ -501,6 +587,18 @@ int main(int argc, char *argv[]) {
if (!process(out, g, buffer, size))
fprintf(stderr, "ERROR: couldn't process file '%s'", argv[i]);
+ if (g->special == kFMTownsVersionE) {
+ // The English and non language specific data has now been extracted
+ // so we switch to Japanese and extract the rest
+ 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;
}
@@ -551,8 +649,18 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
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)) {
+
+ int patch = 0;
+ if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
+ // FM Towns files that need addional patches
+ if (i->id == kTakenStrings || i->id == kNoDropStrings || i->id == kPoisonGoneString ||
+ i->id == kThePoisonStrings || i->id == kFluteStrings || i->id == kWispJewelStrings)
+ patch = 1;
+ else if (i->id == kIntroStrings || i->id == kKyra1TownsSFXTable)
+ patch = 2;
+ }
+
+ if (!tDesc->extract(out, g, data + i->startOff, i->endOff - i->startOff, filename, patch)) {
fprintf(stderr, "ERROR: couldn't extract id %d\n", i->id);
return false;
}
@@ -573,6 +681,7 @@ const Game *gameDescs[] = {
kyra1EspGames,
kyra1FreGames,
kyra1GerGames,
+ kyra1TownsGames,
0
};
@@ -599,3 +708,4 @@ const Game *findGame(const byte *buffer, const uint32 size) {
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
index 4bcf289fad..2a75702e01 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -134,6 +134,9 @@ enum kExtractID {
kConfigStrings,
kKyra1TownsSFXTable,
+ kCreditsStrings,
+ kSjisVTable,
+ kMenuSKB,
kMaxResIDs
};
@@ -153,7 +156,8 @@ struct ExtractFilename {
enum kSpecial {
kTalkieVersion = 0,
kDemoVersion = 1,
- kFMTownsVersion = 2
+ kFMTownsVersionE = 2,
+ kFMTownsVersionJ = 3
};
struct SpecialExtension {
@@ -195,7 +199,7 @@ enum kExtractType {
struct ExtractType {
int type;
- bool (*extract)(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename);
+ bool (*extract)(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch);
void (*createFilename)(char *dstFilename, const int lang, const int special, const char *filename);
};
diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h
index 191abf3370..f4fd212839 100644
--- a/tools/create_kyradat/misc.h
+++ b/tools/create_kyradat/misc.h
@@ -182,9 +182,127 @@ const int kyra1DemoNeed[] = {
-1
};
+const int kyra1TownsEngNeed[] = {
+ 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,
+
+ kKyra1TownsSFXTable,
+ kCreditsStrings,
+ kMenuSKB,
+ kSjisVTable,
+ -1
+};
+
+const int kyra1TownsJapNeed[] = {
+ kIntroStrings,
+ kItemNames,
+ kTakenStrings,
+ kPlacedStrings,
+ kDroppedStrings,
+ kNoDropStrings,
+ kPutDownString,
+ kWaitAmuletString,
+ kBlackJewelString,
+ kHealingTipString,
+ kPoisonGoneString,
+ kThePoisonStrings,
+ kFluteStrings,
+ kWispJewelStrings,
+ kMagicJewelStrings,
+ kFlaskFullString,
+ kFullFlaskString,
+ kOutroHomeString,
+ kVeryCleverString,
+ kGUIStrings,
+ kNewGameString,
+ kConfigStrings,
+ -1
+};
+
const GameNeed gameNeedTable[] = {
{ kKyra1, -1, kyra1FloppyNeed },
{ kKyra1, kTalkieVersion, kyra1CDNeed },
+ { kKyra1, kFMTownsVersionE , kyra1TownsEngNeed},
+ { kKyra1, kFMTownsVersionJ, kyra1TownsJapNeed},
{ kKyra1, kDemoVersion, kyra1DemoNeed },
{ -1, -1, 0 }
};
@@ -192,7 +310,8 @@ const GameNeed gameNeedTable[] = {
const SpecialExtension specialTable[] = {
{ kTalkieVersion, "CD" },
{ kDemoVersion, "DEM" },
- { kFMTownsVersion, "TNS" },
+ { kFMTownsVersionE , "TNS" },
+ { kFMTownsVersionJ, "TNS" },
{ -1, 0 }
};
@@ -205,3 +324,4 @@ const Language languageTable[] = {
{ JA_JPN, "JPN" },
{ -1, 0 }
};
+
diff --git a/tools/create_kyradat/towns.h b/tools/create_kyradat/towns.h
new file mode 100644
index 0000000000..ad35ec7ab2
--- /dev/null
+++ b/tools/create_kyradat/towns.h
@@ -0,0 +1,121 @@
+const ExtractEntry kyra1FMTownsE[] = {
+ { kKallakWritingSeq, 0x0002F1FF, 0x0002F9F6 },
+ { kMalcolmTreeSeq, 0x0002FCC3, 0x0002FEDB },
+ { kWestwoodLogoSeq, 0x0002FEDB, 0x0002FF26 },
+ { kKyrandiaLogoSeq, 0x0002F9F7, 0x0002FA53 },
+ { kKallakMalcolmSeq, 0x0002FA53, 0x0002FCC0 },
+ { kForestSeq, 0x0002F067, 0x0002F1FD },
+ { kIntroCPSStrings, 0x00027D5A, 0x00027D6F },
+ { kIntroWSAStrings, 0x00027D72, 0x00027E05 },
+ { kIntroCOLStrings, 0x00027E06, 0x00027E36 },
+ { kIntroStrings, 0x00027E36, 0x0002837B },
+ { kRoomList, 0x0002FF90, 0x00036478 },
+ { kRoomFilenames, 0x00028B20, 0x00028E6C},
+ { kCharacterImageFilenames, 0x0002606E, 0x00026165 },
+ { kDefaultShapes, 0x00037CF9, 0x00038183 },
+ { kItemNames, 0x00029724, 0x00029C29 },
+ { kTakenStrings, 0x00028978, 0x00028994 },
+ { kPlacedStrings, 0x000289A0, 0x000289A9 },
+ { kDroppedStrings, 0x000289E4, 0x000289EE },
+ { kNoDropStrings, 0x00027C0E, 0x00027C88 },
+ { kAmuleteAnimSeq, 0x0002A814, 0x0002A83E },
+ { kPaletteList1, 0x0002E80B, 0x0002E820 },
+ { kPaletteList2, 0x0002E823, 0x0002E856 },
+ { kPaletteList3, 0x0002E857, 0x0002E88A },
+ { kPaletteList4, 0x0002E88B, 0x0002E8BE },
+ { kPaletteList5, 0x0002E8BF, 0x0002E8F2 },
+ { kPaletteList6, 0x0002E8F3, 0x0002E926 },
+ { kPaletteList7, 0x0002E927, 0x0002E95D },
+ { kPaletteList8, 0x0002E95F, 0x0002E995 },
+ { kPaletteList9, 0x0002E997, 0x0002E9C4 },
+ { kPaletteList10, 0x0002E9C7, 0x0002E9F4 },
+ { kPaletteList11, 0x0002E9F7, 0x0002EA24 },
+ { kPaletteList12, 0x0002EA27, 0x0002EA54 },
+ { kPaletteList13, 0x0002EA54, 0x0002EA81 },
+ { kPaletteList14, 0x0002EA87, 0x0002EAC3 },
+ { kPaletteList15, 0x0002EAC3, 0x0002EAF0 },
+ { kPaletteList16, 0x0002EAF3, 0x0002EB14 },
+ { kPaletteList17, 0x0002EB17, 0x0002EB38 },
+ { kPaletteList18, 0x0002EB3B, 0x0002EB50 },
+ { kPaletteList19, 0x0002EB53, 0x0002EB68 },
+ { kPaletteList20, 0x0002EB6B, 0x0002EB80 },
+ { kPaletteList21, 0x0002EB83, 0x0002EB98 },
+ { kPaletteList22, 0x0002EB9B, 0x0002EBB0 },
+ { kPaletteList23, 0x0002EBB3, 0x0002EBC8 },
+ { kPaletteList24, 0x0002EBCB, 0x0002EBFB },
+ { kPaletteList25, 0x0002EBFB, 0x0002EC2B },
+ { kPaletteList26, 0x0002EC2B, 0x0002EC5B },
+ { kPaletteList27, 0x0002EC5B, 0x0002EC8B },
+ { kPaletteList28, 0x0002EC8B, 0x0002ECBB },
+ { kPaletteList29, 0x0002ECBB, 0x0002ECEB },
+ { kPaletteList30, 0x0002ECEB, 0x0002ED27 },
+ { kPaletteList31, 0x0002ED27, 0x0002ED4E },
+ { kPaletteList32, 0x0002ED4F, 0x0002ED76 },
+ { kPaletteList33, 0x0002ED77, 0x0002EDB3 },
+ { kPutDownString, 0x00025BD6, 0x00025BFC },
+ { kWaitAmuletString, 0x00025C2A, 0x00025C67 },
+ { kBlackJewelString, 0x00025C96, 0x00025CB9 },
+ { kHealingTipString, 0x00025CF2, 0x00025D1F },
+ { kPoisonGoneString, 0x00025E06, 0x00025E42 },
+ { kHealing1Shapes, 0x000381F1, 0x0003828B },
+ { kHealing2Shapes, 0x0003828D, 0x0003835F },
+ { kThePoisonStrings, 0x000294B8, 0x0002954A },
+ { kFluteStrings, 0x00025B1E, 0x00025B78 },
+ { kPoisonDeathShapes, 0x0003865D, 0x000386E9 },
+ { kFluteShapes, 0x00038561, 0x0003865D },
+ { kWinter1Shapes, 0x00038361, 0x00038392 },
+ { kWinter2Shapes, 0x00038395, 0x0003848A },
+ { kWinter3Shapes, 0x0003848D, 0x000384A9 },
+ { kDrinkShapes, 0x00038185, 0x000381EF },
+ { kWispShapes, 0x000384A9, 0x0003855F },
+ { kMagicAnimShapes, 0x000386E9, 0x0003870C },
+ { kBranStoneShapes, 0x0003870D, 0x00038770 },
+ { kWispJewelStrings, 0x00025D4E, 0x00025DC3 },
+ { kMagicJewelStrings, 0x00025DE2, 0x00025DF5 },
+ { kFlaskFullString, 0x00029688, 0x000296A4 },
+ { kFullFlaskString, 0x00029568, 0x00029605 },
+ { kOutroReunionSeq, 0x0002B529, 0x0002BA70 },
+ { kOutroHomeString, 0x00025F7E, 0x00025F83 },
+ { kVeryCleverString, 0x00025F8E, 0x00025FC0 },
+ { kGUIStrings, 0x000291E0, 0x000293DC },
+ { kNewGameString, 0x0002919C, 0x000291B1 },
+ { kConfigStrings, 0x00029360, 0x000293AA},
+ { kKyra1TownsSFXTable, 0x0003A978, 0x0004CF80 },
+ { kCreditsStrings, 0x0002AED8, 0x0002B464 },
+ { kMenuSKB, 0x000293DE, 0x000294A7 },
+ { kSjisVTable, 0x0003A421, 0x0003A749 },
+ { -1, 0, 0 }
+};
+
+const ExtractEntry kyra1FMTownsJ[] = {
+ { kIntroStrings, 0x0002837C, 0x00028977 },
+ { kItemNames, 0x00029C2C, 0x0002A1B3 },
+ { kTakenStrings, 0x00028980, 0x0002899F },
+ { kPlacedStrings, 0x000289AC, 0x000289B9 },
+ { kDroppedStrings, 0x000289F0, 0x000289FB },
+ { kNoDropStrings, 0x00027C3E, 0x00027C9F },
+ { kPutDownString, 0x00025BFE, 0x00025C27 },
+ { kWaitAmuletString, 0x00025C6A, 0x00025C93 },
+ { kBlackJewelString, 0x00025CBA, 0x00025CEF },
+ { kHealingTipString, 0x00025D22, 0x00025D4D },
+ { kPoisonGoneString, 0x00025E12, 0x00025E4F },
+ { kThePoisonStrings, 0x000294C8, 0x00029568 },
+ { kFluteStrings, 0x00025B3E, 0x00025B91 },
+ { kWispJewelStrings, 0x00025D7A, 0x00025DE1 },
+ { kMagicJewelStrings, 0x00025DF6, 0x00025E05 },
+ { kFlaskFullString, 0x000296A4, 0x000296C3 },
+ { kFullFlaskString, 0x00029608, 0x00029685 },
+ { kOutroHomeString, 0x00025F86, 0x00025F8D },
+ { kVeryCleverString, 0x00025FC2, 0x00025FF1 },
+ { kGUIStrings, 0x000368D1, 0x00036B30 },
+ { kNewGameString, 0x000291B4, 0x000291CF},
+ { kConfigStrings, 0x000290AC, 0x00029103 },
+ { -1, 0, 0 }
+};
+
+const Game kyra1TownsGames[] = {
+ { kKyra1, EN_ANY, kFMTownsVersionE, "5a3ad60ccd0f2e29463e0368cd14a60d", kyra1FMTownsE },
+ { kKyra1, JA_JPN, kFMTownsVersionJ, "5a3ad60ccd0f2e29463e0368cd14a60d", kyra1FMTownsJ },
+ GAME_DUMMY_ENTRY
+};
+