Ticket #8797: dlgTim_v3.patch

File dlgTim_v3.patch, 39.1 KB (added by athrxx, 17 years ago)
  • 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(),
     
    19721994} // end of namespace Kyra
    19731995
    19741996
     1997
  • 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 objectId, 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        uint8 *tim_loadFile(const char *filename, uint8 *buffer, int32 bufferSize);
     675        void tim_releaseBuffer(uint8 *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        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
     730        // Talk object handling
     731        void initTalkObject(int index);
     732        void deinitTalkObject(int index);
     733
     734        struct TalkObject {
     735                char filename[13];
     736                int8 scriptId;
     737                int16 x, y;
     738                int8 color;
     739        };
     740        TalkObject *_talkObjectList;
     741
     742        struct TalkSections {
     743                uint8 *STATim;
     744                uint8 *TLKTim;
     745                uint8 *ENDTim;
     746        };
     747        TalkSections _currentTalkSections;
     748
     749        char _TLKFilename[13];
     750        bool _objectChatFinished;
     751
    658752        // sound
    659753        int _oldTalkFile;
    660754        int _currentTalkFile;
     
    688782        // delay
    689783        void delay(uint32 millis, bool updateGame = false, bool isMainLoop = false);
    690784
    691         // Talk object handling
    692         struct TalkObject {
    693                 char filename[13];
    694                 int8 scriptId;
    695                 int16 x, y;
    696                 int8 color;
    697         };
    698         TalkObject *_talkObjectList;
    699 
    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 
    725         struct TalkSections {
    726                 byte *STATim;
    727                 byte *TLKTim;
    728                 byte *ENDTim;
    729         };
    730         TalkSections _currentTalkSections;
    731 
    732         bool _objectChatFinished;
    733         byte *loadTIMFile(const char *filename, byte *buffer, int32 bufferSize);
    734         void freeTIM(byte *buffer);
    735 
    736785        // ingame static sequence handling
    737786        void seq_makeBookOrCauldronAppear(int type);
    738787        void seq_makeBookAppear();
     
    809858        int o2_setSpecialSceneScriptRunTime(ScriptState *script);
    810859        int o2_defineSceneAnim(ScriptState *script);
    811860        int o2_updateSceneAnim(ScriptState *script);
     861        int o2_useItemOnMainChar(ScriptState *script);
     862        int o2_startDialogue(ScriptState *script);
     863        int o2_setupDialogue(ScriptState *script);
     864        int o2_getDlgIndex(ScriptState *script);
    812865        int o2_defineRoom(ScriptState *script);
    813866        int o2_objectChat(ScriptState *script);
     867        int o2_getColorCodeFlag1(ScriptState *script);
     868        int o2_setColorCodeFlag1(ScriptState *script);
     869        int o2_getColorCodeFlag2(ScriptState *script);
     870        int o2_setColorCodeFlag2(ScriptState *script);
    814871        int o2_countItemInstances(ScriptState *script);
    815872        int o2_initObject(ScriptState *script);
     873        int o2_npcChat(ScriptState *script);
    816874        int o2_deinitObject(ScriptState *script);
    817875        int o2_makeBookOrCauldronAppear(ScriptState *script);
    818876        int o2_setSpecialSceneScriptState(ScriptState *script);
     
    896954        int _ingameSoundIndexSize;
    897955        const char *const *_sequenceStrings;
    898956        int _sequenceStringsSize;
     957        const uint16 *_ingameTalkObjIndex;
     958        int _ingameTalkObjIndexSize;
     959        const char *const *_ingameTimJpStr;
     960        int _ingameTimJpStrSize;
    899961        uint8 *_demoShapeDefs;
    900962        int _sequenceStringsDuration[33];
    901963
     
    919981
    920982        Sequence *_sequences;
    921983        NestedSequence *_nSequences;
     984
     985        // these are used whenever the color code has to be entered
     986        int _colorCodeFlag1;
     987        int _colorCodeFlag2;
    922988};
    923989
    924990} // end of namespace Kyra
     
    926992#endif
    927993
    928994
     995
  • 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 \
  • resource.h

     
    218218        k2IngameSfxIndex,
    219219        k2IngameTracks,
    220220        k2IngameCDA,
     221        k2IngameTalkObjIndex,
     222        k2IngameTimJpStrings,
    221223
    222224        kMaxResIDs
    223225};
     
    328330
    329331#endif
    330332
     333
  • 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(&_ingameTalkObjIndex[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;
     
    910928
    911929} // end of namespace Kyra
    912930
     931
  • 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));
     
    840908} // end of namespace Kyra
    841909
    842910
     911
  • sequences_tim.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/kyra/sequences_v1.cpp $
     22 * $Id: sequences_v1.cpp 30667 2008-01-28 00:14:17Z jvprat $
     23 *
     24 */
     25
     26#include "kyra/text_v2.h"
     27#include "kyra/kyra_v2.h"
     28#include "kyra/sound.h"
     29#include "kyra/resource.h"
     30
     31#include "common/endian.h"
     32
     33namespace Kyra {
     34
     35uint8 *KyraEngine_v2::tim_loadFile(const char *filename, byte *buffer, int32 bufferSize) {
     36        ScriptFileParser file(filename, _res);
     37        if (!file) {
     38                error("Couldn't open script file '%s'", filename);
     39                return NULL;
     40        }
     41
     42        int32 formBlockSize = file.getFORMBlockSize();
     43        if (formBlockSize == -1) {
     44                error("No FORM chunk found in file: '%s'", filename);
     45                return NULL;
     46        }
     47
     48        if (formBlockSize < 20) {
     49                return NULL;
     50        }
     51
     52        formBlockSize += sizeof(TIMHeader) +  10 * (sizeof(Cmds) + 120);
     53
     54        TIMHeader *timHeader;
     55        if (buffer == NULL || bufferSize < formBlockSize) {
     56                buffer = new byte[formBlockSize];
     57                timHeader = (TIMHeader *)buffer;
     58                timHeader->deleteBufferFlag = 0xBABE;
     59        } else {
     60                timHeader = (TIMHeader *)buffer;
     61                timHeader->deleteBufferFlag = 0x0;
     62        }
     63
     64        int32 chunkSize = file.getIFFBlockSize(AVTL_CHUNK);
     65        timHeader->unkFlag = -1;
     66        timHeader->unkFlag2 = 0;
     67        timHeader->cmdsOffset = sizeof(TIMHeader);
     68        timHeader->unkOffset2 = timHeader->cmdsOffset + 10 * sizeof(Cmds);
     69        timHeader->AVTLOffset = timHeader->unkOffset2 + 120;
     70        timHeader->TEXTOffset = timHeader->AVTLOffset + chunkSize;
     71
     72        _TIMBuffers.AVTLChunk = buffer + timHeader->AVTLOffset;
     73        _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
     74
     75        if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
     76                error("Couldn't load AVTL chunk from file: '%s'", filename);
     77                return NULL;
     78        }
     79
     80        _TIMBuffers.currentCommandSet = (Cmds *)(buffer + timHeader->cmdsOffset);
     81
     82        for (int i = 0; i < 10; i++) {
     83                _TIMBuffers.currentCommandSet[i].dataPtr = 0;
     84                _TIMBuffers.currentCommandSet[i].unk_2 = 0;
     85                _TIMBuffers.currentCommandSet[i].AVTLSubChunk = &_TIMBuffers.AVTLChunk[READ_LE_UINT16(&_TIMBuffers.AVTLChunk[i << 1]) << 1];
     86                _TIMBuffers.currentCommandSet[i].timer1 = 0;
     87                _TIMBuffers.currentCommandSet[i].timer2 = 0;
     88        }
     89
     90        chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
     91        if (chunkSize > 0) {
     92                if (!file.loadIFFBlock(TEXT_CHUNK, _TIMBuffers.TEXTChunk, chunkSize)) {
     93                        error("Couldn't load TEXT chunk from file: '%s'", filename);
     94                        return NULL;
     95                }
     96        }
     97
     98        return buffer;
     99}
     100
     101void KyraEngine_v2::tim_releaseBuffer(byte *buffer) {
     102        TIMHeader *timHeader = (TIMHeader *)buffer;
     103        if (timHeader->deleteBufferFlag == 0xBABE)
     104                delete[] buffer;
     105}
     106
     107void KyraEngine_v2::tim_processSequence(uint8 *timBuffer, int loop) {
     108        if (!timBuffer)
     109                return;
     110
     111        TIMHeader *hdr = (TIMHeader*) timBuffer;
     112        _TIMBuffers.offsUnkFlag = (uint8*) &hdr->unkFlag;
     113        _TIMBuffers.offsUnkFlag2 = (uint8*) &hdr->unkFlag2;
     114        _TIMBuffers.currentCommandSet = (Cmds*) (timBuffer + hdr->cmdsOffset);
     115        _TIMBuffers.unkCmds = timBuffer + hdr->unkOffset2;
     116        _TIMBuffers.AVTLChunk = timBuffer + hdr->AVTLOffset;
     117        _TIMBuffers.TEXTChunk = timBuffer + hdr->TEXTOffset;
     118
     119        if (!_TIMBuffers.currentCommandSet->dataPtr) {
     120                _TIMBuffers.currentCommandSet->dataPtr = _TIMBuffers.currentCommandSet->AVTLSubChunk;
     121                _TIMBuffers.currentCommandSet->timer1 = _system->getMillis();
     122                _TIMBuffers.currentCommandSet->timer2 = _system->getMillis();
     123        }
     124
     125        do {
     126                _TIMBuffers.currentEntry = 0;
     127
     128                while (_TIMBuffers.currentEntry < 10) {
     129                        Cmds *s = &_TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry];
     130                        if ((int16)READ_LE_UINT16(_TIMBuffers.offsUnkFlag) !=  -1)
     131                                (this->*_timOpcodes[28])(_TIMBuffers.offsUnkFlag2);
     132
     133                        bool loop = true;
     134
     135                        while (s->dataPtr && s->timer2 <= _system->getMillis() && loop) {
     136                                uint8 cmd = s->dataPtr[4];
     137                                hdr->unkFlag2 = cmd;
     138                                uint8 *para = &s->dataPtr[6];
     139
     140                                switch((this->*_timOpcodes[cmd])(para)) {
     141                                        case -3:
     142                                                WRITE_LE_UINT16(_TIMBuffers.offsUnkFlag, _TIMBuffers.currentEntry);
     143                                                _TIMBuffers.unk_12 = -1;
     144                                                break;
     145
     146                                        case -2:
     147                                                loop = false;
     148                                                break;
     149
     150                                        case -1:
     151                                                loop = 0;
     152                                                loop = false;
     153                                                _TIMBuffers.currentEntry = 11;
     154                                                break;
     155                                       
     156                                        case 22:
     157                                                s->backupPtr = 0;
     158                                                break;
     159
     160                                        default:
     161                                                break;
     162                                }                               
     163
     164                                if (s) {
     165                                        if (s->dataPtr) {
     166                                                s->dataPtr += (READ_LE_UINT16(s->dataPtr) * 2);
     167                                                s->timer1 = s->timer2;
     168                                                s->timer2 += (READ_LE_UINT16(s->dataPtr + 2) * _tickLength);
     169                                        }
     170                                }
     171                        }
     172
     173                        _TIMBuffers.currentEntry++;
     174                }
     175        } while (loop == 1);   
     176
     177}
     178
     179int KyraEngine_v2::tim_o_dummy_r0(uint8 *ptr) {
     180        return 0;
     181}
     182
     183int KyraEngine_v2::tim_o_dummy_r1(uint8 *ptr) {
     184        return 1;
     185}
     186
     187int KyraEngine_v2::tim_o_clearCmds2(uint8 *ptr) {
     188        for (int i = 1; i < 10; i++)
     189                memset(&_TIMBuffers.unkCmds[i], 0, 12);
     190        _TIMBuffers.currentCommandSet[0].dataPtr = _TIMBuffers.currentCommandSet[0].AVTLSubChunk;
     191        _TIMBuffers.currentCommandSet[0].timer1 = _system->getMillis();
     192        return 1;
     193}
     194
     195int KyraEngine_v2::tim_o_abort(uint8 *ptr) {
     196        _TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry].dataPtr = 0;
     197        if(!_TIMBuffers.currentEntry)
     198                _objectChatFinished = true;
     199        return -2;     
     200}
     201
     202
     203int KyraEngine_v2::tim_o_selectcurrentCommandSet(uint8 *ptr) {
     204        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk ?
     205        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk : &_TIMBuffers.AVTLChunk[_TIMBuffers.AVTLChunk[READ_LE_UINT16(ptr) << 1] << 1];
     206        return 1;
     207}
     208
     209int KyraEngine_v2::tim_o_deleteBuffer(uint8 *ptr) {
     210        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
     211        return 1;
     212}
     213
     214int KyraEngine_v2::tim_o_refreshTimers(uint8 *ptr) {
     215        for (int i = 1; i < 10; i++) {
     216                if (_TIMBuffers.currentCommandSet[i].dataPtr)
     217                        _TIMBuffers.currentCommandSet[i].timer2 = _system->getMillis();
     218        }
     219
     220        return 1;
     221}
     222
     223int KyraEngine_v2::tim_o_execSubOpcode(uint8 *ptr) {
     224        return (this->*_timOpcodes[30 + READ_LE_UINT16(ptr)])(ptr + 2);
     225}
     226
     227int KyraEngine_v2::tim_o_initActiveSub(uint8 *ptr) {
     228        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk;
     229        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = _system->getMillis();
     230        return 1;
     231}
     232
     233int KyraEngine_v2::tim_o_resetActiveSub(uint8 *ptr) {
     234        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
     235        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = 0;
     236        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = 0;
     237        return 1;
     238}
     239
     240int KyraEngine_v2::tim_o_printTalkText(uint8 *ptr) {
     241        _chatText = _timChatText = (const char*) _TIMBuffers.TEXTChunk + (READ_LE_UINT16(ptr) << 1);
     242        _chatObject = _timChatObject = READ_LE_UINT16(ptr + 2);
     243       
     244        if (_flags.lang == Common::JA_JPN) {
     245                for (int i = 0; i < _ingameTimJpStrSize; i += 2) {
     246                        if (!scumm_stricmp(_timChatText, _ingameTimJpStr[i]))
     247                                _chatText = _ingameTimJpStr[i + 1];
     248                }               
     249        }
     250        objectChatInit(_chatText, _timChatObject);
     251        return 0;
     252}
     253
     254int KyraEngine_v2::tim_o_updateSceneAnim(uint8 *ptr) {
     255        updateSceneAnim(READ_LE_UINT16(ptr + 2), READ_LE_UINT16(ptr));
     256        return 0;
     257}
     258
     259int KyraEngine_v2::tim_o_resetChat(uint8 *ptr) {
     260        _text->restoreScreen();
     261        _chatText = 0;
     262        _chatObject = -1;
     263        _timChatText = 0;
     264        _timChatObject = -1;
     265        return 0;
     266}
     267
     268int KyraEngine_v2::tim_o_playSoundEffect(uint8 *ptr) {
     269        snd_playSoundEffect(READ_LE_UINT16(ptr));
     270        return 0;
     271}
     272
     273void KyraEngine_v2::tim_setupOpcodes() {
     274        static const TimOpc Opcodes[] = {
     275                &KyraEngine_v2::tim_o_clearCmds2,
     276                &KyraEngine_v2::tim_o_abort,
     277                &KyraEngine_v2::tim_o_dummy_r0,
     278                &KyraEngine_v2::tim_o_dummy_r0,
     279                &KyraEngine_v2::tim_o_selectcurrentCommandSet,
     280                &KyraEngine_v2::tim_o_deleteBuffer,
     281                &KyraEngine_v2::tim_o_dummy_r0,
     282                &KyraEngine_v2::tim_o_dummy_r0,
     283                &KyraEngine_v2::tim_o_dummy_r0,
     284                &KyraEngine_v2::tim_o_dummy_r0,
     285                &KyraEngine_v2::tim_o_dummy_r0,
     286                &KyraEngine_v2::tim_o_dummy_r0,
     287                &KyraEngine_v2::tim_o_dummy_r0,
     288                &KyraEngine_v2::tim_o_dummy_r0,
     289                &KyraEngine_v2::tim_o_dummy_r0,
     290                &KyraEngine_v2::tim_o_dummy_r0,
     291                &KyraEngine_v2::tim_o_dummy_r0,
     292                &KyraEngine_v2::tim_o_dummy_r0,
     293                &KyraEngine_v2::tim_o_dummy_r0,
     294                &KyraEngine_v2::tim_o_dummy_r0,
     295                &KyraEngine_v2::tim_o_dummy_r0,
     296                &KyraEngine_v2::tim_o_dummy_r0,
     297                &KyraEngine_v2::tim_o_dummy_r0,
     298                &KyraEngine_v2::tim_o_refreshTimers,
     299                &KyraEngine_v2::tim_o_dummy_r1,
     300                &KyraEngine_v2::tim_o_execSubOpcode,
     301                &KyraEngine_v2::tim_o_initActiveSub,
     302                &KyraEngine_v2::tim_o_resetActiveSub,
     303                &KyraEngine_v2::tim_o_dummy_r1,
     304                &KyraEngine_v2::tim_o_dummy_r1,
     305                &KyraEngine_v2::tim_o_printTalkText,
     306                &KyraEngine_v2::tim_o_updateSceneAnim,
     307                &KyraEngine_v2::tim_o_resetChat,
     308                &KyraEngine_v2::tim_o_playSoundEffect,
     309        };
     310
     311        _timOpcodes = (TimOpc*) (Opcodes);
     312}
     313
     314} // end of namespace Kyra
     315
  • 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
     
    5252        bool found = false;
    5353        char filenamebuffer[25];
    5454
     55        int h = 0;
     56        if (_currentVocFile) {
     57                while (_mixer->isSoundHandleActive(_vocHandles[h]))
     58                        h++;
     59                if (h >= NUM_VOC_HANDLES)
     60                        return;
     61        }
     62
    5563        for (int i = 0; _supportedCodes[i].fileext; ++i) {
    5664                strcpy(filenamebuffer, file);
    5765                strcat(filenamebuffer, _supportedCodes[i].fileext);
     
    7684                _currentVocFile = Audio::makeVOCStream(vocStream);
    7785        }
    7886
    79         if (_currentVocFile) {
    80                 //_mixer->stopHandle(_vocHandle);
    81                 _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
    82         }
     87        _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandles[h], _currentVocFile);
     88
    8389        delete [] fileData;
    8490        fileSize = 0;
    8591}
    8692
    8793void Sound::voiceStop() {
    88         if (_mixer->isSoundHandleActive(_vocHandle))
    89                 _mixer->stopHandle(_vocHandle);
     94        for (int h = 0; h < kNumVocHandles; h++) {
     95                if (_mixer->isSoundHandleActive(_vocHandles[h]))
     96                        _mixer->stopHandle(_vocHandles[h]);
     97        }
    9098}
    9199
    92100bool Sound::voiceIsPlaying() {
    93         return _mixer->isSoundHandleActive(_vocHandle);
     101        bool res = false;
     102        for (int h = 0; h < kNumVocHandles; h++) {
     103                if (_mixer->isSoundHandleActive(_vocHandles[h]))
     104                        res = true;
     105        }
     106        return res;
    94107}
    95108
    96109#pragma mark -
     
    522535
    523536} // end of namespace Kyra
    524537
     538
  • sound.h

     
    5454#include "kyra/kyra.h"
    5555#include "kyra/kyra_v2.h"
    5656
     57#define         NUM_VOC_HANDLES         4
     58
    5759namespace Audio {
    5860class AudioStream;
    5961} // end of namespace Audio
     
    180182        const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
    181183        const int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
    182184
     185        enum {
     186                kNumVocHandles = 4
     187        };
     188
    183189        int _musicEnabled;
    184190        bool _sfxEnabled;
    185191
     
    191197private:
    192198        const AudioDataStruct *_soundDataList;
    193199        Audio::AudioStream *_currentVocFile;
    194         Audio::SoundHandle _vocHandle;
     200        Audio::SoundHandle _vocHandles[kNumVocHandles];
    195201
    196202        struct SpeechCodecs {
    197203                const char *fileext;
     
    425431        int _lastTrack;
    426432
    427433        Audio::AudioStream *_currentSFX;
    428         Audio::SoundHandle _sfxHandle;
     434        Audio::SoundHandle _sfxHandles[NUM_VOC_HANDLES];
    429435
    430436        //SoundTowns_v2_TwnDriver * _driver;
    431437        uint8 * _twnTrackData;
  • staticres.cpp

     
    3535
    3636namespace Kyra {
    3737
    38 #define RESFILE_VERSION 20
     38#define RESFILE_VERSION 21
    3939
    4040bool StaticResource::checkKyraDat() {
    4141        Common::File kyraDat;
     
    241241
    242242                // Ingame
    243243                { k2IngamePakFiles, kStringList, "I_PAKFILES.TXT" },
    244                 { k2IngameSfxFiles, kStringList, "I_SFXFILES.TXT" },
    245                 { k2IngameSfxIndex, kRawData, "I_SFXINDEX.TRA" },
     244                { k2IngameSfxFiles, kStringList, "I_SFXFILES.TRA" },
     245                { k2IngameSfxIndex, kRawData, "I_SFXINDEX.MAP" },
    246246                { k2IngameTracks, kStringList, "I_TRACKS.TRA" },
    247247                { k2IngameCDA, kRawData, "I_TRACKS.CDA" },
     248                { k2IngameTalkObjIndex, kRawData, "I_TALKOBJECTS.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        _ingameTalkObjIndex = (const uint16*) _staticres->loadRawData(k2IngameTalkObjIndex, _ingameTalkObjIndexSize);
     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
     
    14941498} // End of namespace Kyra
    14951499
    14961500
     1501
  • 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(&_ingameTalkObjIndex[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];
    347         char TLKFilename[13];
    348514        char ENDFilename[13];
    349515
    350516        strcpy(STAFilename, object.filename);
    351         strcpy(TLKFilename, object.filename);
     517        strcpy(_TLKFilename, object.filename);
    352518        strcpy(ENDFilename, object.filename);
    353519
    354520        strcpy(STAFilename + 4, "_STA.TIM");
    355         strcpy(TLKFilename + 4, "_TLK.TIM");
     521        strcpy(_TLKFilename + 4, "_TLK.TIM");
    356522        strcpy(ENDFilename + 4, "_END.TIM");
    357523
    358         _currentTalkSections.STATim = loadTIMFile(STAFilename, NULL, 0);
    359         _currentTalkSections.TLKTim = loadTIMFile(TLKFilename, NULL, 0);
    360         _currentTalkSections.ENDTim = loadTIMFile(ENDFilename, NULL, 0);
     524        _currentTalkSections.STATim = tim_loadFile(STAFilename, NULL, 0);
     525        _currentTalkSections.TLKTim = tim_loadFile(_TLKFilename, NULL, 0);
     526        _currentTalkSections.ENDTim = tim_loadFile(ENDFilename, NULL, 0);
    361527
    362528        if (object.scriptId != -1) {
    363529                _specialSceneScriptStateBackup[object.scriptId] = _specialSceneScriptState[object.scriptId];
    364530                _specialSceneScriptState[object.scriptId] = 1;
    365531        }
    366532
    367         /*if (_currentTalkObject.STATim) {
     533        if (_currentTalkSections.STATim) {
    368534                _objectChatFinished = false;
    369535                while (!_objectChatFinished) {
    370                         processTalkObject(_currentTalkObject.STATim, 0);
     536                        tim_processSequence(_currentTalkSections.STATim, 0);
    371537                        if (_chatText)
    372538                                updateWithText();
    373539                        else
    374540                                update();
    375541                }
    376         }*/
     542        }
    377543}
    378544
    379 void KyraEngine_v2::deinitTalkObject(int initObject) {
    380         TalkObject &object = _talkObjectList[initObject];
     545void KyraEngine_v2::deinitTalkObject(int index) {
     546        TalkObject &object = _talkObjectList[index];
    381547
    382         /*if (_currentTalkObject.ENDTim) {
     548        if (_currentTalkSections.ENDTim) {
    383549                _objectChatFinished = false;
    384550                while (!_objectChatFinished) {
    385                         processTalkObject(_currentTalkObject.ENDTim, 0);
     551                        tim_processSequence(_currentTalkSections.ENDTim, 0);
    386552                        if (_chatText)
    387553                                updateWithText();
    388554                        else
    389555                                update();
    390556                }
    391         }*/
     557        }
    392558
    393559        if (object.scriptId != -1) {
    394560                _specialSceneScriptState[object.scriptId] = _specialSceneScriptStateBackup[object.scriptId];
    395561        }
    396562
    397563        if (_currentTalkSections.STATim != NULL) {
    398                 freeTIM(_currentTalkSections.STATim);
     564                tim_releaseBuffer(_currentTalkSections.STATim);
    399565                _currentTalkSections.STATim = NULL;
    400566        }
    401567
    402568        if (_currentTalkSections.TLKTim != NULL) {
    403                 freeTIM(_currentTalkSections.TLKTim);
     569                tim_releaseBuffer(_currentTalkSections.TLKTim);
    404570                _currentTalkSections.TLKTim = NULL;
    405571        }
    406572
    407573        if (_currentTalkSections.ENDTim != NULL) {
    408                 freeTIM(_currentTalkSections.ENDTim);
     574                tim_releaseBuffer(_currentTalkSections.ENDTim);
    409575                _currentTalkSections.ENDTim = NULL;
    410576        }
    411577}
    412578
    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         }
     579void KyraEngine_v2::npcChatSequence(const char *str, int objectId, int vocHigh, int vocLow) {
     580        _chatText = str;
     581        _chatObject = objectId;
     582        objectChatInit(str, objectId, vocHigh, vocLow);
    419583
    420         int32 formBlockSize = file.getFORMBlockSize();
    421         if (formBlockSize == -1) {
    422                 error("No FORM chunk found in file: '%s'", filename);
    423                 return NULL;
    424         }
     584        if (!_currentTalkSections.TLKTim)
     585                _currentTalkSections.TLKTim = tim_loadFile(_TLKFilename, 0, 0);
    425586
    426         if (formBlockSize < 20) {
    427                 return NULL;
    428         }
     587        setNextIdleAnimTimer();
     588       
     589        uint32 ct = chatCalcDuration(str);
     590        uint32 time = _system->getMillis();
     591        _chatEndTime =  time + (3 + ct) * _tickLength;
     592        uint32 chatAnimEndTime = time + (3 + (ct >> 1)) * _tickLength;
    429593
    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;
     594        if (_chatVocHigh >= 0) {
     595                playVoice(_chatVocHigh, _chatVocLow);
     596                _chatVocHigh = _chatVocLow = -1;
    440597        }
    441598
    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;
     599        while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || _skipFlag)) {
     600                if (!speechEnabled() && chatAnimEndTime > _system->getMillis() || speechEnabled() && snd_voiceIsPlaying()) {
     601                        _objectChatFinished = false;
    449602
    450         _TIMBuffers.AVTLChunk = (uint16 *)(buffer + timHeader->AVTLOffset);
    451         _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
     603                        while (!_objectChatFinished && !_skipFlag) {           
     604                                if (_currentTalkSections.TLKTim)
     605                                        tim_processSequence(_currentTalkSections.TLKTim, 0);
     606                                else
     607                                        _objectChatFinished = false;
    452608
    453         if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
    454                 error("Couldn't load AVTL chunk from file: '%s'", filename);
    455                 return NULL;
     609                                updateWithText();
     610       
     611                                int inputFlag = checkInput(0);
     612                                removeInputTop();
     613                                if (inputFlag == 198 || inputFlag == 199) {
     614                                        //XXX
     615                                        _skipFlag = true;
     616                                        snd_stopVoice();
     617                                }
     618                                delay(10);
     619                        }
     620                        if (_currentTalkSections.TLKTim)
     621                                tim_o_abort(0);
     622                }
     623                updateWithText();
    456624        }
    457625
    458         _TIMBuffers.UnkChunk = (TIMStructUnk1 *)(buffer + timHeader->unkOffset);
     626        _skipFlag = false;
    459627
    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;
     628        if (_currentTalkSections.TLKTim) {
     629                tim_releaseBuffer(_currentTalkSections.TLKTim);
     630                _currentTalkSections.TLKTim = 0;
    466631        }
    467632
    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;
     633        _text->restoreScreen();
     634        _chatText = 0;
     635        _chatObject = -1;
     636        setNextIdleAnimTimer();
    477637}
    478638
    479 void KyraEngine_v2::freeTIM(byte *buffer) {
    480         TIMHeader *timHeader = (TIMHeader *)buffer;
    481 
    482         if (timHeader->deleteBufferFlag == 0xBABE) {
    483                 delete[] buffer;
    484         }
     639void KyraEngine_v2::setNewDlgIndex(int dlgIndex) {
     640        if (dlgIndex == _mainCharacter.dlgIndex)
     641                return;
     642        memset(_newSceneDlgState, 0, 32);
     643        for (int i = 0; i < 19; i++)
     644                memset(_conversationState[i], -1, 14);
     645        _npcTalkUNK = 0;
     646        _mainCharacter.dlgIndex = dlgIndex;
    485647}
    486648
    487649} // end of namespace Kyra
    488 
    489