Ticket #8797: dlgTim.patch

File dlgTim.patch, 37.2 KB (added by athrxx, 16 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(),
  • 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;
     
    632634        byte _messagePal[3];
    633635        int _msgUnk1;
    634636
     637        uint8 _configTextspeed;
     638
    635639        // chat
    636640        int _vocHigh;
    637641
     
    652656        void objectChatPrintText(const char *text, int object);
    653657        void objectChatProcess(const char *script);
    654658        void objectChatWaitToFinish();
    655         void initTalkObject(int initObject);
    656         void deinitTalkObject(int initObject);
    657659
     660        void startDialogue(int dlgIndex);
     661        void updateDlgBuffer();
     662        void loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2);
     663        void processDialogue(int dlgOffset, int vocH = 0, int csEntry = 0);
     664        void npcChatSequence(const char *str, int timId, int vocHigh = -1, int vocLow = -1);
     665        void setNewDlgIndex(int dlgIndex);
     666
     667        int _npcTalkChpIndex;
     668        int _npcTalkDlgIndex;   
     669        uint8 _newSceneDlgState[32];
     670        int8 **_conversationState;
     671        uint8 _npcTalkUNK;
     672        uint8 *_dlgBuffer;
     673
     674        // tim sequence
     675        void tim_setupOpcodes();
     676        byte* tim_loadFile(const char *filename, byte *buffer, int32 bufferSize);
     677        void tim_releaseBuffer(byte *buffer);
     678        void tim_processSequence(uint8 *timBuffer, int loop);
     679
     680        int tim_o_dummy_r0(uint8 *ptr);
     681        int tim_o_dummy_r1(uint8 *ptr);
     682        int tim_o_clearCmds2(uint8 *ptr);
     683        int tim_o_abort(uint8 *ptr);           
     684        int tim_o_selectcurrentCommandSet(uint8 *ptr);
     685        int tim_o_deleteBuffer(uint8 *ptr);
     686        int tim_o_refreshTimers(uint8 *ptr);
     687        int tim_o_execSubOpcode(uint8 *ptr);
     688        int tim_o_initActiveSub(uint8 *ptr);
     689        int tim_o_resetActiveSub(uint8 *ptr);
     690        int tim_o_printTalkText(uint8 *ptr);
     691        int tim_o_updateSceneAnim(uint8 *ptr);
     692        int tim_o_resetChat(uint8 *ptr);
     693        int tim_o_playSoundEffect(uint8 *ptr);
     694
     695        typedef int (KyraEngine_v2::*TimOpc)(uint8 *ptr);
     696        TimOpc * _timOpcodes;
     697
     698        struct TIMHeader {
     699                uint16 deleteBufferFlag;
     700                int16 unkFlag;
     701                int16 unkFlag2;
     702                int16 cmdsOffset;
     703                int16 unkOffset2;
     704                int16 AVTLOffset;
     705                int16 TEXTOffset;
     706        };
     707
     708        struct Cmds {
     709                uint8 *dataPtr;
     710                uint32 unk_2;
     711                uint32 timer1;
     712                uint32 timer2;
     713                uint8 *backupPtr;
     714                uint8 *AVTLSubChunk;
     715        };
     716
     717        struct TIMBuffers {
     718                uint8 *AVTLChunk;
     719                uint8 *TEXTChunk;
     720                uint8 *offsUnkFlag2;
     721                uint8 *offsUnkFlag;
     722                int16 currentEntry;
     723                int16 unk_12;
     724                Cmds *currentCommandSet;
     725                uint8 *unkCmds;
     726        };
     727        TIMBuffers _TIMBuffers;
     728
     729        const char *_timChatText;
     730        int _timChatObject;
     731
    658732        // sound
    659733        int _oldTalkFile;
    660734        int _currentTalkFile;
     
    689763        void delay(uint32 millis, bool updateGame = false, bool isMainLoop = false);
    690764
    691765        // Talk object handling
     766        void initTalkObject(int index);
     767        void deinitTalkObject(int index);
     768
    692769        struct TalkObject {
    693770                char filename[13];
    694771                int8 scriptId;
     
    697774        };
    698775        TalkObject *_talkObjectList;
    699776
    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 
    725777        struct TalkSections {
    726778                byte *STATim;
    727779                byte *TLKTim;
     
    730782        TalkSections _currentTalkSections;
    731783
    732784        bool _objectChatFinished;
    733         byte *loadTIMFile(const char *filename, byte *buffer, int32 bufferSize);
    734         void freeTIM(byte *buffer);
    735785
    736786        // ingame static sequence handling
    737787        void seq_makeBookOrCauldronAppear(int type);
     
    809859        int o2_setSpecialSceneScriptRunTime(ScriptState *script);
    810860        int o2_defineSceneAnim(ScriptState *script);
    811861        int o2_updateSceneAnim(ScriptState *script);
     862        int o2_useItemOnMainChar(ScriptState *script);
     863        int o2_startDialogue(ScriptState *script);
     864        int o2_setupDialogue(ScriptState *script);
     865        int o2_getDlgIndex(ScriptState *script);
    812866        int o2_defineRoom(ScriptState *script);
    813867        int o2_objectChat(ScriptState *script);
     868        int o2_getColorCodeFlag1(ScriptState *script);
     869        int o2_setColorCodeFlag1(ScriptState *script);
     870        int o2_getColorCodeFlag2(ScriptState *script);
     871        int o2_setColorCodeFlag2(ScriptState *script);
    814872        int o2_countItemInstances(ScriptState *script);
    815873        int o2_initObject(ScriptState *script);
     874        int o2_npcChat(ScriptState *script);
    816875        int o2_deinitObject(ScriptState *script);
    817876        int o2_makeBookOrCauldronAppear(ScriptState *script);
    818877        int o2_setSpecialSceneScriptState(ScriptState *script);
     
    896955        int _ingameSoundIndexSize;
    897956        const char *const *_sequenceStrings;
    898957        int _sequenceStringsSize;
     958        const uint16 *_ingameTimIndex;
     959        int _ingameTimIndexSize;
     960        const char *const *_ingameTimJpStr;
     961        int _ingameTimJpStrSize;
    899962        uint8 *_demoShapeDefs;
    900963        int _sequenceStringsDuration[33];
    901964
     
    919982
    920983        Sequence *_sequences;
    921984        NestedSequence *_nSequences;
     985
     986        // these are used whenever the color code has to be entered
     987        int _colorCodeFlag1;
     988        int _colorCodeFlag2;
    922989};
    923990
    924991} // end of namespace Kyra
  • resource.h

     
    218218        k2IngameSfxIndex,
    219219        k2IngameTracks,
    220220        k2IngameCDA,
     221        k2IngameTimIndex,
     222        k2IngameTimJpStrings,
    221223
    222224        kMaxResIDs
    223225};
  • 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;
  • 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));
  • 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
     35
     36
     37byte *KyraEngine_v2::tim_loadFile(const char *filename, byte *buffer, int32 bufferSize) {
     38        ScriptFileParser file(filename, _res);
     39        if (!file) {
     40                error("Couldn't open script file '%s'", filename);
     41                return NULL;
     42        }
     43
     44        int32 formBlockSize = file.getFORMBlockSize();
     45        if (formBlockSize == -1) {
     46                error("No FORM chunk found in file: '%s'", filename);
     47                return NULL;
     48        }
     49
     50        if (formBlockSize < 20) {
     51                return NULL;
     52        }
     53
     54        formBlockSize += sizeof(TIMHeader) +  10 * (sizeof(Cmds) + 120);
     55
     56        TIMHeader *timHeader;
     57        if (buffer == NULL || bufferSize < formBlockSize) {
     58                buffer = new byte[formBlockSize];
     59                timHeader = (TIMHeader *)buffer;
     60                timHeader->deleteBufferFlag = 0xBABE;
     61        } else {
     62                timHeader = (TIMHeader *)buffer;
     63                timHeader->deleteBufferFlag = 0x0;
     64        }
     65
     66        int32 chunkSize = file.getIFFBlockSize(AVTL_CHUNK);
     67        timHeader->unkFlag = -1;
     68        timHeader->unkFlag2 = 0;
     69        timHeader->cmdsOffset = sizeof(TIMHeader);
     70        timHeader->unkOffset2 = timHeader->cmdsOffset + 10 * sizeof(Cmds);
     71        timHeader->AVTLOffset = timHeader->unkOffset2 + 120;
     72        timHeader->TEXTOffset = timHeader->AVTLOffset + chunkSize;
     73
     74        _TIMBuffers.AVTLChunk = buffer + timHeader->AVTLOffset;
     75        _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
     76
     77        if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
     78                error("Couldn't load AVTL chunk from file: '%s'", filename);
     79                return NULL;
     80        }
     81
     82        _TIMBuffers.currentCommandSet = (Cmds *)(buffer + timHeader->cmdsOffset);
     83
     84        for (int i = 0; i < 10; i++) {
     85                _TIMBuffers.currentCommandSet[i].dataPtr = 0;
     86                _TIMBuffers.currentCommandSet[i].unk_2 = 0;
     87                _TIMBuffers.currentCommandSet[i].AVTLSubChunk = &_TIMBuffers.AVTLChunk[READ_LE_UINT16(&_TIMBuffers.AVTLChunk[i << 1]) << 1];
     88                _TIMBuffers.currentCommandSet[i].timer1 = 0;
     89                _TIMBuffers.currentCommandSet[i].timer2 = 0;
     90        }
     91
     92        chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
     93        if (chunkSize > 0) {
     94                if (!file.loadIFFBlock(TEXT_CHUNK, _TIMBuffers.TEXTChunk, chunkSize)) {
     95                        error("Couldn't load TEXT chunk from file: '%s'", filename);
     96                        return NULL;
     97                }
     98        }
     99
     100        return buffer;
     101}
     102
     103void KyraEngine_v2::tim_releaseBuffer(byte *buffer) {
     104        TIMHeader *timHeader = (TIMHeader *)buffer;
     105        if (timHeader->deleteBufferFlag == 0xBABE)
     106                delete[] buffer;
     107}
     108
     109void KyraEngine_v2::tim_processSequence(uint8 *timBuffer, int loop) {
     110        if (!timBuffer)
     111                return;
     112
     113        TIMHeader *hdr = (TIMHeader*) timBuffer;
     114        _TIMBuffers.offsUnkFlag = (uint8*) &hdr->unkFlag;
     115        _TIMBuffers.offsUnkFlag2 = (uint8*) &hdr->unkFlag2;
     116        _TIMBuffers.currentCommandSet = (Cmds*) (timBuffer + hdr->cmdsOffset);
     117        _TIMBuffers.unkCmds = timBuffer + hdr->unkOffset2;
     118        _TIMBuffers.AVTLChunk = timBuffer + hdr->AVTLOffset;
     119        _TIMBuffers.TEXTChunk = timBuffer + hdr->TEXTOffset;
     120
     121        if (!_TIMBuffers.currentCommandSet->dataPtr) {
     122                _TIMBuffers.currentCommandSet->dataPtr = _TIMBuffers.currentCommandSet->AVTLSubChunk;
     123                _TIMBuffers.currentCommandSet->timer1 = _system->getMillis();
     124                _TIMBuffers.currentCommandSet->timer2 = _system->getMillis();
     125        }
     126
     127        do {
     128                _TIMBuffers.currentEntry = 0;
     129
     130                while (_TIMBuffers.currentEntry < 10) {
     131                        Cmds *s = &_TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry];
     132                        if ((int)READ_LE_UINT16(_TIMBuffers.offsUnkFlag) !=  -1)
     133                                (this->*_timOpcodes[28])(_TIMBuffers.offsUnkFlag2);
     134
     135                        bool loop = true;
     136
     137                        while (s->dataPtr && s->timer2 <= _system->getMillis() && loop) {
     138                                uint8 cmd = s->dataPtr[4];
     139                                hdr->unkFlag2 = cmd;
     140                                uint8 *para = &s->dataPtr[6];
     141
     142                                switch((this->*_timOpcodes[cmd])(para)) {
     143                                        case -3:
     144                                                WRITE_LE_UINT16(_TIMBuffers.offsUnkFlag, _TIMBuffers.currentEntry);
     145                                                _TIMBuffers.unk_12 = -1;
     146                                                break;
     147
     148                                        case -2:
     149                                                loop = false;
     150                                                break;
     151
     152                                        case -1:
     153                                                loop = 0;
     154                                                loop = false;
     155                                                _TIMBuffers.currentEntry = 11;
     156                                                break;
     157                                       
     158                                        case 22:
     159                                                s->backupPtr = 0;
     160                                                break;
     161
     162                                        default:
     163                                                break;
     164                                }                               
     165
     166                                if (s) {
     167                                        if (s->dataPtr) {
     168                                                s->dataPtr += (READ_LE_UINT16(s->dataPtr) * 2);
     169                                                s->timer1 = s->timer2;
     170                                                s->timer2 += (READ_LE_UINT16(s->dataPtr + 2) * _tickLength);
     171                                        }
     172                                }
     173                        }
     174
     175                        _TIMBuffers.currentEntry++;
     176                }
     177        } while (loop == 1);   
     178
     179}
     180
     181int KyraEngine_v2::tim_o_dummy_r0(uint8 *ptr) {
     182        return 0;
     183}
     184
     185int KyraEngine_v2::tim_o_dummy_r1(uint8 *ptr) {
     186        return 1;
     187}
     188
     189int KyraEngine_v2::tim_o_clearCmds2(uint8 *ptr) {
     190        for (int i = 1; i < 10; i++)
     191                memset(&_TIMBuffers.unkCmds[i], 0, 12);
     192        _TIMBuffers.currentCommandSet[0].dataPtr = _TIMBuffers.currentCommandSet[0].AVTLSubChunk;
     193        _TIMBuffers.currentCommandSet[0].timer1 = _system->getMillis();
     194        return 1;
     195}
     196
     197int KyraEngine_v2::tim_o_abort(uint8 *ptr) {
     198        _TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry].dataPtr = 0;
     199        if(!_TIMBuffers.currentEntry)
     200                _objectChatFinished = true;
     201        return -2;     
     202}
     203
     204
     205int KyraEngine_v2::tim_o_selectcurrentCommandSet(uint8 *ptr) {
     206        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk ?
     207        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk : &_TIMBuffers.AVTLChunk[_TIMBuffers.AVTLChunk[READ_LE_UINT16(ptr) << 1] << 1];
     208        return 1;
     209}
     210
     211int KyraEngine_v2::tim_o_deleteBuffer(uint8 *ptr) {
     212        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
     213        return 1;
     214}
     215
     216int KyraEngine_v2::tim_o_refreshTimers(uint8 *ptr) {
     217        for (int i = 1; i < 10; i++) {
     218                if (_TIMBuffers.currentCommandSet[i].dataPtr)
     219                        _TIMBuffers.currentCommandSet[i].timer2 = _system->getMillis();
     220        }
     221
     222        return 1;
     223}
     224
     225int KyraEngine_v2::tim_o_execSubOpcode(uint8 *ptr) {
     226        return (this->*_timOpcodes[30 + READ_LE_UINT16(ptr)])(ptr + 2);
     227}
     228
     229int KyraEngine_v2::tim_o_initActiveSub(uint8 *ptr) {
     230        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk;
     231        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = _system->getMillis();
     232        return 1;
     233}
     234
     235int KyraEngine_v2::tim_o_resetActiveSub(uint8 *ptr) {
     236        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
     237        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = 0;
     238        _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = 0;
     239        return 1;
     240}
     241
     242int KyraEngine_v2::tim_o_printTalkText(uint8 *ptr) {
     243        _chatText = _timChatText = (const char*) _TIMBuffers.TEXTChunk + (READ_LE_UINT16(ptr) << 1);
     244        _chatObject = _timChatObject = READ_LE_UINT16(ptr + 2);
     245       
     246        if (_flags.lang == Common::JA_JPN) {
     247                for (int i = 0; i < _ingameTimJpStrSize; i += 2) {
     248                        if (!scumm_stricmp(_timChatText, _ingameTimJpStr[i]))
     249                                _chatText = _ingameTimJpStr[i + 1];
     250                }               
     251        }
     252        objectChatInit(_chatText, _timChatObject);
     253        return 0;
     254}
     255
     256int KyraEngine_v2::tim_o_updateSceneAnim(uint8 *ptr) {
     257        updateSceneAnim(READ_LE_UINT16(ptr + 2), READ_LE_UINT16(ptr));
     258        return 0;
     259}
     260
     261int KyraEngine_v2::tim_o_resetChat(uint8 *ptr) {
     262        _text->restoreScreen();
     263        _chatText = 0;
     264        _chatObject = -1;
     265        _timChatText = 0;
     266        _timChatObject = -1;
     267        return 0;
     268}
     269
     270int KyraEngine_v2::tim_o_playSoundEffect(uint8 *ptr) {
     271        snd_playSoundEffect(READ_LE_UINT16(ptr));
     272        return 0;
     273}
     274
     275void KyraEngine_v2::tim_setupOpcodes() {
     276        static const TimOpc Opcodes[] = {
     277                &KyraEngine_v2::tim_o_clearCmds2,
     278                &KyraEngine_v2::tim_o_abort,
     279                &KyraEngine_v2::tim_o_dummy_r0,
     280                &KyraEngine_v2::tim_o_dummy_r0,
     281                &KyraEngine_v2::tim_o_selectcurrentCommandSet,
     282                &KyraEngine_v2::tim_o_deleteBuffer,
     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_dummy_r0,
     299                &KyraEngine_v2::tim_o_dummy_r0,
     300                &KyraEngine_v2::tim_o_refreshTimers,
     301                &KyraEngine_v2::tim_o_dummy_r1,
     302                &KyraEngine_v2::tim_o_execSubOpcode,
     303                &KyraEngine_v2::tim_o_initActiveSub,
     304                &KyraEngine_v2::tim_o_resetActiveSub,
     305                &KyraEngine_v2::tim_o_dummy_r1,
     306                &KyraEngine_v2::tim_o_dummy_r1,
     307                &KyraEngine_v2::tim_o_printTalkText,
     308                &KyraEngine_v2::tim_o_updateSceneAnim,
     309                &KyraEngine_v2::tim_o_resetChat,
     310                &KyraEngine_v2::tim_o_playSoundEffect,
     311        };
     312
     313        _timOpcodes = (TimOpc*) (Opcodes);
     314}
     315
     316} // end of namespace Kyra
     317
  • 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 >= NUM_VOC_HANDLES)
     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 < NUM_VOC_HANDLES; 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 < NUM_VOC_HANDLES; h++) {
     101                if (_mixer->isSoundHandleActive(_vocHandles[h]))
     102                        res = true;
     103        }
     104        return res;
    94105}
    95106
    96107#pragma mark -
  • 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
     
    191193private:
    192194        const AudioDataStruct *_soundDataList;
    193195        Audio::AudioStream *_currentVocFile;
    194         Audio::SoundHandle _vocHandle;
     196        Audio::SoundHandle _vocHandles[NUM_VOC_HANDLES];
    195197
    196198        struct SpeechCodecs {
    197199                const char *fileext;
  • staticres.cpp

     
    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
  • 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 Suffix_Talkie[] = "EFG";
     374        static const char Suffix_Towns[] = "G  J";
     375        const char * suffix = _flags.isTalkie ? Suffix_Talkie : Suffix_Towns;
     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        bool running = true;
     591        uint32 ct = chatCalcDuration(str);
     592        uint32 time = _system->getMillis();
     593        _chatEndTime =  time + (3 + ct) * _tickLength;
     594        uint32 chatAnimEndTime = time + (3 + (ct >> 1)) * _tickLength;
    429595
    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;
     596        if (_chatVocHigh >= 0) {
     597                playVoice(_chatVocHigh, _chatVocLow);
     598                _chatVocHigh = _chatVocLow = -1;
    440599        }
    441600
    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;
     601        while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || _skipFlag)) {
     602                if (chatAnimEndTime > _system->getMillis()) {
     603                        _objectChatFinished = false;
    449604
    450         _TIMBuffers.AVTLChunk = (uint16 *)(buffer + timHeader->AVTLOffset);
    451         _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
     605                        while (!_objectChatFinished && !_skipFlag) {           
     606                                if (_currentTalkSections.TLKTim)
     607                                        tim_processSequence(_currentTalkSections.TLKTim, 0);
     608                                else
     609                                        _objectChatFinished = false;
    452610
    453         if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
    454                 error("Couldn't load AVTL chunk from file: '%s'", filename);
    455                 return NULL;
     611                                updateWithText();
     612       
     613                                int inputFlag = checkInput(0);
     614                                removeInputTop();
     615                                if (inputFlag == 198 || inputFlag == 199) {
     616                                        //XXX
     617                                        _skipFlag = true;
     618                                        snd_stopVoice();
     619                                }
     620                                delay(10);
     621                        }
     622                        if (_currentTalkSections.TLKTim)
     623                                tim_o_abort(0);
     624                }
     625                updateWithText();
    456626        }
    457627
    458         _TIMBuffers.UnkChunk = (TIMStructUnk1 *)(buffer + timHeader->unkOffset);
     628        _skipFlag = false;
    459629
    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;
     630        if (_currentTalkSections.TLKTim) {
     631                tim_releaseBuffer(_currentTalkSections.TLKTim);
     632                _currentTalkSections.TLKTim = 0;
    466633        }
    467 
    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;
     634snd_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
    487 } // end of namespace Kyra
    488 
    489 
     651} // end of namespace Kyra
     652 No newline at end of file