Commit slighty modified patch #1865509 "KYRA: kyradat support for hof".

svn-id: r30393
This commit is contained in:
Johannes Schickel 2008-01-10 23:24:43 +00:00
parent 1f6237567e
commit 89cedb5d1e
9 changed files with 727 additions and 36 deletions

View File

@ -31,7 +31,7 @@
#include "md5.h"
enum {
kKyraDatVersion = 17,
kKyraDatVersion = 18,
kIndexSize = 12
};
@ -45,6 +45,11 @@ enum {
#include "towns.h"
#include "amiga.h"
#include "hof_floppy.h"
#include "hof_towns.h"
#include "hof_cd.h"
#include "hof_demo.h"
const Game kyra1FanTranslations[] = {
{ kKyra1, IT_ITA, kTalkieVersion, "d0f1752098236083d81b9497bd2b6989", kyra1FreCD },
GAME_DUMMY_ENTRY
@ -54,9 +59,13 @@ bool extractRaw(PAKFile &out, const Game *g, const byte *data, const uint32 size
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);
bool extractHofSeqData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
int extractHofSeqData_checkString(const void *ptr, uint8 checkSize);
int extractHofSeqData_isSequence(const void *ptr, const Game *g, uint32 maxCheckSize);
int extractHofSeqData_isControl(const void *ptr, uint32 size);
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);
void createFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
void createLangFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
const ExtractType extractTypeTable[] = {
{ kTypeLanguageList, extractStrings, createLangFilename },
@ -64,6 +73,9 @@ const ExtractType extractTypeTable[] = {
{ kTypeRoomList, extractRooms, createFilename },
{ kTypeShapeList, extractShapes, createFilename },
{ kTypeRawData, extractRaw, createFilename },
{ k2TypeSeqData, extractHofSeqData, createFilename },
{ -1, 0, 0}
};
@ -133,6 +145,10 @@ const ExtractFilename extractFilenames[] = {
// IMAGE filename table
{ kCharacterImageFilenames, kTypeStringList, "CHAR-IMAGE.TXT" },
// AUDIO filename table
{ kAudioTracks, kTypeStringList, "TRACKS.TXT" },
{ kAudioTracksIntro, kTypeStringList, "TRACKSINT.TXT" },
// AMULET anim
{ kAmuleteAnimSeq, kTypeRawData, "AMULETEANIM.SEQ" },
@ -172,10 +188,30 @@ const ExtractFilename extractFilenames[] = {
{ kPaletteList33, kTypeRawData, "PALTABLE33.PAL" },
// FM-TOWNS specific
{ kKyra1TownsSFXTable, kTypeRawData, "SFXTABLE" },
{ kKyra1TownsSFXwdTable, kTypeRawData, "SFXWDTABLE" },
{ kKyra1TownsSFXbtTable, kTypeRawData, "SFXBTTABLE" },
{ kKyra1TownsCDATable, kTypeRawData, "CDATABLE" },
{ kCreditsStrings, kTypeRawData, "CREDITS" },
{ kMenuSKB, kTypeStringList, "MENUSKB" },
{ kSjisVTable, kTypeRawData, "SJISTABLE" },
// HAND OF FATE
// Sequence Player
{ k2SeqplayPakFiles, kTypeStringList, "S_PAKFILES.TXT" },
{ k2SeqplayCredits, kTypeRawData, "S_CREDITS.TXT" },
{ k2SeqplayStrings, kTypeLanguageList, "S_STRINGS" },
{ k2SeqplaySfxFiles, kTypeStringList, "S_SFXFILES.TXT" },
{ k2SeqplayTlkFiles, kTypeLanguageList, "S_TLKFILES" },
{ k2SeqplaySeqData, k2TypeSeqData, "S_DATA.SEQ" },
{ k2SeqplayIntroTracks, kTypeStringList, "S_INTRO.TRA" },
{ k2SeqplayFinaleTracks, kTypeStringList, "S_FINALE.TRA" },
{ k2SeqplayIntroCDA, kTypeRawData, "S_INTRO.CDA" },
{ k2SeqplayFinaleCDA, kTypeRawData, "S_FINALE.CDA" },
// Ingame
{ k2IngamePakFiles, kTypeStringList, "I_PAKFILES.TXT" },
{ k2IngameTracks, kTypeStringList, "I_TRACKS.TRA" },
{ k2IngameCDA, kTypeRawData, "I_TRACKS.CDA" },
{ -1, 0, 0 }
};
@ -207,12 +243,15 @@ bool getFilename(char *dstFilename, const Game *g, const int id) {
return false;
const ExtractType *type = findExtractType(i->type);
type->createFilename(dstFilename, g->lang, g->special, i->filename);
type->createFilename(dstFilename, g->game, g->lang, g->special, i->filename);
return true;
}
void createFilename(char *dstFilename, const int lang, const int special, const char *filename) {
void createFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename) {
strcpy(dstFilename, filename);
static const char *gidExtensions[] = { "", ".K2", ".K3" };
strcat(dstFilename, gidExtensions[gid]);
for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
if (specialE->special == special) {
@ -223,9 +262,9 @@ void createFilename(char *dstFilename, const int lang, const int special, const
}
}
void createLangFilename(char *dstFilename, const int lang, const int special, const char *filename) {
void createLangFilename(char *dstFilename, const int gid, 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, ".");
@ -233,6 +272,9 @@ void createLangFilename(char *dstFilename, const int lang, const int special, co
break;
}
}
static const char *gidExtensions[] = { "", ".K2", ".K3" };
strcat(dstFilename, gidExtensions[gid]);
for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
if (specialE->special == special) {
@ -328,7 +370,9 @@ bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32
++entries;
}
if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
g->special == k2TownsFile2E || g->special == k2TownsFile2J) {
// prevents creation of empty entries (which we have mostly between all strings in the fm-towns version)
while (!data[++i]) {
if (i == size)
@ -364,9 +408,18 @@ bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32
if (g->special == kFMTownsVersionE)
targetsize--;
if (g->special == kFMTownsVersionJ)
targetsize += 2;
targetsize += 2;
entries += (g->special - 1);
}
if (fmtPatch == 3) {
entries++;
targetsize++;
}
if (fmtPatch == 4) {
targetsize -= 9;
}
uint8 *buffer = new uint8[targetsize];
assert(buffer);
@ -374,13 +427,16 @@ bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32
const uint8 *input = (const uint8*) data;
WRITE_BE_UINT32(output, entries); output += 4;
if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
g->special == k2TownsFile2E || g->special == k2TownsFile2J) {
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;
@ -394,6 +450,13 @@ bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32
*output++ = *input;
}
// insert one dummy string at hof sequence strings position 59
if (fmtPatch == 3) {
if ((g->special == k2TownsFile1E && input - data == 0x695) ||
(g->special == k2TownsFile1J && input - data == 0x598))
*output++ = *input;
}
if (++input == c)
break;
}
@ -424,7 +487,19 @@ bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32
}
targetsize = dstPos + 4;
} else {
memcpy(output, data, size);
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);
@ -474,6 +549,284 @@ bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 s
return out.addFile(filename, buffer, size + 1 * 4);
}
bool extractHofSeqData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
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, g, endOffs - ptr);
if (cycle == 0 && v == 1) {
if (g->special == k2FloppyFile1 && *ptr == 5) {
// patch for floppy version
// skips invalid ferb sequence
ptr += 54;
continue;
}
numSequences++;
uint16 relOffs = (uint16) (output - buffer);
WRITE_LE_UINT16(hdout, relOffs);
hdout++;
/*char cc[15];
cc[14] = 0;
if (ptr[2]) {
memcpy(cc, ptr + 2, 14);
debug(1, "adding sequence with file: %s, output file offset: 0x%x", cc, relOffs);
} else if (ptr[16]) {
memcpy(cc, ptr + 16, 14);
debug(1, "adding sequence with file: %s, output file offset: 0x%x", cc, relOffs);
} else if (ptr[0] == 4) {
debug(1, "adding sequence (text only), output file offset: 0x%x", relOffs);
//}*/
memcpy(output , ptr, 30);
ptr += 30;
output += 30;
if (g->special == k2TownsFile1E) {
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;
}
memcpy(output, ptr, 14);
ptr += 18;
output += 14;
memcpy(output, ptr, 2);
ptr += 2;
output+= 2;
} else if (cycle == 1 && v != 1 && v != -2) {
uint16 controlOffs = 0;
if (v) {
const byte *ctrStart = ptr;
while (v && v != -2) {
ptr++;
v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
}
if (v == -2)
break;
uint16 ctrSize = (uint16)(ptr - ctrStart);
if (g->special != k2DemoVersion &&
extractHofSeqData_isControl(ctrStart, ctrSize)) {
controlOffs = (uint16) (output - buffer);
//debug(1, "frame control encountered, size: %d, output file offset: 0x%x", ctrSize, controlOffs);
memcpy(output, ctrStart, ctrSize);
output += ctrSize;
}
}
numNestedSequences++;
uint16 relOffs = (uint16) (output - buffer);
WRITE_LE_UINT16(hdout, relOffs);
hdout++;
/*char cc[15];
cc[14] = 0;
memcpy(cc, ptr + 2, 14);
debug(1, "adding nested sequence with file: %s, output file offset: 0x%x", cc, relOffs);*/
memcpy(output , ptr, 22);
ptr += 26;
output += 22;
memcpy(output, ptr, 4);
ptr += 4;
output += 4;
if (!READ_LE_UINT32(ptr))
controlOffs = 0;
//else if (controlOffs)
// debug(1, "assigning frame control with output file offset 0x%x to item %s (output file offset: 0x%x)", controlOffs, cc, relOffs);
WRITE_LE_UINT16(output, controlOffs);
if (g->special != k2DemoVersion)
ptr += 4;
output += 2;
if (g->special != k2DemoVersion) {
memcpy(output, ptr, 4);
ptr += 4;
} else {
WRITE_LE_UINT32(output, 0);
}
output+= 4;
if (g->special == k2TownsFile1E)
ptr += 2;
} else if (cycle == 0) {
while (v != 1 && v != -2) {
ptr++;
v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
}
if (v == -2)
break;
/*char cc[15];
cc[14] = 0;
if (ptr[2])
memcpy(cc, ptr + 2, 14);
else
memcpy(cc, ptr + 16, 14);
debug(1, "next item: sequence with file %s", cc);*/
} else if (cycle == 1) {
while (v == 1 && v != -2) {
ptr++;
v = extractHofSeqData_isSequence(ptr, g, 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_LE_UINT16(&finHeader[i], (READ_LE_UINT16(&header[i]) - diff));
WRITE_LE_UINT16(finHeader, numSequences);
WRITE_LE_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_LE_UINT16(finHeader++) + 26;
uint16 ctrl = READ_LE_UINT16(offs);
if (ctrl)
ctrl -= diff;
WRITE_LE_UINT16(offs, ctrl);
}
//debug(1, "\n\nFinished.\n");
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 Game *g, 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 (g->special == k2TownsFile1E) {
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 (uint i = 2; i < size; i += 4) {
if (!s[i])
return 0;
}
for (uint i = 1; i < size; i += 2) {
if (s[i])
return 0;
}
return 1;
}
// index generation
enum {
@ -495,11 +848,13 @@ enum {
uint32 getFeatures(const Game *g) {
uint32 features = 0;
if (g->special == kTalkieVersion)
if (g->special == kTalkieVersion || g->special == k2CDFile1E || g->special == k2CDFile1F || g->special == k2CDFile1G || g->special == k2CDFile2E || g->special == k2CDFile2F || g->special == k2CDFile2G)
features |= GF_TALKIE;
else if (g->special == kDemoVersion)
else if (g->special == kDemoVersion || g->special == k2DemoVersion)
features |= GF_DEMO;
else if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ)
else if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
g->special == k2TownsFile2E || g->special == k2TownsFile2J)
features |= GF_FMTOWNS;
else if (g->special == kAmigaVersion)
features |= GF_AMIGA;
@ -544,7 +899,7 @@ bool checkIndex(const byte *s, const int srcSize) {
bool updateIndex(PAKFile &out, const Game *g) {
char filename[32];
createFilename(filename, -1, g->special, "INDEX");
createFilename(filename, g->game, -1, g->special, "INDEX");
byte *index = new byte[kIndexSize];
assert(index);
@ -572,7 +927,7 @@ bool updateIndex(PAKFile &out, const Game *g) {
bool checkIndex(PAKFile &out, const Game *g) {
char filename[32];
createFilename(filename, -1, g->special, "INDEX");
createFilename(filename, g->game, -1, g->special, "INDEX");
uint32 size = 0;
const uint8 *data = out.getFileData(filename, &size);
@ -639,9 +994,23 @@ 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 (g->special == kFMTownsVersionE || g->special == k2TownsFile1E || g->special == k2TownsFile2E ||
g->special == k2CDFile1E || g->special == k2CDFile2E) {
// This is for executables which contain support for at least 2 languages
// The English and non language specific data has now been extracted.
// We switch to the second language and continue extraction.
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]);
}
if (g->special == k2CDFile1F || g->special == k2CDFile2F) {
// This is for executables which contain support for 3 languages.
// We switch to the third language and continue extraction.
if (!hasNeededEntries(++g, &out)) {
warning("file '%s' is missing offset entries and thus can't be processed", argv[i]);
delete [] buffer;
@ -708,9 +1077,19 @@ bool process(PAKFile &out, const Game *g, const byte *data, const uint32 size) {
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)
else if (i->id == kIntroStrings || i->id == kKyra1TownsSFXwdTable)
patch = 2;
}
if (g->special == k2TownsFile1E || g->special == k2TownsFile1J) {
if (i->id == k2SeqplayStrings)
patch = 3;
}
if (g->special == k2FloppyFile2) {
if (i->id == k2IngamePakFiles)
patch = 4;
}
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);
@ -736,6 +1115,12 @@ const Game *gameDescs[] = {
kyra1TownsGames,
kyra1AmigaGames,
kyra1FanTranslations,
kyra2FloppyGames,
kyra2TalkieGames,
kyra2TownsGames,
kyra2Demos,
0
};

View File

@ -59,6 +59,9 @@ enum kExtractID {
kRoomList,
kCharacterImageFilenames,
kAudioTracks,
kAudioTracksIntro,
kItemNames,
kTakenStrings,
@ -133,10 +136,25 @@ enum kExtractID {
kGUIStrings,
kConfigStrings,
kKyra1TownsSFXTable,
kKyra1TownsSFXwdTable,
kKyra1TownsSFXbtTable,
kKyra1TownsCDATable,
kCreditsStrings,
kSjisVTable,
kMenuSKB,
k2SeqplayPakFiles,
k2SeqplayStrings,
k2SeqplaySfxFiles,
k2SeqplayTlkFiles,
k2SeqplaySeqData,
k2SeqplayCredits,
k2SeqplayIntroTracks,
k2SeqplayFinaleTracks,
k2SeqplayIntroCDA,
k2SeqplayFinaleCDA,
k2IngamePakFiles,
k2IngameTracks,
k2IngameCDA,
kMaxResIDs
};
@ -158,7 +176,24 @@ enum kSpecial {
kDemoVersion = 1,
kFMTownsVersionE = 2,
kFMTownsVersionJ = 3,
kAmigaVersion = 4
kAmigaVersion = 4,
k2CDFile1E = 5,
k2CDFile1F = 6,
k2CDFile1G = 7,
k2CDFile2E = 8,
k2CDFile2F = 9,
k2CDFile2G = 10,
k2TownsFile1E = 11,
k2TownsFile1J = 12,
k2TownsFile2E = 13,
k2TownsFile2J = 14,
k2FloppyFile1 = 15,
k2FloppyFile2 = 16,
k2DemoVersion = 17
};
struct SpecialExtension {
@ -195,13 +230,15 @@ enum kExtractType {
kTypeStringList,
kTypeRoomList,
kTypeShapeList,
kTypeRawData
kTypeRawData,
k2TypeSeqData
};
struct ExtractType {
int type;
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);
void (*createFilename)(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
};
#endif

View File

@ -80,6 +80,9 @@ const ExtractEntry kyra1EngFloppy[] = {
{ kGUIStrings, 0x0002EE7A, 0x0002F02A },
{ kNewGameString, 0x00032466, 0x0003247B },
{ kConfigStrings, 0x0002f870, 0x0002f8af },
{ kAudioTracks, 0x00032771, 0x000327B2 },
{ kAudioTracksIntro, 0x0002FC88, 0x0002FC8E },
{ -1, 0, 0 }
};
@ -165,6 +168,8 @@ const ExtractEntry kyra1EngCD[] = {
{ kGUIStrings, 0x0002F1EE, 0x0002F3F7 },
{ kNewGameString, 0x00032CFB, 0x00032D10 },
{ kConfigStrings, 0x0002fc3d, 0x0002fc9e },
{ kAudioTracks, 0x00033006, 0x00033047 },
{ kAudioTracksIntro, 0x0002FE9A, 0x0002FEA6 },
{ -1, 0, 0 }
};

View File

@ -0,0 +1,46 @@
const ExtractEntry kyra2File1CDE[] = {
{ k2SeqplayPakFiles, 0x00029FA4, 0x00029FEA },
{ k2SeqplayCredits, 0x00027920, 0x00028408 },
{ k2SeqplayStrings, 0x0002C566, 0x0002CE7C },
{ k2SeqplaySfxFiles, 0x0002E284, 0x0002E4B8 },
{ k2SeqplayTlkFiles, 0x0002A2AC, 0x0002A349 },
{ k2SeqplayIntroTracks, 0x0002E4C5, 0x0002E4CD },
{ k2SeqplayFinaleTracks, 0x0002E4DA, 0x0002E4E3 },
{ k2SeqplaySeqData, 0x0002BB4C, 0x0002C20A },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File1CDF[] = {
{ k2SeqplayStrings, 0x0002CE7C, 0x0002D845 },
{ k2SeqplayTlkFiles, 0x0002A349, 0x0002A3E6 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File1CDG[] = {
{ k2SeqplayStrings, 0x0002D845, 0x0002E284 },
{ k2SeqplayTlkFiles, 0x0002A3E6, 0x0002A483 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2CDE[] = {
{ k2IngameTracks, 0x0002F2FE, 0x0002F37E },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2CDF[] = {
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2CDG[] = {
{ -1, 0, 0 }
};
const Game kyra2TalkieGames[] = {
{ kKyra2, EN_ANY, k2CDFile1E, "85bbc1cc6c4cef6ad31fc6ee79518efb", kyra2File1CDE},
{ kKyra2, FR_FRA, k2CDFile1F, "85bbc1cc6c4cef6ad31fc6ee79518efb", kyra2File1CDF},
{ kKyra2, DE_DEU, k2CDFile1G, "85bbc1cc6c4cef6ad31fc6ee79518efb", kyra2File1CDG},
{ kKyra2, EN_ANY, k2CDFile2E, "e20d0d2e500f01e399ec588247a7e213", kyra2File2CDE},
{ kKyra2, FR_FRA, k2CDFile2F, "e20d0d2e500f01e399ec588247a7e213", kyra2File2CDF},
{ kKyra2, DE_DEU, k2CDFile2G, "e20d0d2e500f01e399ec588247a7e213", kyra2File2CDG},
GAME_DUMMY_ENTRY
};

View File

@ -0,0 +1,12 @@
const ExtractEntry kyra2Demo[] = {
{ k2SeqplayPakFiles, 0x0001C130, 0x0001C144 },
{ k2SeqplaySfxFiles, 0x0001CDDE, 0x0001CEBC },
{ k2SeqplaySeqData, 0x0001C920, 0x0001CB9C },
{ k2SeqplayIntroTracks, 0x0001CEBC, 0x0001CECC },
{ -1, 0, 0 }
};
const Game kyra2Demos[] = {
{ kKyra2, EN_ANY, k2DemoVersion, "a620a37579dd44ab0403482285e3897f", kyra2Demo},
GAME_DUMMY_ENTRY
};

View File

@ -0,0 +1,58 @@
const ExtractEntry kyra2File1E[] = {
{ k2SeqplayPakFiles, 0x0002132A, 0x0002134C },
{ k2SeqplayStrings, 0x00022DF2, 0x000236BA },
{ k2SeqplaySfxFiles, 0x000236BA, 0x0002382D },
{ k2SeqplayIntroTracks, 0x0002383A, 0x0002384A },
{ k2SeqplayFinaleTracks, 0x00023857, 0x00023869 },
{ k2SeqplaySeqData, 0x000223E0, 0x00022AD4 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File1F[] = {
{ k2SeqplayPakFiles, 0x00020F9D, 0x00020FBF },
{ k2SeqplayStrings, 0x00022A9C, 0x00023431 },
{ k2SeqplaySfxFiles, 0x00023431, 0x000235A4 },
{ k2SeqplayIntroTracks, 0x000235B1, 0x000235C1 },
{ k2SeqplayFinaleTracks, 0x000235CE, 0x000235E0 },
{ k2SeqplaySeqData, 0x000223E0, 0x0002277E },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File1G[] = {
{ k2SeqplayPakFiles, 0x000211F9, 0x0002121B },
{ k2SeqplayStrings, 0x00022D30, 0x0002371C },
{ k2SeqplaySfxFiles, 0x0002371C, 0x0002388F },
{ k2SeqplayIntroTracks, 0x0002389C, 0x000238AC },
{ k2SeqplayFinaleTracks, 0x000238B9, 0x000238CB },
{ k2SeqplaySeqData, 0x0002231E, 0x00022A12 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2E[] = {
{ k2IngamePakFiles, 0x0035E4E, 0x00362ED },
{ k2IngameTracks, 0x0003B2F2, 0x0003B370 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2F[] = {
{ k2IngamePakFiles, 0x0003AA9C, 0x0003AB1A },
{ k2IngameTracks, 0x0003B2F2, 0x0003B370 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2G[] = {
{ k2IngamePakFiles, 0x0035626, 0x0035AC5 },
{ k2IngameTracks, 0x0003AA8C, 0x0003AB0A },
{ -1, 0, 0 }
};
const Game kyra2FloppyGames[] = {
{ kKyra2, EN_ANY, k2FloppyFile1, "9b0f5e57b5a2ed88b5b989cbb402b6c7", kyra2File1E},
{ kKyra2, FR_FRA, k2FloppyFile1, "df31cc9e37e1cf68df2fdc75ddf2d87b", kyra2File1F},
{ kKyra2, DE_DEU, k2FloppyFile1, "0ca4f9a1438264a4c63c3218e064ed3b", kyra2File1G},
{ kKyra2, EN_ANY, k2FloppyFile2, "7c3eadbe5122722cf2e5e1611e19dfb9", kyra2File2E},
{ kKyra2, FR_FRA, k2FloppyFile2, "fc2c6782778e6c6d5a553d1cb73c98ad", kyra2File2F},
{ kKyra2, DE_DEU, k2FloppyFile2, "0d9b0eb7b0ad889ec942d74d80dde1bf", kyra2File2G},
GAME_DUMMY_ENTRY
};

View File

@ -0,0 +1,32 @@
const ExtractEntry kyra2File1FMTownsE[] = {
{ k2SeqplayPakFiles, 0x00000540, 0x00000573 },
{ k2SeqplayStrings, 0x00001614, 0x00001FA4 },
{ k2SeqplaySfxFiles, 0x0000284C, 0x000029EF },
{ k2SeqplaySeqData, 0x000050D8, 0x00005794 },
{ k2SeqplayIntroCDA, 0x00007FF8, 0x00008010 },
{ k2SeqplayFinaleCDA, 0x00008010, 0x00008018 },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File1FMTownsJ[] = {
{ k2SeqplayStrings, 0x00001FA4, 0x0000284C },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2FMTownsE[] = {
{ k2IngamePakFiles, 0x00000540, 0x0000065C },
{ k2IngameCDA, 0x0001808C, 0x000181BC },
{ -1, 0, 0 }
};
const ExtractEntry kyra2File2FMTownsJ[] = {
{ -1, 0, 0 }
};
const Game kyra2TownsGames[] = {
{ kKyra2, EN_ANY, k2TownsFile1E, "74f50d79c919cc8e7196c24942ce43d7", kyra2File1FMTownsE},
{ kKyra2, JA_JPN, k2TownsFile1J, "74f50d79c919cc8e7196c24942ce43d7", kyra2File1FMTownsJ},
{ kKyra2, EN_ANY, k2TownsFile2E, "a9a7fd4f05d00090e9e8bda073e6d431", kyra2File2FMTownsE},
{ kKyra2, JA_JPN, k2TownsFile2J, "a9a7fd4f05d00090e9e8bda073e6d431", kyra2File2FMTownsJ},
GAME_DUMMY_ENTRY
};

View File

@ -80,6 +80,8 @@ const int kyra1FloppyNeed[] = {
kGUIStrings,
kNewGameString,
kConfigStrings,
kAudioTracks,
kAudioTracksIntro,
-1
};
@ -165,6 +167,8 @@ const int kyra1CDNeed[] = {
kGUIStrings,
kNewGameString,
kConfigStrings,
kAudioTracks,
kAudioTracksIntro,
-1
};
@ -265,10 +269,11 @@ const int kyra1TownsEngNeed[] = {
kNewGameString,
kConfigStrings,
kKyra1TownsSFXTable,
kKyra1TownsSFXwdTable,
kKyra1TownsSFXbtTable,
kKyra1TownsCDATable,
kAudioTracks,
kCreditsStrings,
kMenuSKB,
kSjisVTable,
-1
};
@ -351,6 +356,89 @@ const int kyra1AmigaNeed[] = {
-1
};
const int kyra2CDFile1EngNeed[] = {
k2SeqplayPakFiles,
k2SeqplayCredits,
k2SeqplayStrings,
k2SeqplaySfxFiles,
k2SeqplaySeqData,
k2SeqplayIntroTracks,
k2SeqplayFinaleTracks,
-1
};
const int kyra2CDFile1FreNeed[] = {
k2SeqplayStrings,
-1
};
const int kyra2CDFile1GerNeed[] = {
k2SeqplayStrings,
-1
};
const int kyra2CDFile2EngNeed[] = {
k2IngameTracks,
-1
};
const int kyra2CDFile2FreNeed[] = {
-1
};
const int kyra2CDFile2GerNeed[] = {
-1
};
const int kyra2FloppyFile1Need[] = {
k2SeqplayPakFiles,
k2SeqplayStrings,
k2SeqplaySfxFiles,
k2SeqplayIntroTracks,
k2SeqplayFinaleTracks,
k2SeqplaySeqData,
-1
};
const int kyra2FloppyFile2Need[] = {
k2IngamePakFiles,
k2IngameTracks,
-1
};
const int kyra2TownsFile1EngNeed[] = {
k2SeqplayPakFiles,
k2SeqplayStrings,
k2SeqplaySfxFiles,
k2SeqplaySeqData,
k2SeqplayIntroCDA,
k2SeqplayFinaleCDA,
-1
};
const int kyra2TownsFile1JapNeed[] = {
k2SeqplayStrings,
-1
};
const int kyra2TownsFile2EngNeed[] = {
k2IngamePakFiles,
k2IngameCDA,
-1
};
const int kyra2TownsFile2JapNeed[] = {
-1
};
const int kyra2DemoNeed[] = {
k2SeqplayPakFiles,
k2SeqplaySeqData,
k2SeqplaySfxFiles,
k2SeqplayIntroTracks,
-1
};
const GameNeed gameNeedTable[] = {
{ kKyra1, -1, kyra1FloppyNeed },
{ kKyra1, kTalkieVersion, kyra1CDNeed },
@ -358,6 +446,21 @@ const GameNeed gameNeedTable[] = {
{ kKyra1, kFMTownsVersionJ, kyra1TownsJapNeed },
{ kKyra1, kAmigaVersion, kyra1AmigaNeed },
{ kKyra1, kDemoVersion, kyra1DemoNeed },
{ kKyra2, k2FloppyFile1, kyra2FloppyFile1Need },
{ kKyra2, k2FloppyFile2, kyra2FloppyFile2Need },
{ kKyra2, k2CDFile1E, kyra2CDFile1EngNeed },
{ kKyra2, k2CDFile1F, kyra2CDFile1FreNeed },
{ kKyra2, k2CDFile1G, kyra2CDFile1GerNeed },
{ kKyra2, k2CDFile2E, kyra2CDFile2EngNeed },
{ kKyra2, k2CDFile2F, kyra2CDFile2FreNeed },
{ kKyra2, k2CDFile2G, kyra2CDFile2GerNeed },
{ kKyra2, k2TownsFile1E , kyra2TownsFile1EngNeed },
{ kKyra2, k2TownsFile1J, kyra2TownsFile1JapNeed },
{ kKyra2, k2TownsFile2E , kyra2TownsFile2EngNeed },
{ kKyra2, k2TownsFile2J, kyra2TownsFile2JapNeed },
{ kKyra2, k2DemoVersion, kyra2DemoNeed},
{ -1, -1, 0 }
};
@ -367,6 +470,19 @@ const SpecialExtension specialTable[] = {
{ kFMTownsVersionE , "TNS" },
{ kFMTownsVersionJ, "TNS" },
{ kAmigaVersion, "AMG" },
{ k2CDFile1E, "CD" },
{ k2CDFile1F, "CD" },
{ k2CDFile1G, "CD" },
{ k2CDFile2E, "CD" },
{ k2CDFile2F, "CD" },
{ k2CDFile2G, "CD" },
{ k2TownsFile1E, "TNS" },
{ k2TownsFile1J, "TNS" },
{ k2TownsFile2E, "TNS" },
{ k2TownsFile2J, "TNS" },
{ k2DemoVersion, "DEM" },
{ -1, 0 }
};
@ -379,4 +495,3 @@ const Language languageTable[] = {
{ JA_JPN, "JPN" },
{ -1, 0 }
};

View File

@ -80,10 +80,11 @@ const ExtractEntry kyra1FMTownsE[] = {
{ kGUIStrings, 0x000291E0, 0x000293DC },
{ kNewGameString, 0x0002919C, 0x000291B1 },
{ kConfigStrings, 0x00029360, 0x000293AA},
{ kKyra1TownsSFXTable, 0x0003A978, 0x0004CF80 },
{ kKyra1TownsSFXwdTable, 0x0003A978, 0x0004CF80 },
{ kKyra1TownsSFXbtTable, 0x0003A878, 0x0003A978 },
{ kKyra1TownsCDATable, 0x0004D021, 0x0004D2E5 },
{ kAudioTracks, 0x00027B8E, 0x00027BEB },
{ kCreditsStrings, 0x0002AED8, 0x0002B464 },
{ kMenuSKB, 0x000293DE, 0x000294A7 },
{ kSjisVTable, 0x0003A421, 0x0003A749 },
{ -1, 0, 0 }
};