Ticket #8772: createKyraDat.patch

File createKyraDat.patch, 25.2 KB (added by athrxx, 13 years ago)

patch for the kyradat tool

  • create_kyradat.cpp

     
    3131#include "md5.h"
    3232
    3333enum {
    34         kKyraDatVersion = 17,
     34        kKyraDatVersion = 18,
    3535        kIndexSize = 12
    3636};
    3737
     
    4545#include "towns.h"
    4646#include "amiga.h"
    4747
     48#include "hof_floppy.h"
     49#include "hof_towns.h"
     50#include "hof_cd.h"
     51#include "hof_demo.h"
     52
    4853const Game kyra1FanTranslations[] = {
    4954        { kKyra1, IT_ITA, kTalkieVersion, "d0f1752098236083d81b9497bd2b6989", kyra1FreCD },
    5055        GAME_DUMMY_ENTRY
     
    5459bool extractStrings(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
    5560bool extractRooms(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
    5661bool extractShapes(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
     62bool extractHofSeqData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch = 0);
     63int extractHofSeqData_checkString(void * ptr, uint8 checkSize);
     64int extractHofSeqData_isSequence(void * ptr, const Game *g, uint32 maxCheckSize);
     65int extractHofSeqData_isControl(void * ptr, uint32 size);
    5766
    58 void createFilename(char *dstFilename, const int lang, const int special, const char *filename);
    59 void createLangFilename(char *dstFilename, const int lang, const int special, const char *filename);
     67void createFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
     68void createLangFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
    6069
    6170const ExtractType extractTypeTable[] = {
    6271        { kTypeLanguageList, extractStrings, createLangFilename },
     
    6473        { kTypeRoomList, extractRooms, createFilename },
    6574        { kTypeShapeList, extractShapes, createFilename },
    6675        { kTypeRawData, extractRaw, createFilename },
     76
     77        { k2TypeSeqData, extractHofSeqData, createFilename },
     78
    6779        { -1, 0, 0}
    6880};
    6981
     
    133145        // IMAGE filename table
    134146        { kCharacterImageFilenames, kTypeStringList, "CHAR-IMAGE.TXT" },
    135147
     148        // AUDIO filename table
     149        { kAudioTracks, kTypeStringList, "TRACKS.TXT" },
     150        { kAudioTracksIntro, kTypeStringList, "TRACKSINT.TXT" },
     151
    136152        // AMULET anim
    137153        { kAmuleteAnimSeq, kTypeRawData, "AMULETEANIM.SEQ" },
    138154
     
    172188        { kPaletteList33, kTypeRawData, "PALTABLE33.PAL" },
    173189       
    174190        // FM-TOWNS specific
    175         { kKyra1TownsSFXTable, kTypeRawData, "SFXTABLE" },
     191        { kKyra1TownsSFXwdTable, kTypeRawData, "SFXWDTABLE" },
     192        { kKyra1TownsSFXbtTable, kTypeRawData, "SFXBTTABLE" },
     193        { kKyra1TownsCDATable, kTypeRawData, "CDATABLE" },
    176194        { kCreditsStrings, kTypeRawData, "CREDITS" },
    177         { kMenuSKB, kTypeStringList, "MENUSKB" },
    178         { kSjisVTable, kTypeRawData, "SJISTABLE" },
    179195
     196
     197        // HAND OF FATE
     198
     199        // Sequence Player
     200        { k2SeqplayPakFiles, kTypeStringList, "S_PAKFILES.TXT" },
     201        { k2SeqplayCredits, kTypeRawData, "S_CREDITS.TXT" },
     202        { k2SeqplayStrings, kTypeLanguageList, "S_STRINGS" },
     203        { k2SeqplaySfxFiles, kTypeStringList, "S_SFXFILES.TXT" },
     204        { k2SeqplayTlkFiles, kTypeLanguageList, "S_TLKFILES" },
     205        { k2SeqplaySeqData, k2TypeSeqData, "S_DATA.SEQ" },
     206        { k2SeqplayIntroTracks, kTypeStringList, "S_INTRO.TRA" },
     207        { k2SeqplayFinaleTracks, kTypeStringList, "S_FINALE.TRA" },     
     208        { k2SeqplayIntroCDA, kTypeRawData, "S_INTRO.CDA" },
     209        { k2SeqplayFinaleCDA, kTypeRawData, "S_FINALE.CDA" },
     210
     211        // Ingame
     212        { k2IngamePakFiles, kTypeStringList, "I_PAKFILES.TXT" },
     213        { k2IngameTracks, kTypeStringList, "I_TRACKS.TRA" },
     214        { k2IngameCDA, kTypeRawData, "I_TRACKS.CDA" },
     215
    180216        { -1, 0, 0 }
    181217};
    182218
     
    207243                return false;
    208244
    209245        const ExtractType *type = findExtractType(i->type);
    210         type->createFilename(dstFilename, g->lang, g->special, i->filename);
     246        type->createFilename(dstFilename, g->game, g->lang, g->special, i->filename);
    211247        return true;
    212248}
    213249
    214 void createFilename(char *dstFilename, const int lang, const int special, const char *filename) {
     250void createFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename) {
    215251        strcpy(dstFilename, filename);
     252
     253        static const char *gidExtensions[] = { "", ".K2", ".K3", ".LOL" };     
     254        strcat(dstFilename, gidExtensions[gid]);
    216255       
    217256        for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
    218257                if (specialE->special == special) {
     
    223262        }
    224263}
    225264
    226 void createLangFilename(char *dstFilename, const int lang, const int special, const char *filename) {
     265void createLangFilename(char *dstFilename, const int gid, const int lang, const int special, const char *filename) {
    227266        strcpy(dstFilename, filename);
    228        
     267
    229268        for (const Language *langE = languageTable; langE->lang != -1; ++langE) {
    230269                if (langE->lang == lang) {
    231270                        strcat(dstFilename, ".");
     
    233272                        break;
    234273                }
    235274        }
     275
     276        static const char *gidExtensions[] = { "", ".K2", ".K3", ".LOL" };     
     277        strcat(dstFilename, gidExtensions[gid]);
    236278       
    237279        for (const SpecialExtension *specialE = specialTable; specialE->special != -1; ++specialE) {
    238280                if (specialE->special == special) {
     
    328370                                ++entries;
    329371                        }
    330372
    331                         if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
     373                        if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
     374                                g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
     375                                g->special == k2TownsFile2E || g->special == k2TownsFile2J) {
    332376                                // prevents creation of empty entries (which we have mostly between all strings in the fm-towns version)
    333377                                while (!data[++i]) {
    334378                                        if (i == size)
     
    364408                if (g->special == kFMTownsVersionE)
    365409                        targetsize--;
    366410                if (g->special == kFMTownsVersionJ)
    367                         targetsize += 2;               
     411                        targetsize += 2;
    368412                entries += (g->special - 1);
    369413        }
     414
     415        if (fmtPatch == 3) {
     416                entries++;
     417                targetsize++;
     418        }
     419
     420        if (fmtPatch == 4) {
     421                targetsize -= 9;
     422        }
    370423       
    371424        uint8 *buffer = new uint8[targetsize];
    372425        assert(buffer);
     
    374427        const uint8 *input = (const uint8*) data;
    375428
    376429        WRITE_BE_UINT32(output, entries); output += 4;
    377         if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ) {
     430        if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
     431                g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
     432                g->special == k2TownsFile2E || g->special == k2TownsFile2J) {
    378433                const byte * c = data + size;
    379434                do {
    380435                        if (fmtPatch == 2 && input - data == 0x3C0 && input[0x10] == 0x32) {
    381436                                memcpy(output, input, 0x0F);
    382437                                input += 0x11; output += 0x0F;
    383438                        }
     439
    384440                        strcpy((char*) output, (const char*) input);
    385441                        uint32 stringsize = strlen((const char*)output) + 1;
    386442                        input += stringsize; output += stringsize;
     
    394450                                                        *output++ = *input;
    395451                                }
    396452
     453                                // insert one dummy string at hof sequence strings position 59
     454                                if (fmtPatch == 3) {
     455                                        if ((g->special == k2TownsFile1E && input - data == 0x695) ||
     456                                                (g->special == k2TownsFile1J && input - data == 0x598))
     457                                                        *output++ = *input;
     458                                }
     459
    397460                                if (++input == c)
    398461                                        break;
    399462                        }
     
    424487                }
    425488                targetsize = dstPos + 4;
    426489        } else {
    427                 memcpy(output, data, size);
     490                uint32 copySize = size;
     491                if (fmtPatch == 4) {
     492                        memcpy(output, data, 44);
     493                        output += 44;
     494                        data += 44;
     495                        for (int t = 1; t != 10; t++) {
     496                                sprintf((char*) output, "COST%d_SH.PAK", t);
     497                                output += 13;
     498                        }
     499                        data += 126;
     500                        copySize -= 170;
     501                }
     502                memcpy(output, data, copySize);
    428503        }
    429504
    430505        return out.addFile(filename, buffer, targetsize);
     
    474549        return out.addFile(filename, buffer, size + 1 * 4);
    475550}
    476551
     552bool extractHofSeqData(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch) {
     553        int numSequences = 0;
     554        int numNestedSequences = 0;
     555
     556        uint16 headerSize = 50 * sizeof(uint16);
     557        uint16 bufferSize = size + headerSize;
     558        byte *buffer = new byte[bufferSize];
     559        assert(buffer);
     560        memset(buffer, 0, bufferSize );
     561        uint16 *header = (uint16*) buffer;
     562        byte *output = buffer + headerSize;
     563        uint16 *hdout = header;
     564
     565        //debug(1, "\nProcessing Hand of Fate sequence data:\n--------------------------------------\n");
     566        for (int cycle = 0; cycle < 2; cycle++) {
     567                byte * ptr = (byte*) data;
     568                hdout++;
     569
     570                const byte * endOffs = (const byte *) (data + size);
     571
     572                // detect sequence structs
     573                while (ptr < endOffs) {
     574                        if (ptr[1]) {
     575                                error("invalid sequence data encountered");
     576                                delete [] buffer;
     577                                return false;
     578                        }
     579
     580                        int v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
     581
     582                        if (cycle == 0 && v == 1) {
     583                                if (g->special == k2FloppyFile1 && *ptr == 5) {
     584                                        // patch for floppy version
     585                                        // skips invalid ferb sequence
     586                                        ptr += 54;
     587                                        continue;
     588                                }
     589
     590                                numSequences++;
     591                                uint16 relOffs = (uint16) (output - buffer);
     592                                WRITE_LE_UINT16(hdout, relOffs);
     593                                hdout++;
     594
     595                                /*char cc[15];
     596                                cc[14] = 0;
     597                                if (ptr[2]) {
     598                                        memcpy(cc, ptr + 2, 14);
     599                                        debug(1, "adding sequence with file: %s, output file offset: 0x%x", cc, relOffs);
     600                                } else if (ptr[16]) {
     601                                        memcpy(cc, ptr + 16, 14);
     602                                        debug(1, "adding sequence with file: %s, output file offset: 0x%x", cc, relOffs);
     603                                } else if (ptr[0] == 4) {
     604                                        debug(1, "adding sequence (text only), output file offset: 0x%x", relOffs);
     605                                //}*/
     606
     607                                memcpy(output , ptr, 30);
     608                                ptr += 30;
     609                                output += 30;
     610                               
     611                                if (g->special == k2TownsFile1E) {
     612                                        memcpy(output , ptr, 2);
     613                                        ptr += 2;
     614                                        output += 2;
     615                                } else {
     616                                        *output++ = READ_LE_UINT16(ptr) & 0xff;
     617                                        ptr += 2;
     618                                        *output++ = READ_LE_UINT16(ptr) & 0xff;
     619                                        ptr += 2;
     620                                }                                               
     621
     622                                memcpy(output, ptr, 14);
     623                                ptr += 18;
     624                                output += 14;
     625                                memcpy(output, ptr, 2);
     626                                ptr += 2;
     627                                output+= 2;
     628
     629                        } else if (cycle == 1 && v != 1 && v != -2) {
     630                                uint16 controlOffs = 0;
     631                                if (v) {
     632                                        byte * ctrStart = ptr;
     633                                        while (v && v != -2) {
     634                                                ptr++;
     635                                                v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
     636                                        }
     637
     638                                        if (v == -2)
     639                                                break;
     640
     641                                        uint16 ctrSize = (uint16) (ptr - ctrStart);
     642
     643                                        if (g->special != k2DemoVersion && g->special != k2DemoLol &&
     644                                                extractHofSeqData_isControl(ctrStart, ctrSize)) {
     645
     646                                                controlOffs = (uint16) (output - buffer);
     647                                                //debug(1, "frame control encountered, size: %d, output file offset: 0x%x", ctrSize, controlOffs);
     648                                                memcpy(output, ctrStart, ctrSize);
     649                                                output += ctrSize;
     650                                        }
     651                                }                               
     652
     653                                numNestedSequences++;
     654                                uint16 relOffs = (uint16) (output - buffer);
     655                                WRITE_LE_UINT16(hdout, relOffs);
     656                                hdout++;
     657
     658                                /*char cc[15];
     659                                cc[14] = 0;
     660                                memcpy(cc, ptr + 2, 14);
     661                                debug(1, "adding nested sequence with file: %s, output file offset: 0x%x", cc, relOffs);*/
     662
     663                                memcpy(output , ptr, 22);
     664                                ptr += 26;
     665                                output += 22;
     666                                memcpy(output, ptr, 4);
     667                                ptr += 4;
     668                                output += 4;
     669
     670                                if (!READ_LE_UINT32(ptr))
     671                                        controlOffs = 0;
     672                                //else if (controlOffs)
     673                                //      debug(1, "assigning frame control with output file offset 0x%x to item %s (output file offset: 0x%x)", controlOffs, cc, relOffs);
     674                                       
     675                                WRITE_LE_UINT16(output, controlOffs);
     676                                if (g->special != k2DemoVersion && g->special != k2DemoLol)
     677                                        ptr += 4;
     678                                output += 2;
     679
     680                                if (g->special != k2DemoVersion && g->special != k2DemoLol) {
     681                                        memcpy(output, ptr, 4);
     682                                        ptr += 4;
     683                                } else {
     684                                        WRITE_LE_UINT32(output, 0);
     685                                }
     686
     687                                output+= 4;
     688                                if (g->special == k2TownsFile1E)
     689                                        ptr += 2;
     690
     691                        } else if (cycle == 0) {
     692                                while (v != 1 && v != -2) {
     693                                        ptr++;
     694                                        v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
     695                                }
     696
     697                                if (v == -2)
     698                                        break;
     699
     700                                /*char cc[15];
     701                                cc[14] = 0;
     702                                if (ptr[2])
     703                                        memcpy(cc, ptr + 2, 14);
     704                                else
     705                                        memcpy(cc, ptr + 16, 14);
     706                                debug(1, "next item: sequence with file %s", cc);*/
     707
     708                        } else if (cycle == 1) {
     709                                while (v == 1 && v != -2) {
     710                                        ptr++;
     711                                        v = extractHofSeqData_isSequence(ptr, g, endOffs - ptr);
     712                                }
     713
     714                                if (v == -2)
     715                                        break;
     716                        }
     717                }
     718        }
     719
     720        uint16 finHeaderSize = (2 + numSequences + numNestedSequences) * sizeof(uint16);
     721        uint16 finBufferSize = ((output - buffer) - headerSize) + finHeaderSize;
     722        byte *finBuffer = new byte[finBufferSize];
     723        assert(finBuffer);
     724        uint16 diff = headerSize - finHeaderSize;
     725        uint16 *finHeader = (uint16*) finBuffer;
     726       
     727        for (int i = 1; i < finHeaderSize; i++)
     728                WRITE_LE_UINT16(&finHeader[i], (READ_LE_UINT16(&header[i]) - diff));
     729        WRITE_LE_UINT16(finHeader, numSequences);
     730        WRITE_LE_UINT16(&finHeader[numSequences + 1], numNestedSequences);
     731        memcpy (finBuffer + finHeaderSize, buffer + headerSize, finBufferSize - finHeaderSize);
     732        delete [] buffer;
     733
     734        finHeader = (uint16*) (finBuffer + ((numSequences + 2) * sizeof(uint16)));
     735        for (int i = 0; i < numNestedSequences; i++) {
     736                uint8 * offs = finBuffer + READ_LE_UINT16(finHeader++) + 26;
     737                uint16 ctrl = READ_LE_UINT16(offs);
     738                if (ctrl)
     739                        ctrl -= diff;
     740                WRITE_LE_UINT16(offs, ctrl);
     741        }
     742
     743
     744        //debug(1, "\n\nFinished.\n");
     745
     746        return out.addFile(filename, finBuffer, finBufferSize);
     747}
     748
     749int extractHofSeqData_checkString(void * ptr, uint8 checkSize) {
     750        // return values: 1 = text; 0 = zero string; -1 = other
     751
     752        int t = 0;
     753        int c = checkSize;
     754        uint8 * s = (uint8*) ptr;
     755
     756        // check for character string
     757        while (c--) {
     758                if (*s > 31 && *s < 123)
     759                        t++;
     760                s++;                   
     761        }
     762
     763        if (t == checkSize)
     764                return 1;
     765
     766        // check for zero string
     767        c = checkSize;
     768        uint32 sum = 0;
     769        s = (uint8*) ptr;
     770        while (c--)
     771                sum += *s++;
     772
     773        return (sum) ? -1 : 0;
     774}
     775
     776int extractHofSeqData_isSequence(void * ptr, const Game *g, uint32 maxCheckSize) {
     777        // return values: 1 = Sequence; 0 = Nested Sequence; -1 = other; -2 = overflow
     778
     779        if (maxCheckSize < 30)
     780                return -2;
     781       
     782        uint8 * s = (uint8*) ptr;
     783        int c1 = extractHofSeqData_checkString(s + 2, 6);
     784        int c2 = extractHofSeqData_checkString(s + 16, 6);
     785        int c3 = extractHofSeqData_checkString(s + 2, 14);
     786        int c4 = extractHofSeqData_checkString(s + 16, 14);
     787        int c0 = s[1];
     788        int c5 = s[0];
     789
     790        if (c0 == 0 && c5 && ((c1 + c2) >= 1) && (!(c3 == 0 && c2 != 1)) && (!(c4 == 0 && c1 != 1))) {
     791                if (maxCheckSize < 41)
     792                        return -2;
     793
     794                if (g->special == k2TownsFile1E) {
     795                        if (!(s[37] | s[39]) && s[38] > s[36])
     796                                return 1;
     797                } else {
     798                        if (!(s[39] | s[41]) && s[40] > s[38])
     799                                return 1;
     800                }
     801        }
     802
     803        if (c0 == 0 && c5 == 4 && c3 == 0 && c4 == 0) {
     804                if (maxCheckSize >= 41 && READ_LE_UINT32(s + 34) && !(s[39] | s[41]) && s[40] > s[38])
     805                        return 1;
     806        }       
     807
     808        if (c0 == 0 && c5 && c1 == 1 && c4 == -1 && s[20])
     809                return 0;
     810       
     811        return -1;
     812}
     813
     814int extractHofSeqData_isControl(void * ptr, uint32 size) {
     815        // return values: 1 = possible frame control data; 0 = definitely not frame control data
     816
     817        uint8 * s = (uint8*) ptr;
     818        for (int i = 2; i < size; i += 4) {
     819                if (!s[i])
     820                        return 0;
     821        }
     822        for (int i = 1; i < size; i += 2) {
     823                if (s[i])
     824                        return 0;
     825        }
     826        return 1;
     827}
     828
    477829// index generation
    478830
    479831enum {
     
    495847uint32 getFeatures(const Game *g) {
    496848        uint32 features = 0;
    497849
    498         if (g->special == kTalkieVersion)
     850        if (g->special == kTalkieVersion || g->special == k2CDFile1E || g->special == k2CDFile1F || g->special == k2CDFile1G || g->special == k2CDFile2E || g->special == k2CDFile2F || g->special == k2CDFile2G)
    499851                features |= GF_TALKIE;
    500         else if (g->special == kDemoVersion)
     852        else if (g->special == kDemoVersion || g->special == k2DemoVersion || g->special == k2DemoLol)
    501853                features |= GF_DEMO;
    502         else if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ)
     854        else if (g->special == kFMTownsVersionE || g->special == kFMTownsVersionJ ||
     855                g->special == k2TownsFile1E || g->special == k2TownsFile1J ||
     856                g->special == k2TownsFile2E || g->special == k2TownsFile2J)
    503857                features |= GF_FMTOWNS;
    504858        else if (g->special == kAmigaVersion)
    505859                features |= GF_AMIGA;
     
    544898
    545899bool updateIndex(PAKFile &out, const Game *g) {
    546900        char filename[32];
    547         createFilename(filename, -1, g->special, "INDEX");
     901        createFilename(filename, g->game, -1, g->special, "INDEX");
    548902       
    549903        byte *index = new byte[kIndexSize];
    550904        assert(index);
     
    572926
    573927bool checkIndex(PAKFile &out, const Game *g) {
    574928        char filename[32];
    575         createFilename(filename, -1, g->special, "INDEX");
     929        createFilename(filename, g->game, -1, g->special, "INDEX");
    576930
    577931        uint32 size = 0;
    578932        const uint8 *data = out.getFileData(filename, &size);
     
    639993                if (!process(out, g, buffer, size))
    640994                        fprintf(stderr, "ERROR: couldn't process file '%s'", argv[i]);
    641995               
    642                 if (g->special == kFMTownsVersionE) {
    643                         // The English and non language specific data has now been extracted
    644                         // so we switch to Japanese and extract the rest
     996                if (g->special == kFMTownsVersionE || g->special == k2TownsFile1E || g->special == k2TownsFile2E ||
     997                        g->special == k2CDFile1E || g->special == k2CDFile2E) {
     998                        // This is for executables which contain support for at least 2 languages
     999                        // The English and non language specific data has now been extracted.
     1000                        // We switch to the second language and continue extraction.
    6451001                        if (!hasNeededEntries(++g, &out)) {
    6461002                                warning("file '%s' is missing offset entries and thus can't be processed", argv[i]);
    6471003                                delete [] buffer;
     
    6501006                        if (!process(out, g, buffer, size))
    6511007                                fprintf(stderr, "ERROR: couldn't process file '%s'", argv[i]);
    6521008                }
     1009
     1010                if (g->special == k2CDFile1F || g->special == k2CDFile2F) {
     1011                        // This is for executables which contain support for 3 languages.
     1012                        // We switch to the third language and continue extraction.
     1013                        if (!hasNeededEntries(++g, &out)) {
     1014                                warning("file '%s' is missing offset entries and thus can't be processed", argv[i]);
     1015                                delete [] buffer;
     1016                                continue;
     1017                        }
     1018                        if (!process(out, g, buffer, size))
     1019                                fprintf(stderr, "ERROR: couldn't process file '%s'", argv[i]);
     1020                }
    6531021               
    6541022                delete [] buffer;
    6551023        }
     
    7081076                        if (i->id == kTakenStrings || i->id == kNoDropStrings || i->id == kPoisonGoneString ||
    7091077                                i->id == kThePoisonStrings || i->id == kFluteStrings || i->id == kWispJewelStrings)
    7101078                                patch = 1;
    711                         else if (i->id == kIntroStrings || i->id == kKyra1TownsSFXTable)
     1079                        else if (i->id == kIntroStrings || i->id == kKyra1TownsSFXwdTable)
    7121080                                patch = 2;                                             
    7131081                }
     1082
     1083                if (g->special == k2TownsFile1E || g->special == k2TownsFile1J) {
     1084                        if (i->id == k2SeqplayStrings)
     1085                                patch = 3;
     1086                }
    7141087               
     1088                if (g->special == k2FloppyFile2) {
     1089                        if (i->id == k2IngamePakFiles)
     1090                                patch = 4;
     1091                }
     1092               
    7151093                if (!tDesc->extract(out, g, data + i->startOff, i->endOff - i->startOff, filename, patch)) {
    7161094                        fprintf(stderr, "ERROR: couldn't extract id %d\n", i->id);
    7171095                        return false;
     
    7361114        kyra1TownsGames,
    7371115        kyra1AmigaGames,
    7381116        kyra1FanTranslations,
     1117
     1118        kyra2FloppyGames,
     1119        kyra2TalkieGames,
     1120        kyra2TownsGames,
     1121        kyra2Demos,
     1122
    7391123        0
    7401124};
    7411125
  • create_kyradat.h

     
    5959        kRoomList,
    6060
    6161        kCharacterImageFilenames,
     62
     63        kAudioTracks,
     64        kAudioTracksIntro,
    6265       
    6366        kItemNames,
    6467        kTakenStrings,
     
    133136        kGUIStrings,
    134137        kConfigStrings,
    135138       
    136         kKyra1TownsSFXTable,
     139        kKyra1TownsSFXwdTable,
     140        kKyra1TownsSFXbtTable,
     141        kKyra1TownsCDATable,
    137142        kCreditsStrings,
    138         kSjisVTable,
    139         kMenuSKB,
     143
     144        k2SeqplayPakFiles,
     145        k2SeqplayStrings,
     146        k2SeqplaySfxFiles,
     147        k2SeqplayTlkFiles,
     148        k2SeqplaySeqData,
     149        k2SeqplayCredits,
     150        k2SeqplayIntroTracks,
     151        k2SeqplayFinaleTracks,
     152        k2SeqplayIntroCDA,
     153        k2SeqplayFinaleCDA,
     154
     155        k2IngamePakFiles,
     156        k2IngameTracks,
     157        k2IngameCDA,
    140158       
    141159        kMaxResIDs
    142160};
     
    158176        kDemoVersion = 1,
    159177        kFMTownsVersionE = 2,
    160178        kFMTownsVersionJ = 3,
    161         kAmigaVersion = 4
     179        kAmigaVersion = 4,
     180
     181        k2CDFile1E = 5,
     182        k2CDFile1F = 6,
     183        k2CDFile1G = 7,
     184        k2CDFile2E = 8,
     185        k2CDFile2F = 9,
     186        k2CDFile2G = 10,
     187
     188        k2TownsFile1E = 11,
     189        k2TownsFile1J = 12,
     190        k2TownsFile2E = 13,
     191        k2TownsFile2J = 14,
     192
     193        k2FloppyFile1 = 15,
     194        k2FloppyFile2 = 16,
     195
     196        k2DemoVersion = 17,
     197        k2DemoLol = 18
    162198};
    163199
    164200struct SpecialExtension {
     
    169205enum kGame {
    170206        kKyra1 = 0,
    171207        kKyra2,
    172         kKyra3
     208        kKyra3,
     209        kLol
    173210};
    174211
    175212struct Game {
     
    195232        kTypeStringList,
    196233        kTypeRoomList,
    197234        kTypeShapeList,
    198         kTypeRawData
     235        kTypeRawData,
     236
     237        k2TypeSeqData
    199238};
    200239
    201240struct ExtractType {
    202241        int type;
    203242        bool (*extract)(PAKFile &out, const Game *g, const byte *data, const uint32 size, const char *filename, int fmtPatch);
    204         void (*createFilename)(char *dstFilename, const int lang, const int special, const char *filename);
     243        void (*createFilename)(char *dstFilename, const int gid, const int lang, const int special, const char *filename);
    205244};
    206245
    207246#endif
  • eng.h

     
    8080        { kGUIStrings, 0x0002EE7A, 0x0002F02A },
    8181        { kNewGameString, 0x00032466, 0x0003247B },
    8282        { kConfigStrings, 0x0002f870, 0x0002f8af },
     83        { kAudioTracks, 0x00032771, 0x000327B2 },
     84        { kAudioTracksIntro, 0x0002FC88, 0x0002FC8E },
     85
    8386        { -1, 0, 0 }
    8487};
    8588
     
    165168        { kGUIStrings, 0x0002F1EE, 0x0002F3F7 },
    166169        { kNewGameString, 0x00032CFB, 0x00032D10 },
    167170        { kConfigStrings, 0x0002fc3d, 0x0002fc9e },
     171        { kAudioTracks, 0x00033006, 0x00033047 },
     172        { kAudioTracksIntro, 0x0002FE9A, 0x0002FEA6 },
    168173        { -1, 0, 0 }
    169174};
    170175
  • misc.h

     
    8080        kGUIStrings,
    8181        kNewGameString,
    8282        kConfigStrings,
     83        kAudioTracks,
     84        kAudioTracksIntro,
    8385        -1
    8486};
    8587
     
    165167        kGUIStrings,
    166168        kNewGameString,
    167169        kConfigStrings,
     170        kAudioTracks,
     171        kAudioTracksIntro,
    168172        -1
    169173};
    170174
     
    265269        kNewGameString,
    266270        kConfigStrings,
    267271
    268         kKyra1TownsSFXTable,
     272        kKyra1TownsSFXwdTable,
     273        kKyra1TownsSFXbtTable,
     274        kKyra1TownsCDATable,
     275        kAudioTracks,
    269276        kCreditsStrings,
    270         kMenuSKB,
    271         kSjisVTable,
    272277        -1
    273278};
    274279
     
    351356        -1
    352357};
    353358
     359const int kyra2CDFile1EngNeed[] = {
     360        k2SeqplayPakFiles,
     361        k2SeqplayCredits,
     362        k2SeqplayStrings,
     363        k2SeqplaySfxFiles,
     364        k2SeqplaySeqData,
     365        k2SeqplayIntroTracks,
     366        k2SeqplayFinaleTracks,
     367        -1
     368};
     369
     370const int kyra2CDFile1FreNeed[] = {
     371        k2SeqplayStrings,
     372        -1
     373};
     374
     375const int kyra2CDFile1GerNeed[] = {
     376        k2SeqplayStrings,
     377        -1
     378};
     379
     380const int kyra2CDFile2EngNeed[] = {
     381        k2IngameTracks,
     382        -1
     383};
     384
     385const int kyra2CDFile2FreNeed[] = {
     386        -1
     387};
     388
     389const int kyra2CDFile2GerNeed[] = {
     390        -1
     391};
     392
     393const int kyra2FloppyFile1Need[] = {
     394        k2SeqplayPakFiles,
     395        k2SeqplayStrings,
     396        k2SeqplaySfxFiles,
     397        k2SeqplayIntroTracks,
     398        k2SeqplayFinaleTracks,
     399        k2SeqplaySeqData,
     400        -1
     401};
     402
     403const int kyra2FloppyFile2Need[] = {
     404        k2IngamePakFiles,
     405        k2IngameTracks,
     406        -1
     407};
     408
     409const int kyra2TownsFile1EngNeed[] = {
     410        k2SeqplayPakFiles,
     411        k2SeqplayStrings,
     412        k2SeqplaySfxFiles,
     413        k2SeqplaySeqData,
     414        k2SeqplayIntroCDA,
     415        k2SeqplayFinaleCDA,
     416        -1
     417};
     418
     419const int kyra2TownsFile1JapNeed[] = {
     420        k2SeqplayStrings,
     421        -1
     422};
     423
     424const int kyra2TownsFile2EngNeed[] = {
     425        k2IngamePakFiles,
     426        k2IngameCDA,
     427        -1
     428};
     429
     430const int kyra2TownsFile2JapNeed[] = {
     431        -1
     432};
     433
     434const int kyra2DemoNeed[] = {
     435        k2SeqplayPakFiles,
     436        k2SeqplaySeqData,
     437        k2SeqplaySfxFiles,
     438        k2SeqplayIntroTracks,
     439        -1
     440};
     441
     442const int kyra2LolDemoNeed[] = {
     443        k2SeqplayPakFiles,
     444        k2SeqplayStrings,
     445        k2SeqplaySeqData,
     446        k2SeqplaySfxFiles,
     447        k2SeqplayIntroTracks,
     448        -1
     449};
     450
    354451const GameNeed gameNeedTable[] = {
    355452        { kKyra1, -1, kyra1FloppyNeed },
    356453        { kKyra1, kTalkieVersion, kyra1CDNeed },
     
    358455        { kKyra1, kFMTownsVersionJ, kyra1TownsJapNeed },
    359456        { kKyra1, kAmigaVersion, kyra1AmigaNeed },
    360457        { kKyra1, kDemoVersion, kyra1DemoNeed },
     458
     459        { kKyra2, k2FloppyFile1, kyra2FloppyFile1Need },
     460        { kKyra2, k2FloppyFile2, kyra2FloppyFile2Need },
     461        { kKyra2, k2CDFile1E, kyra2CDFile1EngNeed },
     462        { kKyra2, k2CDFile1F, kyra2CDFile1FreNeed },
     463        { kKyra2, k2CDFile1G, kyra2CDFile1GerNeed },
     464        { kKyra2, k2CDFile2E, kyra2CDFile2EngNeed },
     465        { kKyra2, k2CDFile2F, kyra2CDFile2FreNeed },
     466        { kKyra2, k2CDFile2G, kyra2CDFile2GerNeed },
     467        { kKyra2, k2TownsFile1E , kyra2TownsFile1EngNeed },
     468        { kKyra2, k2TownsFile1J, kyra2TownsFile1JapNeed },
     469        { kKyra2, k2TownsFile2E , kyra2TownsFile2EngNeed },
     470        { kKyra2, k2TownsFile2J, kyra2TownsFile2JapNeed },
     471        { kKyra2, k2DemoVersion, kyra2DemoNeed},
     472        { kLol, k2DemoLol, kyra2LolDemoNeed},
     473
    361474        { -1, -1, 0 }
    362475};
    363476
     
    367480        { kFMTownsVersionE , "TNS" },
    368481        { kFMTownsVersionJ, "TNS" },
    369482        { kAmigaVersion, "AMG" },
     483
     484        { k2CDFile1E, "CD" },
     485        { k2CDFile1F, "CD" },
     486        { k2CDFile1G, "CD" },
     487        { k2CDFile2E, "CD" },
     488        { k2CDFile2F, "CD" },
     489        { k2CDFile2G, "CD" },
     490        { k2TownsFile1E, "TNS" },
     491        { k2TownsFile1J, "TNS" },
     492        { k2TownsFile2E, "TNS" },
     493        { k2TownsFile2J, "TNS" },
     494        { k2DemoVersion, "DEM" },
     495        { k2DemoLol, "DEM" },   
     496
    370497        { -1, 0 }
    371498};
    372499
     
    379506        { JA_JPN, "JPN" },
    380507        { -1, 0 }
    381508};
    382 
  • towns.h

     
    8080        { kGUIStrings, 0x000291E0, 0x000293DC },
    8181        { kNewGameString, 0x0002919C, 0x000291B1 },
    8282        { kConfigStrings, 0x00029360, 0x000293AA},
    83         { kKyra1TownsSFXTable, 0x0003A978, 0x0004CF80 },
     83        { kKyra1TownsSFXwdTable, 0x0003A978, 0x0004CF80 },
     84        { kKyra1TownsSFXbtTable, 0x0003A878, 0x0003A978 },
     85        { kKyra1TownsCDATable, 0x0004D021, 0x0004D2E5 },
     86        { kAudioTracks, 0x00027B8E, 0x00027BEB },
    8487        { kCreditsStrings, 0x0002AED8, 0x0002B464 },
    85         { kMenuSKB, 0x000293DE, 0x000294A7 },
    86         { kSjisVTable, 0x0003A421, 0x0003A749 },
    8788        { -1, 0, 0 }
    8889};
    8990