Ticket #8797: dlgTim_v2.patch

File dlgTim_v2.patch, 27.0 KB (added by lordhoto, 16 years ago)
  • staticres.cpp

     
    3535
    3636namespace Kyra {
    3737
    38 #define RESFILE_VERSION 20
     38#define RESFILE_VERSION 21
    3939
    4040bool StaticResource::checkKyraDat() {
    4141        Common::File kyraDat;
     
    242242                // Ingame
    243243                { k2IngamePakFiles, kStringList, "I_PAKFILES.TXT" },
    244244                { k2IngameSfxFiles, kStringList, "I_SFXFILES.TXT" },
    245                 { k2IngameSfxIndex, kRawData, "I_SFXINDEX.TRA" },
     245                { k2IngameSfxIndex, kRawData, "I_SFXINDEX.MAP" },
    246246                { k2IngameTracks, kStringList, "I_TRACKS.TRA" },
    247247                { k2IngameCDA, kRawData, "I_TRACKS.CDA" },
     248                { k2IngameTimIndex, kRawData, "I_TIMINDEX.MAP" },
     249                { k2IngameTimJpStrings, kStringList, "I_TIMJPSTR.TXT" },
    248250
    249251                { 0, 0, 0 }
    250252        };
     
    926928        _cdaTrackTableIntro = _staticres->loadRawData(k2SeqplayIntroCDA, _cdaTrackTableIntroSize);
    927929        _cdaTrackTableIngame = _staticres->loadRawData(k2IngameCDA, _cdaTrackTableIngameSize);
    928930        _cdaTrackTableFinale = _staticres->loadRawData(k2SeqplayFinaleCDA, _cdaTrackTableFinaleSize);
     931        _ingameTimIndex = (const uint16*) _staticres->loadRawData(k2IngameTimIndex, _ingameTimIndexSize);
     932        _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize);
    929933
    930934        // replace sequence talkie files with localized versions and cut off .voc
    931935        // suffix from voc files so as to allow compression specific file extensions
  • module.mk

     
    2525        script_v2.o \
    2626        script.o \
    2727        seqplayer.o \
     28        sequences_tim.o \
    2829        sequences_v1.o \
    2930        sequences_v2.o \
    3031        sound_adlib.o \
  • script_v2.cpp

     
    622622        return 0;
    623623}
    624624
     625int KyraEngine_v2::o2_useItemOnMainChar(ScriptState *script) {
     626        ScriptState tmpScript;
     627        _scriptInterpreter->initScript(&tmpScript, &_npcScriptData);
     628        _scriptInterpreter->startScript(&tmpScript, 0);
     629        tmpScript.regs[4] = _itemInHand;
     630        tmpScript.regs[0] = _mainCharacter.sceneId;
     631
     632        int oldVocH = _vocHigh;
     633        _vocHigh = 0x5a;
     634
     635        while(_scriptInterpreter->validScript(&tmpScript))
     636                _scriptInterpreter->runScript(&tmpScript);
     637
     638        _vocHigh = oldVocH;
     639
     640        return 0;
     641}
     642
     643int KyraEngine_v2::o2_startDialogue(ScriptState *script) {
     644        debugC(3, kDebugLevelScriptFuncs, "o2_startDialogue(%p) (%d)", (const void *)script, stackPos(0));
     645        startDialogue(stackPos(0));
     646        return 0;
     647}
     648
     649int KyraEngine_v2::o2_setupDialogue(ScriptState *script) {
     650        debugC(3, kDebugLevelScriptFuncs, "o2_setupDialogue(%p) (%d)", (const void *)script, stackPos(0));
     651        setNewDlgIndex(stackPos(0));
     652        return 0;
     653}
     654
     655int KyraEngine_v2::o2_getDlgIndex(ScriptState *script) {
     656        debugC(3, kDebugLevelScriptFuncs, "o2_setNewDlgIndex(%p) (%d)", (const void *)script, stackPos(0));
     657        return _mainCharacter.dlgIndex;
     658}
     659
    625660int KyraEngine_v2::o2_defineRoom(ScriptState *script) {
    626661        debugC(3, kDebugLevelScriptFuncs, "o2_defineRoom(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)", (const void *)script,
    627662                        stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
     
    653688        return 0;
    654689}
    655690
     691int KyraEngine_v2::o2_getColorCodeFlag1(ScriptState *script) {
     692        debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag1(%p)", (const void *)script);
     693        return _colorCodeFlag1;
     694}
     695
     696int KyraEngine_v2::o2_setColorCodeFlag1(ScriptState *script) {
     697        debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag1(%p) (%d)", (const void *)script, stackPos(0));
     698        _colorCodeFlag1 = stackPos(0);
     699        return 0;
     700}
     701
     702int KyraEngine_v2::o2_getColorCodeFlag2(ScriptState *script) {
     703        debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag2(%p)", (const void *)script);
     704        return _colorCodeFlag2;
     705}
     706
     707int KyraEngine_v2::o2_setColorCodeFlag2(ScriptState *script) {
     708        debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag2(%p) (%d)", (const void *)script, stackPos(0));
     709        _colorCodeFlag2 = stackPos(0);
     710        return 0;
     711}
     712
    656713int KyraEngine_v2::o2_countItemInstances(ScriptState *script) {
    657714        debugC(3, kDebugLevelScriptFuncs, "o2_countItemInstances(%p) (%d)", (const void *)script, stackPos(0));
    658715        uint16 item = stackPos(0);
     
    691748        return 0;
    692749}
    693750
     751int KyraEngine_v2::o2_npcChat(ScriptState *script) {
     752        if (_flags.isTalkie) {
     753                debugC(3, kDebugLevelScriptFuncs, "o2_npcChat(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), _vocHigh, stackPos(2));
     754                npcChatSequence(stackPosString(0), stackPos(1), _vocHigh, stackPos(2));
     755        } else {
     756                debugC(3, kDebugLevelScriptFuncs, "o2_npcChat(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
     757                npcChatSequence(stackPosString(0), stackPos(1));
     758        }
     759        return 0;
     760}
     761
    694762int KyraEngine_v2::o2_deinitObject(ScriptState *script) {
    695763        debugC(3, kDebugLevelScriptFuncs, "o2_deinitObject(%p) (%d)", (const void *)script, stackPos(0));
    696764        deinitTalkObject(stackPos(0));
  • kyra_v2.h

     
    495495        void runSceneScript6();
    496496        void runSceneScript7();
    497497
     498        void sceneStartupChat();
     499
    498500        void initSceneAnims(int unk1);
    499501        void initSceneScreen(int unk1);
    500502
     
    589591        // character
    590592        struct Character {
    591593                uint16 sceneId;
    592                 uint16 unk2;
     594                uint16 dlgIndex;
    593595                uint8 height;
    594596                uint8 facing;
    595597                uint16 animFrame;
     
    652654        void objectChatPrintText(const char *text, int object);
    653655        void objectChatProcess(const char *script);
    654656        void objectChatWaitToFinish();
    655         void initTalkObject(int initObject);
    656         void deinitTalkObject(int initObject);
    657657
     658        void startDialogue(int dlgIndex);
     659        void updateDlgBuffer();
     660        void loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2);
     661        void processDialogue(int dlgOffset, int vocH = 0, int csEntry = 0);
     662        void npcChatSequence(const char *str, int timId, int vocHigh = -1, int vocLow = -1);
     663        void setNewDlgIndex(int dlgIndex);
     664
     665        int _npcTalkChpIndex;
     666        int _npcTalkDlgIndex;   
     667        uint8 _newSceneDlgState[32];
     668        int8 **_conversationState;
     669        uint8 _npcTalkUNK;
     670        uint8 *_dlgBuffer;
     671
     672        // tim sequence
     673        void tim_setupOpcodes();
     674        byte* tim_loadFile(const char *filename, byte *buffer, int32 bufferSize);
     675        void tim_releaseBuffer(byte *buffer);
     676        void tim_processSequence(uint8 *timBuffer, int loop);
     677
     678        int tim_o_dummy_r0(uint8 *ptr);
     679        int tim_o_dummy_r1(uint8 *ptr);
     680        int tim_o_clearCmds2(uint8 *ptr);
     681        int tim_o_abort(uint8 *ptr);           
     682        int tim_o_selectcurrentCommandSet(uint8 *ptr);
     683        int tim_o_deleteBuffer(uint8 *ptr);
     684        int tim_o_refreshTimers(uint8 *ptr);
     685        int tim_o_execSubOpcode(uint8 *ptr);
     686        int tim_o_initActiveSub(uint8 *ptr);
     687        int tim_o_resetActiveSub(uint8 *ptr);
     688        int tim_o_printTalkText(uint8 *ptr);
     689        int tim_o_updateSceneAnim(uint8 *ptr);
     690        int tim_o_resetChat(uint8 *ptr);
     691        int tim_o_playSoundEffect(uint8 *ptr);
     692
     693        typedef int (KyraEngine_v2::*TimOpc)(uint8 *ptr);
     694        const TimOpc *_timOpcodes;
     695
     696        struct TIMHeader {
     697                uint16 deleteBufferFlag;
     698                int16 unkFlag;
     699                int16 unkFlag2;
     700                int16 cmdsOffset;
     701                int16 unkOffset2;
     702                int16 AVTLOffset;
     703                int16 TEXTOffset;
     704        };
     705
     706        struct Cmds {
     707                uint8 *dataPtr;
     708                uint32 unk_2;
     709                uint32 timer1;
     710                uint32 timer2;
     711                uint8 *backupPtr;
     712                uint8 *AVTLSubChunk;
     713        };
     714
     715        struct TIMBuffers {
     716                uint8 *AVTLChunk;
     717                uint8 *TEXTChunk;
     718                uint8 *offsUnkFlag2;
     719                uint8 *offsUnkFlag;
     720                int16 currentEntry;
     721                int16 unk_12;
     722                Cmds *currentCommandSet;
     723                uint8 *unkCmds;
     724        };
     725        TIMBuffers _TIMBuffers;
     726
     727        const char *_timChatText;
     728        int _timChatObject;
     729
    658730        // sound
    659731        int _oldTalkFile;
    660732        int _currentTalkFile;
     
    689761        void delay(uint32 millis, bool updateGame = false, bool isMainLoop = false);
    690762
    691763        // Talk object handling
     764        void initTalkObject(int index);
     765        void deinitTalkObject(int index);
     766
    692767        struct TalkObject {
    693768                char filename[13];
    694769                int8 scriptId;
     
    697772        };
    698773        TalkObject *_talkObjectList;
    699774
    700         struct TIMHeader {
    701                 uint16 deleteBufferFlag;
    702                 int16 unkFlag;
    703                 int16 unkFlag2;
    704                 int16 unkOffset;
    705                 int16 unkOffset2;
    706                 int16 AVTLOffset;
    707                 int16 TEXTOffset;
    708         };
    709 
    710         struct TIMStructUnk1 {
    711                 uint16 unk_0;
    712                 uint16 unk_2;
    713                 uint16 unk_4;
    714                 uint16 unk_8;
    715                 uint16 *unk_20;
    716         };
    717 
    718         struct TIMBuffers {
    719                 uint16 *AVTLChunk;
    720                 byte *TEXTChunk;
    721                 TIMStructUnk1 *UnkChunk;
    722         };
    723         TIMBuffers _TIMBuffers;
    724 
    725775        struct TalkSections {
    726776                byte *STATim;
    727777                byte *TLKTim;
     
    730780        TalkSections _currentTalkSections;
    731781
    732782        bool _objectChatFinished;
    733         byte *loadTIMFile(const char *filename, byte *buffer, int32 bufferSize);
    734         void freeTIM(byte *buffer);
    735783
    736784        // ingame static sequence handling
    737785        void seq_makeBookOrCauldronAppear(int type);
     
    809857        int o2_setSpecialSceneScriptRunTime(ScriptState *script);
    810858        int o2_defineSceneAnim(ScriptState *script);
    811859        int o2_updateSceneAnim(ScriptState *script);
     860        int o2_useItemOnMainChar(ScriptState *script);
     861        int o2_startDialogue(ScriptState *script);
     862        int o2_setupDialogue(ScriptState *script);
     863        int o2_getDlgIndex(ScriptState *script);
    812864        int o2_defineRoom(ScriptState *script);
    813865        int o2_objectChat(ScriptState *script);
     866        int o2_getColorCodeFlag1(ScriptState *script);
     867        int o2_setColorCodeFlag1(ScriptState *script);
     868        int o2_getColorCodeFlag2(ScriptState *script);
     869        int o2_setColorCodeFlag2(ScriptState *script);
    814870        int o2_countItemInstances(ScriptState *script);
    815871        int o2_initObject(ScriptState *script);
     872        int o2_npcChat(ScriptState *script);
    816873        int o2_deinitObject(ScriptState *script);
    817874        int o2_makeBookOrCauldronAppear(ScriptState *script);
    818875        int o2_setSpecialSceneScriptState(ScriptState *script);
     
    896953        int _ingameSoundIndexSize;
    897954        const char *const *_sequenceStrings;
    898955        int _sequenceStringsSize;
     956        const uint16 *_ingameTimIndex;
     957        int _ingameTimIndexSize;
     958        const char *const *_ingameTimJpStr;
     959        int _ingameTimJpStrSize;
    899960        uint8 *_demoShapeDefs;
    900961        int _sequenceStringsDuration[33];
    901962
     
    919980
    920981        Sequence *_sequences;
    921982        NestedSequence *_nSequences;
     983
     984        // these are used whenever the color code has to be entered
     985        int _colorCodeFlag1;
     986        int _colorCodeFlag2;
    922987};
    923988
    924989} // end of namespace Kyra
  • text_v2.cpp

     
    2727#include "kyra/kyra_v2.h"
    2828#include "kyra/resource.h"
    2929
     30#include "common/endian.h"
     31
    3032namespace Kyra {
    3133
    3234TextDisplayer_v2::TextDisplayer_v2(KyraEngine_v2 *vm, Screen_v2 *screen)
     
    325327                        }
    326328
    327329                        const uint32 curTime = _system->getMillis();
    328                         if ((textEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || _skipFlag) {
     330                        if ((textEnabled() && curTime > endTime) || (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) || _skipFlag) {
    329331                                _skipFlag = false;
    330332                                nextFrame = curTime;
    331333                                running = false;
     
    340342        resetCharacterAnimDim();
    341343}
    342344
    343 void KyraEngine_v2::initTalkObject(int initObject) {
    344         TalkObject &object = _talkObjectList[initObject];
     345void KyraEngine_v2::startDialogue(int dlgIndex) {
     346        updateDlgBuffer();
     347        int csEntry, vocH, unused1, unused2;
     348        loadDlgHeader(csEntry, vocH, unused1, unused2);
     349        int s = _conversationState[dlgIndex][csEntry];
     350        uint8 bufferIndex = 8;
    345351
     352        if (s == -1) {
     353                bufferIndex += (dlgIndex * 6);
     354                _conversationState[dlgIndex][csEntry] = 0;
     355        } else if (!s || s == 2) {
     356                bufferIndex += (dlgIndex * 6 + 2);
     357                _conversationState[dlgIndex][csEntry] = 1;
     358        } else {
     359                bufferIndex += (dlgIndex * 6 + 4);
     360                _conversationState[dlgIndex][csEntry] = 2;
     361        }
     362
     363        int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
     364        processDialogue(offs, vocH, csEntry);
     365}
     366
     367void KyraEngine_v2::updateDlgBuffer() {
     368        static const char DlgFileTemplate[] = "CH**-S**.DLG";
     369        char filename[13];
     370        filename[12] = 0;
     371        memcpy(filename, DlgFileTemplate, 12);
     372
     373        static const char suffixTalkie[] = "EFG";
     374        static const char suffixTowns[] = "G  J";
     375        const char *suffix = _flags.isTalkie ? suffixTalkie : suffixTowns;
     376
     377        filename[2] = (char)((_currentChapter / 10 + 48) & 0xFF);
     378        filename[3] = (char)((_currentChapter % 10 + 48) & 0xFF);
     379       
     380        if (!(_flags.platform == Common::kPlatformPC && !_flags.isTalkie))
     381                filename[11] = suffix[_lang];
     382
     383        if (_currentChapter == _npcTalkChpIndex && _mainCharacter.dlgIndex == _npcTalkDlgIndex)
     384                return;
     385
     386        _npcTalkChpIndex = _currentChapter;
     387        _npcTalkDlgIndex = _mainCharacter.dlgIndex;
     388
     389        filename[6] = (char)((_npcTalkDlgIndex / 10 + 48) & 0xFF);
     390        filename[7] = (char)((_npcTalkDlgIndex % 10 + 48) & 0xFF);
     391
     392        if (_dlgBuffer)
     393                delete [] _dlgBuffer;
     394       
     395        _dlgBuffer = _res->fileData(filename, 0);
     396}
     397
     398void KyraEngine_v2::loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2) {
     399        csEntry = READ_LE_UINT16(_dlgBuffer);
     400        vocH = READ_LE_UINT16(_dlgBuffer + 2);
     401        scIndex1 = READ_LE_UINT16(_dlgBuffer + 4);
     402        scIndex2 = READ_LE_UINT16(_dlgBuffer + 6);
     403}
     404
     405void KyraEngine_v2::processDialogue(int dlgOffset, int vocH, int csEntry) {
     406        int activeTimSequence = -1;
     407        int nextTimSequence = -1;
     408        int cmd = 0;
     409        int vocHi = -1;
     410        int vocLo = -1;
     411        bool loop = true;
     412        int offs = dlgOffset;
     413
     414        _screen->hideMouse();
     415
     416        while (loop) {
     417                cmd = READ_LE_UINT16(_dlgBuffer + offs);
     418                offs += 2;
     419
     420                nextTimSequence = READ_LE_UINT16(&_ingameTimIndex[cmd]);
     421
     422                if (nextTimSequence == 10) {
     423                        if (queryGameFlag(0x3e))
     424                                nextTimSequence = 14;
     425                        if (queryGameFlag(0x3f))
     426                                nextTimSequence = 15;
     427                        if (queryGameFlag(0x40))
     428                                nextTimSequence = 16;
     429                }
     430
     431                if (nextTimSequence == 27 && _mainCharacter.sceneId == 34)
     432                        nextTimSequence = 41;
     433
     434                if (queryGameFlag(0x72)) {
     435                        if (nextTimSequence == 18)
     436                                nextTimSequence = 43;
     437                        else if (nextTimSequence == 19)
     438                                nextTimSequence = 44;
     439                }
     440
     441                if (_mainCharacter.x1 > 160) {
     442                        if (nextTimSequence == 4)
     443                                nextTimSequence = 46;
     444                        else if (nextTimSequence == 5)
     445                                nextTimSequence = 47;
     446                }
     447
     448                if (cmd == 10) {
     449                        loop = false;
     450
     451                } else if (cmd == 4) {
     452                        csEntry = READ_LE_UINT16(_dlgBuffer + offs);
     453                        setNewDlgIndex(csEntry);
     454                        offs += 2;
     455
     456                } else {
     457                        if (!_flags.isTalkie || cmd == 11) {
     458                                int len = READ_LE_UINT16(_dlgBuffer + offs);
     459                                offs += 2;
     460                                if (_flags.isTalkie) {
     461                                        vocLo = READ_LE_UINT16(_dlgBuffer + offs);
     462                                        offs += 2;
     463                                }
     464                                memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
     465                                _unkBuf500Bytes[len] = 0;
     466                                offs += len;
     467                                if (_flags.isTalkie)
     468                                        continue;
     469
     470                        } else if (_flags.isTalkie) {
     471                                int len = READ_LE_UINT16(_dlgBuffer + offs);
     472                                offs += 2;
     473                                static const int irnv[] = { 91, 105, 110, 114, 118 };
     474                                vocHi = irnv[vocH - 1] + csEntry;
     475                                vocLo = READ_LE_UINT16(_dlgBuffer + offs);
     476                                offs += 2;
     477                                memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
     478                                _unkBuf500Bytes[len] = 0;
     479                                offs += len;
     480                        }
     481
     482                        if (_unkBuf500Bytes[0]) {
     483                                if ((!_flags.isTalkie && cmd == 11) || (_flags.isTalkie && cmd == 12)) {
     484                                        if (activeTimSequence > -1) {
     485                                                deinitTalkObject(activeTimSequence);
     486                                                activeTimSequence = -1;
     487                                        }
     488                                        objectChat((const char*) _unkBuf500Bytes, 0, vocHi, vocLo);                                     
     489                                } else {
     490                                        if (activeTimSequence != nextTimSequence ) {
     491                                                if (activeTimSequence > -1) {
     492                                                        deinitTalkObject(activeTimSequence);
     493                                                        activeTimSequence = -1;
     494                                                }
     495                                                initTalkObject(nextTimSequence);
     496                                                activeTimSequence = nextTimSequence;
     497                                        }
     498                                        npcChatSequence((const char *)_unkBuf500Bytes, nextTimSequence, vocHi, vocLo);
     499                                }
     500                        }
     501                }
     502        }
     503
     504        if (activeTimSequence > -1)
     505                deinitTalkObject(activeTimSequence);
     506
     507        _screen->showMouse();
     508}
     509
     510void KyraEngine_v2::initTalkObject(int index) {
     511        TalkObject &object = _talkObjectList[index];
     512
    346513        char STAFilename[13];
    347514        char TLKFilename[13];
    348515        char ENDFilename[13];
     
    355522        strcpy(TLKFilename + 4, "_TLK.TIM");
    356523        strcpy(ENDFilename + 4, "_END.TIM");
    357524
    358         _currentTalkSections.STATim = loadTIMFile(STAFilename, NULL, 0);
    359         _currentTalkSections.TLKTim = loadTIMFile(TLKFilename, NULL, 0);
    360         _currentTalkSections.ENDTim = loadTIMFile(ENDFilename, NULL, 0);
     525        _currentTalkSections.STATim = tim_loadFile(STAFilename, NULL, 0);
     526        _currentTalkSections.TLKTim = tim_loadFile(TLKFilename, NULL, 0);
     527        _currentTalkSections.ENDTim = tim_loadFile(ENDFilename, NULL, 0);
    361528
    362529        if (object.scriptId != -1) {
    363530                _specialSceneScriptStateBackup[object.scriptId] = _specialSceneScriptState[object.scriptId];
    364531                _specialSceneScriptState[object.scriptId] = 1;
    365532        }
    366533
    367         /*if (_currentTalkObject.STATim) {
     534        if (_currentTalkSections.STATim) {
    368535                _objectChatFinished = false;
    369536                while (!_objectChatFinished) {
    370                         processTalkObject(_currentTalkObject.STATim, 0);
     537                        tim_processSequence(_currentTalkSections.STATim, 0);
    371538                        if (_chatText)
    372539                                updateWithText();
    373540                        else
    374541                                update();
    375542                }
    376         }*/
     543        }
    377544}
    378545
    379 void KyraEngine_v2::deinitTalkObject(int initObject) {
    380         TalkObject &object = _talkObjectList[initObject];
     546void KyraEngine_v2::deinitTalkObject(int index) {
     547        TalkObject &object = _talkObjectList[index];
    381548
    382         /*if (_currentTalkObject.ENDTim) {
     549        if (_currentTalkSections.ENDTim) {
    383550                _objectChatFinished = false;
    384551                while (!_objectChatFinished) {
    385                         processTalkObject(_currentTalkObject.ENDTim, 0);
     552                        tim_processSequence(_currentTalkSections.ENDTim, 0);
    386553                        if (_chatText)
    387554                                updateWithText();
    388555                        else
    389556                                update();
    390557                }
    391         }*/
     558        }
    392559
    393560        if (object.scriptId != -1) {
    394561                _specialSceneScriptState[object.scriptId] = _specialSceneScriptStateBackup[object.scriptId];
    395562        }
    396563
    397564        if (_currentTalkSections.STATim != NULL) {
    398                 freeTIM(_currentTalkSections.STATim);
     565                tim_releaseBuffer(_currentTalkSections.STATim);
    399566                _currentTalkSections.STATim = NULL;
    400567        }
    401568
    402569        if (_currentTalkSections.TLKTim != NULL) {
    403                 freeTIM(_currentTalkSections.TLKTim);
     570                tim_releaseBuffer(_currentTalkSections.TLKTim);
    404571                _currentTalkSections.TLKTim = NULL;
    405572        }
    406573
    407574        if (_currentTalkSections.ENDTim != NULL) {
    408                 freeTIM(_currentTalkSections.ENDTim);
     575                tim_releaseBuffer(_currentTalkSections.ENDTim);
    409576                _currentTalkSections.ENDTim = NULL;
    410577        }
    411578}
    412579
    413 byte *KyraEngine_v2::loadTIMFile(const char *filename, byte *buffer, int32 bufferSize) {
    414         ScriptFileParser file(filename, _res);
    415         if (!file) {
    416                 error("Couldn't open script file '%s'", filename);
    417                 return NULL;
    418         }
     580void KyraEngine_v2::npcChatSequence(const char *str, int timId, int vocHigh, int vocLow) {
     581        _chatText = str;
     582        _chatObject = timId;
     583        objectChatInit(str, timId, vocHigh, vocLow);
    419584
    420         int32 formBlockSize = file.getFORMBlockSize();
    421         if (formBlockSize == -1) {
    422                 error("No FORM chunk found in file: '%s'", filename);
    423                 return NULL;
    424         }
     585        if (!_currentTalkSections.TLKTim)
     586                _currentTalkSections.TLKTim = tim_loadFile(_talkObjectList[READ_LE_UINT16(&_ingameTimIndex[timId])].filename, 0, 0);
    425587
    426         if (formBlockSize < 20) {
    427                 return NULL;
    428         }
     588        setNextIdleAnimTimer();
     589       
     590        uint32 ct = chatCalcDuration(str);
     591        uint32 time = _system->getMillis();
     592        _chatEndTime =  time + (3 + ct) * _tickLength;
     593        uint32 chatAnimEndTime = time + (3 + (ct >> 1)) * _tickLength;
    429594
    430         formBlockSize += sizeof(TIMHeader) + 120 + sizeof(TIMStructUnk1) * 10;
    431 
    432         TIMHeader *timHeader;
    433         if (buffer == NULL || bufferSize < formBlockSize) {
    434                 buffer = new byte[formBlockSize];
    435                 timHeader = (TIMHeader *)buffer;
    436                 timHeader->deleteBufferFlag = 0xBABE;
    437         } else {
    438                 timHeader = (TIMHeader *)buffer;
    439                 timHeader->deleteBufferFlag = 0x0;
     595        if (_chatVocHigh >= 0) {
     596                playVoice(_chatVocHigh, _chatVocLow);
     597                _chatVocHigh = _chatVocLow = -1;
    440598        }
    441599
    442         int32 chunkSize = file.getIFFBlockSize(AVTL_CHUNK);
    443         timHeader->unkFlag = -1;
    444         timHeader->unkFlag2 = 0;
    445         timHeader->unkOffset = sizeof(TIMHeader);
    446         timHeader->unkOffset2 = timHeader->unkOffset + sizeof(TIMStructUnk1) * 10;
    447         timHeader->AVTLOffset = timHeader->unkOffset2 + 120;
    448         timHeader->TEXTOffset = timHeader->AVTLOffset + chunkSize;
     600        while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || _skipFlag)) {
     601                if (chatAnimEndTime > _system->getMillis()) {
     602                        _objectChatFinished = false;
    449603
    450         _TIMBuffers.AVTLChunk = (uint16 *)(buffer + timHeader->AVTLOffset);
    451         _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
     604                        while (!_objectChatFinished && !_skipFlag) {           
     605                                if (_currentTalkSections.TLKTim)
     606                                        tim_processSequence(_currentTalkSections.TLKTim, 0);
     607                                else
     608                                        _objectChatFinished = false;
    452609
    453         if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
    454                 error("Couldn't load AVTL chunk from file: '%s'", filename);
    455                 return NULL;
     610                                updateWithText();
     611       
     612                                int inputFlag = checkInput(0);
     613                                removeInputTop();
     614                                if (inputFlag == 198 || inputFlag == 199) {
     615                                        //XXX
     616                                        _skipFlag = true;
     617                                        snd_stopVoice();
     618                                }
     619                                delay(10);
     620                        }
     621                        if (_currentTalkSections.TLKTim)
     622                                tim_o_abort(0);
     623                }
     624                updateWithText();
    456625        }
    457626
    458         _TIMBuffers.UnkChunk = (TIMStructUnk1 *)(buffer + timHeader->unkOffset);
     627        _skipFlag = false;
    459628
    460         for (int i = 0; i < 10; i++) {
    461                 _TIMBuffers.UnkChunk[i].unk_0 = 0;
    462                 _TIMBuffers.UnkChunk[i].unk_2 = 0;
    463                 _TIMBuffers.UnkChunk[i].unk_20 = &_TIMBuffers.AVTLChunk[ _TIMBuffers.AVTLChunk[i] ];
    464                 _TIMBuffers.UnkChunk[i].unk_4 = 0;
    465                 _TIMBuffers.UnkChunk[i].unk_8 = 0;
     629        if (_currentTalkSections.TLKTim) {
     630                tim_releaseBuffer(_currentTalkSections.TLKTim);
     631                _currentTalkSections.TLKTim = 0;
    466632        }
    467633
    468         chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
    469         if (chunkSize > 0) {
    470                 if (!file.loadIFFBlock(TEXT_CHUNK, _TIMBuffers.TEXTChunk, chunkSize)) {
    471                         error("Couldn't load TEXT chunk from file: '%s'", filename);
    472                         return NULL;
    473                 }
    474         }
    475 
    476         return buffer;
     634        snd_stopVoice();
     635        _text->restoreScreen();
     636        _chatText = 0;
     637        _chatObject = -1;
     638        setNextIdleAnimTimer();
    477639}
    478640
    479 void KyraEngine_v2::freeTIM(byte *buffer) {
    480         TIMHeader *timHeader = (TIMHeader *)buffer;
    481 
    482         if (timHeader->deleteBufferFlag == 0xBABE) {
    483                 delete[] buffer;
    484         }
     641void KyraEngine_v2::setNewDlgIndex(int dlgIndex) {
     642        if (dlgIndex == _mainCharacter.dlgIndex)
     643                return;
     644        memset(_newSceneDlgState, 0, 32);
     645        for (int i = 0; i < 19; i++)
     646                memset(_conversationState[i], -1, 14);
     647        _npcTalkUNK = 0;
     648        _mainCharacter.dlgIndex = dlgIndex;
    485649}
    486650
    487651} // end of namespace Kyra
    488652
    489 
  • resource.h

     
    218218        k2IngameSfxIndex,
    219219        k2IngameTracks,
    220220        k2IngameCDA,
     221        k2IngameTimIndex,
     222        k2IngameTimJpStrings,
    221223
    222224        kMaxResIDs
    223225};
  • sound.h

     
    191191private:
    192192        const AudioDataStruct *_soundDataList;
    193193        Audio::AudioStream *_currentVocFile;
    194         Audio::SoundHandle _vocHandle;
     194        enum {
     195                kNumVocHandles = 4
     196        };
     197        Audio::SoundHandle _vocHandles[kNumVocHandles];
    195198
    196199        struct SpeechCodecs {
    197200                const char *fileext;
  • scene_v2.cpp

     
    243243
    244244        if (!unk1) {
    245245                runSceneScript4(0);
    246                 //XXX sub_27158
     246                sceneStartupChat();
    247247        }
    248248
    249249        _unk4 = 0;
     
    499499        _screen->_curPage = oldPage;
    500500}
    501501
     502void KyraEngine_v2::sceneStartupChat() {
     503        int tableIndex = _mainCharacter.sceneId - READ_LE_UINT16(&_ingameTimIndex[5 + _newChapterFile]);
     504        if (queryGameFlag(0x159) || _newSceneDlgState[tableIndex])
     505                return;
     506
     507        int csEntry, vocH, scIndex1, scIndex2;
     508        updateDlgBuffer();
     509        loadDlgHeader(csEntry, vocH, scIndex1, scIndex2);
     510
     511        uint8 bufferIndex = 8;
     512       
     513        bufferIndex += (scIndex1 * 6 + scIndex2 * 4 + tableIndex * 2);
     514        int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
     515        processDialogue(offs, vocH, csEntry);
     516
     517        _newSceneDlgState[tableIndex] = 1;
     518}
     519
    502520void KyraEngine_v2::initSceneAnims(int unk1) {
    503521        for (int i = 0; i < ARRAYSIZE(_animObjects); ++i)
    504522                _animObjects[i].enabled = 0;
  • kyra_v2.cpp

     
    8686        _chatObject = -1;
    8787        _lastIdleScript = -1;
    8888
     89        _timChatText = 0;
     90        _timChatObject = -1;
     91
    8992        _currentTalkSections.STATim = NULL;
    9093        _currentTalkSections.TLKTim = NULL;
    9194        _currentTalkSections.ENDTim = NULL;
    9295
    9396        _invWsa.wsa = 0;
    9497
     98        _colorCodeFlag1 = 0;
     99        _colorCodeFlag2 = -1;
     100
    95101        memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
     102
     103        _dlgBuffer = 0;
     104        _conversationState = new int8*[19];
     105        for (int i = 0; i < 19; i++)
     106                _conversationState[i] = new int8[14];
     107        _npcTalkChpIndex = _npcTalkDlgIndex = -1;
     108        _mainCharacter.dlgIndex = 0;
     109        setNewDlgIndex(-1);
    96110}
    97111
    98112KyraEngine_v2::~KyraEngine_v2() {
     
    109123        _text = 0;
    110124        delete _debugger;
    111125        delete _invWsa.wsa;
     126
     127        if (_dlgBuffer)
     128                delete [] _dlgBuffer;
     129        for (int i = 0; i < 19; i++)
     130                delete [] _conversationState[i];
     131        delete [] _conversationState;
    112132}
    113133
    114134Movie *KyraEngine_v2::createWSAMovie() {
     
    155175        if (_flags.isDemo)
    156176                return 0;
    157177
     178        tim_setupOpcodes();
     179
    158180        _mouseSHPBuf = _res->fileData("PWGMOUSE.SHP", 0);
    159181        assert(_mouseSHPBuf);
    160182
     
    18771899                Opcode(o2_updateSceneAnim),
    18781900                OpcodeUnImpl(),
    18791901                // 0x74
     1902                Opcode(o2_useItemOnMainChar),
     1903                Opcode(o2_startDialogue),
    18801904                OpcodeUnImpl(),
    1881                 OpcodeUnImpl(),
    1882                 OpcodeUnImpl(),
    1883                 OpcodeUnImpl(),
     1905                Opcode(o2_setupDialogue),
    18841906                // 0x78
    1885                 OpcodeUnImpl(),
     1907                Opcode(o2_getDlgIndex),
    18861908                Opcode(o2_defineRoom),
    18871909                OpcodeUnImpl(),
    18881910                OpcodeUnImpl(),
     
    18941916                // 0x80
    18951917                Opcode(o2_objectChat),
    18961918                OpcodeUnImpl(),
    1897                 OpcodeUnImpl(),
    1898                 OpcodeUnImpl(),
     1919                Opcode(o2_getColorCodeFlag1),
     1920                Opcode(o2_setColorCodeFlag1),
    18991921                // 0x84
     1922                Opcode(o2_getColorCodeFlag2),
     1923                Opcode(o2_setColorCodeFlag2),
    19001924                OpcodeUnImpl(),
    19011925                OpcodeUnImpl(),
    1902                 OpcodeUnImpl(),
    1903                 OpcodeUnImpl(),
    19041926                // 0x88
    19051927                Opcode(o2_countItemInstances),
    19061928                OpcodeUnImpl(),
    19071929                Opcode(o2_initObject),
    1908                 OpcodeUnImpl(),
     1930                Opcode(o2_npcChat),
    19091931                // 0x8c
    19101932                Opcode(o2_deinitObject),
    19111933                OpcodeUnImpl(),
  • sound.cpp

     
    3939namespace Kyra {
    4040
    4141Sound::Sound(KyraEngine *vm, Audio::Mixer *mixer)
    42         : _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandle(),
     42        : _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandles(),
    4343        _musicEnabled(1), _sfxEnabled(true), _soundDataList(0) {
    4444}
    4545
     
    7777        }
    7878
    7979        if (_currentVocFile) {
    80                 //_mixer->stopHandle(_vocHandle);
    81                 _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
     80                int h = 0;
     81                while (_mixer->isSoundHandleActive(_vocHandles[h]))
     82                        h++;
     83                if (h >= kNumVocHandles)
     84                        error("Overflow in function 'Sound::voicePlay(const char *file)'. More voc handles required.");
     85                _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandles[h], _currentVocFile);
    8286        }
    8387        delete [] fileData;
    8488        fileSize = 0;
    8589}
    8690
    8791void Sound::voiceStop() {
    88         if (_mixer->isSoundHandleActive(_vocHandle))
    89                 _mixer->stopHandle(_vocHandle);
     92        for (int h = 0; h < kNumVocHandles; h++) {
     93                if (_mixer->isSoundHandleActive(_vocHandles[h]))
     94                        _mixer->stopHandle(_vocHandles[h]);
     95        }
    9096}
    9197
    9298bool Sound::voiceIsPlaying() {
    93         return _mixer->isSoundHandleActive(_vocHandle);
     99        bool res = false;
     100        for (int h = 0; h < kNumVocHandles; h++) {
     101                if (_mixer->isSoundHandleActive(_vocHandles[h]))
     102                        res = true;
     103        }
     104        return res;
    94105}
    95106
    96107#pragma mark -