aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorFlorian Kagerer2008-02-17 02:06:04 +0000
committerFlorian Kagerer2008-02-17 02:06:04 +0000
commit753536fa61119a20a5e0d0e9b00790593cd5190e (patch)
tree336fe694314c829ff8c5da1c515c27b506eb5b92 /engines
parent9146cf360301f5bd1822a111c9e49b8e8f497211 (diff)
downloadscummvm-rg350-753536fa61119a20a5e0d0e9b00790593cd5190e.tar.gz
scummvm-rg350-753536fa61119a20a5e0d0e9b00790593cd5190e.tar.bz2
scummvm-rg350-753536fa61119a20a5e0d0e9b00790593cd5190e.zip
committing patch 1891492 : dialogue (dlg/tim) support for HoF
- talking to NPCs is now possible. - Zanthia's talks when entering a new scene for the first time now work - using items on Zanthia is now possible. svn-id: r30886
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/kyra_v2.cpp41
-rw-r--r--engines/kyra/kyra_v2.h163
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/resource.h3
-rw-r--r--engines/kyra/scene_v2.cpp21
-rw-r--r--engines/kyra/script_v2.cpp69
-rw-r--r--engines/kyra/sequences_tim.cpp315
-rw-r--r--engines/kyra/sound.cpp30
-rw-r--r--engines/kyra/sound.h12
-rw-r--r--engines/kyra/sound_towns.cpp10
-rw-r--r--engines/kyra/staticres.cpp13
-rw-r--r--engines/kyra/text_v2.cpp318
12 files changed, 840 insertions, 156 deletions
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 19fa30e3de..546fd6d954 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -86,13 +86,27 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngi
_chatObject = -1;
_lastIdleScript = -1;
+ _timChatText = 0;
+ _timChatObject = -1;
+
_currentTalkSections.STATim = NULL;
_currentTalkSections.TLKTim = NULL;
_currentTalkSections.ENDTim = NULL;
_invWsa.wsa = 0;
+ _colorCodeFlag1 = 0;
+ _colorCodeFlag2 = -1;
+
memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
+
+ _dlgBuffer = 0;
+ _conversationState = new int8*[19];
+ for (int i = 0; i < 19; i++)
+ _conversationState[i] = new int8[14];
+ _npcTalkChpIndex = _npcTalkDlgIndex = -1;
+ _mainCharacter.dlgIndex = 0;
+ setNewDlgIndex(-1);
}
KyraEngine_v2::~KyraEngine_v2() {
@@ -109,6 +123,12 @@ KyraEngine_v2::~KyraEngine_v2() {
_text = 0;
delete _debugger;
delete _invWsa.wsa;
+
+ if (_dlgBuffer)
+ delete [] _dlgBuffer;
+ for (int i = 0; i < 19; i++)
+ delete [] _conversationState[i];
+ delete [] _conversationState;
}
Movie *KyraEngine_v2::createWSAMovie() {
@@ -155,6 +175,8 @@ int KyraEngine_v2::init() {
if (_flags.isDemo)
return 0;
+ tim_setupOpcodes();
+
_mouseSHPBuf = _res->fileData("PWGMOUSE.SHP", 0);
assert(_mouseSHPBuf);
@@ -1877,12 +1899,12 @@ void KyraEngine_v2::setupOpcodeTable() {
Opcode(o2_updateSceneAnim),
OpcodeUnImpl(),
// 0x74
+ Opcode(o2_useItemOnMainChar),
+ Opcode(o2_startDialogue),
OpcodeUnImpl(),
- OpcodeUnImpl(),
- OpcodeUnImpl(),
- OpcodeUnImpl(),
+ Opcode(o2_setupDialogue),
// 0x78
- OpcodeUnImpl(),
+ Opcode(o2_getDlgIndex),
Opcode(o2_defineRoom),
OpcodeUnImpl(),
OpcodeUnImpl(),
@@ -1894,18 +1916,18 @@ void KyraEngine_v2::setupOpcodeTable() {
// 0x80
Opcode(o2_objectChat),
OpcodeUnImpl(),
- OpcodeUnImpl(),
- OpcodeUnImpl(),
+ Opcode(o2_getColorCodeFlag1),
+ Opcode(o2_setColorCodeFlag1),
// 0x84
- OpcodeUnImpl(),
- OpcodeUnImpl(),
+ Opcode(o2_getColorCodeFlag2),
+ Opcode(o2_setColorCodeFlag2),
OpcodeUnImpl(),
OpcodeUnImpl(),
// 0x88
Opcode(o2_countItemInstances),
OpcodeUnImpl(),
Opcode(o2_initObject),
- OpcodeUnImpl(),
+ Opcode(o2_npcChat),
// 0x8c
Opcode(o2_deinitObject),
OpcodeUnImpl(),
@@ -1972,3 +1994,4 @@ void KyraEngine_v2::setupOpcodeTable() {
} // end of namespace Kyra
+
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index 54570b97cd..f35efa1d8d 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -495,6 +495,8 @@ protected:
void runSceneScript6();
void runSceneScript7();
+ void sceneStartupChat();
+
void initSceneAnims(int unk1);
void initSceneScreen(int unk1);
@@ -589,7 +591,7 @@ protected:
// character
struct Character {
uint16 sceneId;
- uint16 unk2;
+ uint16 dlgIndex;
uint8 height;
uint8 facing;
uint16 animFrame;
@@ -652,8 +654,100 @@ protected:
void objectChatPrintText(const char *text, int object);
void objectChatProcess(const char *script);
void objectChatWaitToFinish();
- void initTalkObject(int initObject);
- void deinitTalkObject(int initObject);
+
+ void startDialogue(int dlgIndex);
+ void updateDlgBuffer();
+ void loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2);
+ void processDialogue(int dlgOffset, int vocH = 0, int csEntry = 0);
+ void npcChatSequence(const char *str, int objectId, int vocHigh = -1, int vocLow = -1);
+ void setNewDlgIndex(int dlgIndex);
+
+ int _npcTalkChpIndex;
+ int _npcTalkDlgIndex;
+ uint8 _newSceneDlgState[32];
+ int8 **_conversationState;
+ uint8 _npcTalkUNK;
+ uint8 *_dlgBuffer;
+
+ // tim sequence
+ void tim_setupOpcodes();
+ uint8 *tim_loadFile(const char *filename, uint8 *buffer, int32 bufferSize);
+ void tim_releaseBuffer(uint8 *buffer);
+ void tim_processSequence(uint8 *timBuffer, int loop);
+
+ int tim_o_dummy_r0(uint8 *ptr);
+ int tim_o_dummy_r1(uint8 *ptr);
+ int tim_o_clearCmds2(uint8 *ptr);
+ int tim_o_abort(uint8 *ptr);
+ int tim_o_selectcurrentCommandSet(uint8 *ptr);
+ int tim_o_deleteBuffer(uint8 *ptr);
+ int tim_o_refreshTimers(uint8 *ptr);
+ int tim_o_execSubOpcode(uint8 *ptr);
+ int tim_o_initActiveSub(uint8 *ptr);
+ int tim_o_resetActiveSub(uint8 *ptr);
+ int tim_o_printTalkText(uint8 *ptr);
+ int tim_o_updateSceneAnim(uint8 *ptr);
+ int tim_o_resetChat(uint8 *ptr);
+ int tim_o_playSoundEffect(uint8 *ptr);
+
+ typedef int (KyraEngine_v2::*TimOpc)(uint8 *ptr);
+ const TimOpc * _timOpcodes;
+
+ struct TIMHeader {
+ uint16 deleteBufferFlag;
+ int16 unkFlag;
+ int16 unkFlag2;
+ int16 cmdsOffset;
+ int16 unkOffset2;
+ int16 AVTLOffset;
+ int16 TEXTOffset;
+ };
+
+ struct Cmds {
+ uint8 *dataPtr;
+ uint32 unk_2;
+ uint32 timer1;
+ uint32 timer2;
+ uint8 *backupPtr;
+ uint8 *AVTLSubChunk;
+ };
+
+ struct TIMBuffers {
+ uint8 *AVTLChunk;
+ uint8 *TEXTChunk;
+ uint8 *offsUnkFlag2;
+ uint8 *offsUnkFlag;
+ int16 currentEntry;
+ int16 unk_12;
+ Cmds *currentCommandSet;
+ uint8 *unkCmds;
+ };
+ TIMBuffers _TIMBuffers;
+
+ const char *_timChatText;
+ int _timChatObject;
+
+ // Talk object handling
+ void initTalkObject(int index);
+ void deinitTalkObject(int index);
+
+ struct TalkObject {
+ char filename[13];
+ int8 scriptId;
+ int16 x, y;
+ int8 color;
+ };
+ TalkObject *_talkObjectList;
+
+ struct TalkSections {
+ uint8 *STATim;
+ uint8 *TLKTim;
+ uint8 *ENDTim;
+ };
+ TalkSections _currentTalkSections;
+
+ char _TLKFilename[13];
+ bool _objectChatFinished;
// sound
int _oldTalkFile;
@@ -688,51 +782,6 @@ protected:
// delay
void delay(uint32 millis, bool updateGame = false, bool isMainLoop = false);
- // Talk object handling
- struct TalkObject {
- char filename[13];
- int8 scriptId;
- int16 x, y;
- int8 color;
- };
- TalkObject *_talkObjectList;
-
- struct TIMHeader {
- uint16 deleteBufferFlag;
- int16 unkFlag;
- int16 unkFlag2;
- int16 unkOffset;
- int16 unkOffset2;
- int16 AVTLOffset;
- int16 TEXTOffset;
- };
-
- struct TIMStructUnk1 {
- uint16 unk_0;
- uint16 unk_2;
- uint16 unk_4;
- uint16 unk_8;
- uint16 *unk_20;
- };
-
- struct TIMBuffers {
- uint16 *AVTLChunk;
- byte *TEXTChunk;
- TIMStructUnk1 *UnkChunk;
- };
- TIMBuffers _TIMBuffers;
-
- struct TalkSections {
- byte *STATim;
- byte *TLKTim;
- byte *ENDTim;
- };
- TalkSections _currentTalkSections;
-
- bool _objectChatFinished;
- byte *loadTIMFile(const char *filename, byte *buffer, int32 bufferSize);
- void freeTIM(byte *buffer);
-
// ingame static sequence handling
void seq_makeBookOrCauldronAppear(int type);
void seq_makeBookAppear();
@@ -809,10 +858,19 @@ protected:
int o2_setSpecialSceneScriptRunTime(ScriptState *script);
int o2_defineSceneAnim(ScriptState *script);
int o2_updateSceneAnim(ScriptState *script);
+ int o2_useItemOnMainChar(ScriptState *script);
+ int o2_startDialogue(ScriptState *script);
+ int o2_setupDialogue(ScriptState *script);
+ int o2_getDlgIndex(ScriptState *script);
int o2_defineRoom(ScriptState *script);
int o2_objectChat(ScriptState *script);
+ int o2_getColorCodeFlag1(ScriptState *script);
+ int o2_setColorCodeFlag1(ScriptState *script);
+ int o2_getColorCodeFlag2(ScriptState *script);
+ int o2_setColorCodeFlag2(ScriptState *script);
int o2_countItemInstances(ScriptState *script);
int o2_initObject(ScriptState *script);
+ int o2_npcChat(ScriptState *script);
int o2_deinitObject(ScriptState *script);
int o2_makeBookOrCauldronAppear(ScriptState *script);
int o2_setSpecialSceneScriptState(ScriptState *script);
@@ -896,6 +954,10 @@ protected:
int _ingameSoundIndexSize;
const char *const *_sequenceStrings;
int _sequenceStringsSize;
+ const uint16 *_ingameTalkObjIndex;
+ int _ingameTalkObjIndexSize;
+ const char *const *_ingameTimJpStr;
+ int _ingameTimJpStrSize;
uint8 *_demoShapeDefs;
int _sequenceStringsDuration[33];
@@ -919,6 +981,10 @@ protected:
Sequence *_sequences;
NestedSequence *_nSequences;
+
+ // these are used whenever the color code has to be entered
+ int _colorCodeFlag1;
+ int _colorCodeFlag2;
};
} // end of namespace Kyra
@@ -926,3 +992,4 @@ protected:
#endif
+
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index e631ddf5dd..bce7364cc8 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
script_v2.o \
script.o \
seqplayer.o \
+ sequences_tim.o \
sequences_v1.o \
sequences_v2.o \
sound_adlib.o \
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 72b4414ccc..cde5df4bf2 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -218,6 +218,8 @@ enum kKyraResources {
k2IngameSfxIndex,
k2IngameTracks,
k2IngameCDA,
+ k2IngameTalkObjIndex,
+ k2IngameTimJpStrings,
kMaxResIDs
};
@@ -328,3 +330,4 @@ private:
#endif
+
diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp
index 63664c91d8..1eee6fe670 100644
--- a/engines/kyra/scene_v2.cpp
+++ b/engines/kyra/scene_v2.cpp
@@ -243,7 +243,7 @@ void KyraEngine_v2::enterNewSceneUnk2(int unk1) {
if (!unk1) {
runSceneScript4(0);
- //XXX sub_27158
+ sceneStartupChat();
}
_unk4 = 0;
@@ -499,6 +499,22 @@ void KyraEngine_v2::runSceneScript7() {
_screen->_curPage = oldPage;
}
+void KyraEngine_v2::sceneStartupChat() {
+ int tableIndex = _mainCharacter.sceneId - READ_LE_UINT16(&_ingameTalkObjIndex[5 + _newChapterFile]);
+ if (queryGameFlag(0x159) || _newSceneDlgState[tableIndex])
+ return;
+
+ int csEntry, vocH, scIndex1, scIndex2;
+ updateDlgBuffer();
+ loadDlgHeader(csEntry, vocH, scIndex1, scIndex2);
+
+ uint8 bufferIndex = 8 + scIndex1 * 6 + scIndex2 * 4 + tableIndex * 2;
+ int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
+ processDialogue(offs, vocH, csEntry);
+
+ _newSceneDlgState[tableIndex] = 1;
+}
+
void KyraEngine_v2::initSceneAnims(int unk1) {
for (int i = 0; i < ARRAYSIZE(_animObjects); ++i)
_animObjects[i].enabled = 0;
@@ -908,5 +924,4 @@ void KyraEngine_v2::fadeScenePal(int srcIndex, int delayTime) {
_screen->fadePalette(_screen->getPalette(0), delayTime, &_updateFunctor);
}
-} // end of namespace Kyra
-
+} // end of namespace Kyra \ No newline at end of file
diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp
index f115665f09..587115551d 100644
--- a/engines/kyra/script_v2.cpp
+++ b/engines/kyra/script_v2.cpp
@@ -622,6 +622,41 @@ int KyraEngine_v2::o2_updateSceneAnim(ScriptState *script) {
return 0;
}
+int KyraEngine_v2::o2_useItemOnMainChar(ScriptState *script) {
+ ScriptState tmpScript;
+ _scriptInterpreter->initScript(&tmpScript, &_npcScriptData);
+ _scriptInterpreter->startScript(&tmpScript, 0);
+ tmpScript.regs[4] = _itemInHand;
+ tmpScript.regs[0] = _mainCharacter.sceneId;
+
+ int oldVocH = _vocHigh;
+ _vocHigh = 0x5a;
+
+ while(_scriptInterpreter->validScript(&tmpScript))
+ _scriptInterpreter->runScript(&tmpScript);
+
+ _vocHigh = oldVocH;
+
+ return 0;
+}
+
+int KyraEngine_v2::o2_startDialogue(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_startDialogue(%p) (%d)", (const void *)script, stackPos(0));
+ startDialogue(stackPos(0));
+ return 0;
+}
+
+int KyraEngine_v2::o2_setupDialogue(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setupDialogue(%p) (%d)", (const void *)script, stackPos(0));
+ setNewDlgIndex(stackPos(0));
+ return 0;
+}
+
+int KyraEngine_v2::o2_getDlgIndex(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setNewDlgIndex(%p) (%d)", (const void *)script, stackPos(0));
+ return _mainCharacter.dlgIndex;
+}
+
int KyraEngine_v2::o2_defineRoom(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "o2_defineRoom(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)", (const void *)script,
stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
@@ -653,6 +688,28 @@ int KyraEngine_v2::o2_objectChat(ScriptState *script) {
return 0;
}
+int KyraEngine_v2::o2_getColorCodeFlag1(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag1(%p)", (const void *)script);
+ return _colorCodeFlag1;
+}
+
+int KyraEngine_v2::o2_setColorCodeFlag1(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag1(%p) (%d)", (const void *)script, stackPos(0));
+ _colorCodeFlag1 = stackPos(0);
+ return 0;
+}
+
+int KyraEngine_v2::o2_getColorCodeFlag2(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag2(%p)", (const void *)script);
+ return _colorCodeFlag2;
+}
+
+int KyraEngine_v2::o2_setColorCodeFlag2(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getColorCodeFlag2(%p) (%d)", (const void *)script, stackPos(0));
+ _colorCodeFlag2 = stackPos(0);
+ return 0;
+}
+
int KyraEngine_v2::o2_countItemInstances(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "o2_countItemInstances(%p) (%d)", (const void *)script, stackPos(0));
uint16 item = stackPos(0);
@@ -691,6 +748,17 @@ int KyraEngine_v2::o2_initObject(ScriptState *script) {
return 0;
}
+int KyraEngine_v2::o2_npcChat(ScriptState *script) {
+ if (_flags.isTalkie) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_npcChat(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), _vocHigh, stackPos(2));
+ npcChatSequence(stackPosString(0), stackPos(1), _vocHigh, stackPos(2));
+ } else {
+ debugC(3, kDebugLevelScriptFuncs, "o2_npcChat(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
+ npcChatSequence(stackPosString(0), stackPos(1));
+ }
+ return 0;
+}
+
int KyraEngine_v2::o2_deinitObject(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "o2_deinitObject(%p) (%d)", (const void *)script, stackPos(0));
deinitTalkObject(stackPos(0));
@@ -840,3 +908,4 @@ int KyraEngine_v2::o2t_setShapeFlag(ScriptState *script) {
} // end of namespace Kyra
+
diff --git a/engines/kyra/sequences_tim.cpp b/engines/kyra/sequences_tim.cpp
new file mode 100644
index 0000000000..a072f2f64d
--- /dev/null
+++ b/engines/kyra/sequences_tim.cpp
@@ -0,0 +1,315 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "kyra/text_v2.h"
+#include "kyra/kyra_v2.h"
+#include "kyra/sound.h"
+#include "kyra/resource.h"
+
+#include "common/endian.h"
+
+namespace Kyra {
+
+uint8 *KyraEngine_v2::tim_loadFile(const char *filename, byte *buffer, int32 bufferSize) {
+ ScriptFileParser file(filename, _res);
+ if (!file) {
+ error("Couldn't open script file '%s'", filename);
+ return NULL;
+ }
+
+ int32 formBlockSize = file.getFORMBlockSize();
+ if (formBlockSize == -1) {
+ error("No FORM chunk found in file: '%s'", filename);
+ return NULL;
+ }
+
+ if (formBlockSize < 20) {
+ return NULL;
+ }
+
+ formBlockSize += sizeof(TIMHeader) + 10 * (sizeof(Cmds) + 120);
+
+ TIMHeader *timHeader;
+ if (buffer == NULL || bufferSize < formBlockSize) {
+ buffer = new byte[formBlockSize];
+ timHeader = (TIMHeader *)buffer;
+ timHeader->deleteBufferFlag = 0xBABE;
+ } else {
+ timHeader = (TIMHeader *)buffer;
+ timHeader->deleteBufferFlag = 0x0;
+ }
+
+ int32 chunkSize = file.getIFFBlockSize(AVTL_CHUNK);
+ timHeader->unkFlag = -1;
+ timHeader->unkFlag2 = 0;
+ timHeader->cmdsOffset = sizeof(TIMHeader);
+ timHeader->unkOffset2 = timHeader->cmdsOffset + 10 * sizeof(Cmds);
+ timHeader->AVTLOffset = timHeader->unkOffset2 + 120;
+ timHeader->TEXTOffset = timHeader->AVTLOffset + chunkSize;
+
+ _TIMBuffers.AVTLChunk = buffer + timHeader->AVTLOffset;
+ _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
+
+ if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
+ error("Couldn't load AVTL chunk from file: '%s'", filename);
+ return NULL;
+ }
+
+ _TIMBuffers.currentCommandSet = (Cmds *)(buffer + timHeader->cmdsOffset);
+
+ for (int i = 0; i < 10; i++) {
+ _TIMBuffers.currentCommandSet[i].dataPtr = 0;
+ _TIMBuffers.currentCommandSet[i].unk_2 = 0;
+ _TIMBuffers.currentCommandSet[i].AVTLSubChunk = &_TIMBuffers.AVTLChunk[READ_LE_UINT16(&_TIMBuffers.AVTLChunk[i << 1]) << 1];
+ _TIMBuffers.currentCommandSet[i].timer1 = 0;
+ _TIMBuffers.currentCommandSet[i].timer2 = 0;
+ }
+
+ chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
+ if (chunkSize > 0) {
+ if (!file.loadIFFBlock(TEXT_CHUNK, _TIMBuffers.TEXTChunk, chunkSize)) {
+ error("Couldn't load TEXT chunk from file: '%s'", filename);
+ return NULL;
+ }
+ }
+
+ return buffer;
+}
+
+void KyraEngine_v2::tim_releaseBuffer(byte *buffer) {
+ TIMHeader *timHeader = (TIMHeader *)buffer;
+ if (timHeader->deleteBufferFlag == 0xBABE)
+ delete[] buffer;
+}
+
+void KyraEngine_v2::tim_processSequence(uint8 *timBuffer, int loop) {
+ if (!timBuffer)
+ return;
+
+ TIMHeader *hdr = (TIMHeader*) timBuffer;
+ _TIMBuffers.offsUnkFlag = (uint8*) &hdr->unkFlag;
+ _TIMBuffers.offsUnkFlag2 = (uint8*) &hdr->unkFlag2;
+ _TIMBuffers.currentCommandSet = (Cmds*) (timBuffer + hdr->cmdsOffset);
+ _TIMBuffers.unkCmds = timBuffer + hdr->unkOffset2;
+ _TIMBuffers.AVTLChunk = timBuffer + hdr->AVTLOffset;
+ _TIMBuffers.TEXTChunk = timBuffer + hdr->TEXTOffset;
+
+ if (!_TIMBuffers.currentCommandSet->dataPtr) {
+ _TIMBuffers.currentCommandSet->dataPtr = _TIMBuffers.currentCommandSet->AVTLSubChunk;
+ _TIMBuffers.currentCommandSet->timer1 = _system->getMillis();
+ _TIMBuffers.currentCommandSet->timer2 = _system->getMillis();
+ }
+
+ do {
+ _TIMBuffers.currentEntry = 0;
+
+ while (_TIMBuffers.currentEntry < 10) {
+ Cmds *s = &_TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry];
+ if ((int16)READ_LE_UINT16(_TIMBuffers.offsUnkFlag) != -1)
+ (this->*_timOpcodes[28])(_TIMBuffers.offsUnkFlag2);
+
+ bool running = true;
+
+ while (s->dataPtr && s->timer2 <= _system->getMillis() && running) {
+ uint8 cmd = s->dataPtr[4];
+ hdr->unkFlag2 = cmd;
+ uint8 *para = &s->dataPtr[6];
+
+ switch((this->*_timOpcodes[cmd])(para)) {
+ case -3:
+ WRITE_LE_UINT16(_TIMBuffers.offsUnkFlag, _TIMBuffers.currentEntry);
+ _TIMBuffers.unk_12 = -1;
+ break;
+
+ case -2:
+ running = false;
+ break;
+
+ case -1:
+ loop = 0;
+ running = false;
+ _TIMBuffers.currentEntry = 11;
+ break;
+
+ case 22:
+ s->backupPtr = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ if (s) {
+ if (s->dataPtr) {
+ s->dataPtr += (READ_LE_UINT16(s->dataPtr) * 2);
+ s->timer1 = s->timer2;
+ s->timer2 += (READ_LE_UINT16(s->dataPtr + 2) * _tickLength);
+ }
+ }
+ }
+
+ _TIMBuffers.currentEntry++;
+ }
+ } while (loop);
+
+}
+
+int KyraEngine_v2::tim_o_dummy_r0(uint8 *ptr) {
+ return 0;
+}
+
+int KyraEngine_v2::tim_o_dummy_r1(uint8 *ptr) {
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_clearCmds2(uint8 *ptr) {
+ for (int i = 1; i < 10; i++)
+ memset(&_TIMBuffers.unkCmds[i], 0, 12);
+ _TIMBuffers.currentCommandSet[0].dataPtr = _TIMBuffers.currentCommandSet[0].AVTLSubChunk;
+ _TIMBuffers.currentCommandSet[0].timer1 = _system->getMillis();
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_abort(uint8 *ptr) {
+ _TIMBuffers.currentCommandSet[_TIMBuffers.currentEntry].dataPtr = 0;
+ if(!_TIMBuffers.currentEntry)
+ _objectChatFinished = true;
+ return -2;
+}
+
+
+int KyraEngine_v2::tim_o_selectcurrentCommandSet(uint8 *ptr) {
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk ?
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk : &_TIMBuffers.AVTLChunk[_TIMBuffers.AVTLChunk[READ_LE_UINT16(ptr) << 1] << 1];
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_deleteBuffer(uint8 *ptr) {
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_refreshTimers(uint8 *ptr) {
+ for (int i = 1; i < 10; i++) {
+ if (_TIMBuffers.currentCommandSet[i].dataPtr)
+ _TIMBuffers.currentCommandSet[i].timer2 = _system->getMillis();
+ }
+
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_execSubOpcode(uint8 *ptr) {
+ return (this->*_timOpcodes[30 + READ_LE_UINT16(ptr)])(ptr + 2);
+}
+
+int KyraEngine_v2::tim_o_initActiveSub(uint8 *ptr) {
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].AVTLSubChunk;
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = _system->getMillis();
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_resetActiveSub(uint8 *ptr) {
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].dataPtr = 0;
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer2 = 0;
+ _TIMBuffers.currentCommandSet[READ_LE_UINT16(ptr)].timer1 = 0;
+ return 1;
+}
+
+int KyraEngine_v2::tim_o_printTalkText(uint8 *ptr) {
+ _chatText = _timChatText = (const char*) _TIMBuffers.TEXTChunk + (READ_LE_UINT16(ptr) << 1);
+ _chatObject = _timChatObject = READ_LE_UINT16(ptr + 2);
+
+ if (_flags.lang == Common::JA_JPN) {
+ for (int i = 0; i < _ingameTimJpStrSize; i += 2) {
+ if (!scumm_stricmp(_timChatText, _ingameTimJpStr[i]))
+ _chatText = _ingameTimJpStr[i + 1];
+ }
+ }
+ objectChatInit(_chatText, _timChatObject);
+ return 0;
+}
+
+int KyraEngine_v2::tim_o_updateSceneAnim(uint8 *ptr) {
+ updateSceneAnim(READ_LE_UINT16(ptr + 2), READ_LE_UINT16(ptr));
+ return 0;
+}
+
+int KyraEngine_v2::tim_o_resetChat(uint8 *ptr) {
+ _text->restoreScreen();
+ _chatText = 0;
+ _chatObject = -1;
+ _timChatText = 0;
+ _timChatObject = -1;
+ return 0;
+}
+
+int KyraEngine_v2::tim_o_playSoundEffect(uint8 *ptr) {
+ snd_playSoundEffect(READ_LE_UINT16(ptr));
+ return 0;
+}
+
+void KyraEngine_v2::tim_setupOpcodes() {
+ static const TimOpc Opcodes[] = {
+ &KyraEngine_v2::tim_o_clearCmds2,
+ &KyraEngine_v2::tim_o_abort,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_selectcurrentCommandSet,
+ &KyraEngine_v2::tim_o_deleteBuffer,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_dummy_r0,
+ &KyraEngine_v2::tim_o_refreshTimers,
+ &KyraEngine_v2::tim_o_dummy_r1,
+ &KyraEngine_v2::tim_o_execSubOpcode,
+ &KyraEngine_v2::tim_o_initActiveSub,
+ &KyraEngine_v2::tim_o_resetActiveSub,
+ &KyraEngine_v2::tim_o_dummy_r1,
+ &KyraEngine_v2::tim_o_dummy_r1,
+ &KyraEngine_v2::tim_o_printTalkText,
+ &KyraEngine_v2::tim_o_updateSceneAnim,
+ &KyraEngine_v2::tim_o_resetChat,
+ &KyraEngine_v2::tim_o_playSoundEffect,
+ };
+
+ _timOpcodes = (const TimOpc*) Opcodes;
+}
+
+} // end of namespace Kyra
+
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index a93a9ed66a..692db54af5 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -39,7 +39,7 @@
namespace Kyra {
Sound::Sound(KyraEngine *vm, Audio::Mixer *mixer)
- : _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandle(),
+ : _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandles(),
_musicEnabled(1), _sfxEnabled(true), _soundDataList(0) {
}
@@ -52,6 +52,14 @@ void Sound::voicePlay(const char *file) {
bool found = false;
char filenamebuffer[25];
+ int h = 0;
+ if (_currentVocFile) {
+ while (_mixer->isSoundHandleActive(_vocHandles[h]))
+ h++;
+ if (h >= kNumVocHandles)
+ return;
+ }
+
for (int i = 0; _supportedCodes[i].fileext; ++i) {
strcpy(filenamebuffer, file);
strcat(filenamebuffer, _supportedCodes[i].fileext);
@@ -76,21 +84,26 @@ void Sound::voicePlay(const char *file) {
_currentVocFile = Audio::makeVOCStream(vocStream);
}
- if (_currentVocFile) {
- //_mixer->stopHandle(_vocHandle);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
- }
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandles[h], _currentVocFile);
+
delete [] fileData;
fileSize = 0;
}
void Sound::voiceStop() {
- if (_mixer->isSoundHandleActive(_vocHandle))
- _mixer->stopHandle(_vocHandle);
+ for (int h = 0; h < kNumVocHandles; h++) {
+ if (_mixer->isSoundHandleActive(_vocHandles[h]))
+ _mixer->stopHandle(_vocHandles[h]);
+ }
}
bool Sound::voiceIsPlaying() {
- return _mixer->isSoundHandleActive(_vocHandle);
+ bool res = false;
+ for (int h = 0; h < kNumVocHandles; h++) {
+ if (_mixer->isSoundHandleActive(_vocHandles[h]))
+ res = true;
+ }
+ return res;
}
#pragma mark -
@@ -522,3 +535,4 @@ const Sound::SpeechCodecs Sound::_supportedCodes[] = {
} // end of namespace Kyra
+
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 426d7b6896..919cc3ceab 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -180,6 +180,10 @@ protected:
const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
const int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
+ enum {
+ kNumVocHandles = 4
+ };
+
int _musicEnabled;
bool _sfxEnabled;
@@ -191,7 +195,7 @@ protected:
private:
const AudioDataStruct *_soundDataList;
Audio::AudioStream *_currentVocFile;
- Audio::SoundHandle _vocHandle;
+ Audio::SoundHandle _vocHandles[kNumVocHandles];
struct SpeechCodecs {
const char *fileext;
@@ -425,10 +429,10 @@ private:
int _lastTrack;
Audio::AudioStream *_currentSFX;
- Audio::SoundHandle _sfxHandle;
+ Audio::SoundHandle _sfxHandles[kNumVocHandles];
- //SoundTowns_v2_TwnDriver * _driver;
- uint8 * _twnTrackData;
+ //SoundTowns_v2_TwnDriver *_driver;
+ uint8 *_twnTrackData;
};
class MixedSoundDriver : public Sound {
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index ae9f3a7915..e3102d747b 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -1435,6 +1435,14 @@ void SoundTowns_v2::haltTrack() {
void SoundTowns_v2::voicePlay(const char *file) {
static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
+ int h = 0;
+ if (_currentSFX) {
+ while (_mixer->isSoundHandleActive(_sfxHandles[h]))
+ h++;
+ if (h >= kNumVocHandles)
+ return;
+ }
+
uint8 * data = _vm->resource()->fileData(file, 0);
uint8 * src = data;
@@ -1482,7 +1490,7 @@ void SoundTowns_v2::voicePlay(const char *file) {
_currentSFX = Audio::makeLinearInputStream(sfx, outsize, outputRate,
Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_LITTLE_ENDIAN | Audio::Mixer::FLAG_AUTOFREE, 0, 0);
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _currentSFX);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandles[h], _currentSFX);
delete [] data;
}
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index a77632617d..f36a67146b 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -35,7 +35,7 @@
namespace Kyra {
-#define RESFILE_VERSION 20
+#define RESFILE_VERSION 21
bool StaticResource::checkKyraDat() {
Common::File kyraDat;
@@ -241,10 +241,12 @@ bool StaticResource::init() {
// Ingame
{ k2IngamePakFiles, kStringList, "I_PAKFILES.TXT" },
- { k2IngameSfxFiles, kStringList, "I_SFXFILES.TXT" },
- { k2IngameSfxIndex, kRawData, "I_SFXINDEX.TRA" },
+ { k2IngameSfxFiles, kStringList, "I_SFXFILES.TRA" },
+ { k2IngameSfxIndex, kRawData, "I_SFXINDEX.MAP" },
{ k2IngameTracks, kStringList, "I_TRACKS.TRA" },
{ k2IngameCDA, kRawData, "I_TRACKS.CDA" },
+ { k2IngameTalkObjIndex, kRawData, "I_TALKOBJECTS.MAP" },
+ { k2IngameTimJpStrings, kStringList, "I_TIMJPSTR.TXT" },
{ 0, 0, 0 }
};
@@ -926,6 +928,8 @@ void KyraEngine_v2::initStaticResource() {
_cdaTrackTableIntro = _staticres->loadRawData(k2SeqplayIntroCDA, _cdaTrackTableIntroSize);
_cdaTrackTableIngame = _staticres->loadRawData(k2IngameCDA, _cdaTrackTableIngameSize);
_cdaTrackTableFinale = _staticres->loadRawData(k2SeqplayFinaleCDA, _cdaTrackTableFinaleSize);
+ _ingameTalkObjIndex = (const uint16*) _staticres->loadRawData(k2IngameTalkObjIndex, _ingameTalkObjIndexSize);
+ _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize);
// replace sequence talkie files with localized versions and cut off .voc
// suffix from voc files so as to allow compression specific file extensions
@@ -934,7 +938,7 @@ void KyraEngine_v2::initStaticResource() {
// of _sequenceSoundList instead of casting away const.
const char* const* tlkfiles = _staticres->loadStrings(k2SeqplayTlkFiles, tmp);
for (int i = 0; i < _sequenceSoundListSize; i++) {
- uint32 len = strlen(_sequenceSoundList[i]);
+ int len = strlen(_sequenceSoundList[i]);
if (_flags.platform == Common::kPlatformPC)
len -= 4;
@@ -1494,3 +1498,4 @@ const int KyraEngine_v3::_languageExtensionSize = ARRAYSIZE(KyraEngine_v3::_lang
} // End of namespace Kyra
+
diff --git a/engines/kyra/text_v2.cpp b/engines/kyra/text_v2.cpp
index 2f517c2d42..5857fdae66 100644
--- a/engines/kyra/text_v2.cpp
+++ b/engines/kyra/text_v2.cpp
@@ -27,6 +27,8 @@
#include "kyra/kyra_v2.h"
#include "kyra/resource.h"
+#include "common/endian.h"
+
namespace Kyra {
TextDisplayer_v2::TextDisplayer_v2(KyraEngine_v2 *vm, Screen_v2 *screen)
@@ -325,7 +327,7 @@ void KyraEngine_v2::objectChatWaitToFinish() {
}
const uint32 curTime = _system->getMillis();
- if ((textEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || _skipFlag) {
+ if ((textEnabled() && curTime > endTime) || (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) || _skipFlag) {
_skipFlag = false;
nextFrame = curTime;
running = false;
@@ -340,150 +342,308 @@ void KyraEngine_v2::objectChatWaitToFinish() {
resetCharacterAnimDim();
}
-void KyraEngine_v2::initTalkObject(int initObject) {
- TalkObject &object = _talkObjectList[initObject];
+void KyraEngine_v2::startDialogue(int dlgIndex) {
+ updateDlgBuffer();
+ int csEntry, vocH, unused1, unused2;
+ loadDlgHeader(csEntry, vocH, unused1, unused2);
+ int s = _conversationState[dlgIndex][csEntry];
+ uint8 bufferIndex = 8;
+
+ if (s == -1) {
+ bufferIndex += (dlgIndex * 6);
+ _conversationState[dlgIndex][csEntry] = 0;
+ } else if (!s || s == 2) {
+ bufferIndex += (dlgIndex * 6 + 2);
+ _conversationState[dlgIndex][csEntry] = 1;
+ } else {
+ bufferIndex += (dlgIndex * 6 + 4);
+ _conversationState[dlgIndex][csEntry] = 2;
+ }
+
+ int offs = READ_LE_UINT16(_dlgBuffer + bufferIndex);
+ processDialogue(offs, vocH, csEntry);
+}
+
+void KyraEngine_v2::updateDlgBuffer() {
+ static const char DlgFileTemplate[] = "CH**-S**.DLG";
+ char filename[13];
+ filename[12] = 0;
+ memcpy(filename, DlgFileTemplate, 12);
+
+ static const char suffixTalkie[] = "EFG";
+ static const char suffixTowns[] = "G J";
+ const char * suffix = _flags.isTalkie ? suffixTalkie : suffixTowns;
+
+ filename[2] = (char)((_currentChapter / 10 + 48) & 0xFF);
+ filename[3] = (char)((_currentChapter % 10 + 48) & 0xFF);
+
+ if (!(_flags.platform == Common::kPlatformPC && !_flags.isTalkie))
+ filename[11] = suffix[_lang];
+
+ if (_currentChapter == _npcTalkChpIndex && _mainCharacter.dlgIndex == _npcTalkDlgIndex)
+ return;
+
+ _npcTalkChpIndex = _currentChapter;
+ _npcTalkDlgIndex = _mainCharacter.dlgIndex;
+
+ filename[6] = (char)((_npcTalkDlgIndex / 10 + 48) & 0xFF);
+ filename[7] = (char)((_npcTalkDlgIndex % 10 + 48) & 0xFF);
+
+ if (_dlgBuffer)
+ delete [] _dlgBuffer;
+
+ _dlgBuffer = _res->fileData(filename, 0);
+}
+
+void KyraEngine_v2::loadDlgHeader(int &csEntry, int &vocH, int &scIndex1, int &scIndex2) {
+ csEntry = READ_LE_UINT16(_dlgBuffer);
+ vocH = READ_LE_UINT16(_dlgBuffer + 2);
+ scIndex1 = READ_LE_UINT16(_dlgBuffer + 4);
+ scIndex2 = READ_LE_UINT16(_dlgBuffer + 6);
+}
+
+void KyraEngine_v2::processDialogue(int dlgOffset, int vocH, int csEntry) {
+ int activeTimSequence = -1;
+ int nextTimSequence = -1;
+ int cmd = 0;
+ int vocHi = -1;
+ int vocLo = -1;
+ bool loop = true;
+ int offs = dlgOffset;
+
+ _screen->hideMouse();
+
+ while (loop) {
+ cmd = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+
+ nextTimSequence = READ_LE_UINT16(&_ingameTalkObjIndex[cmd]);
+
+ if (nextTimSequence == 10) {
+ if (queryGameFlag(0x3e))
+ nextTimSequence = 14;
+ if (queryGameFlag(0x3f))
+ nextTimSequence = 15;
+ if (queryGameFlag(0x40))
+ nextTimSequence = 16;
+ }
+
+ if (nextTimSequence == 27 && _mainCharacter.sceneId == 34)
+ nextTimSequence = 41;
+
+ if (queryGameFlag(0x72)) {
+ if (nextTimSequence == 18)
+ nextTimSequence = 43;
+ else if (nextTimSequence == 19)
+ nextTimSequence = 44;
+ }
+
+ if (_mainCharacter.x1 > 160) {
+ if (nextTimSequence == 4)
+ nextTimSequence = 46;
+ else if (nextTimSequence == 5)
+ nextTimSequence = 47;
+ }
+
+ if (cmd == 10) {
+ loop = false;
+
+ } else if (cmd == 4) {
+ csEntry = READ_LE_UINT16(_dlgBuffer + offs);
+ setNewDlgIndex(csEntry);
+ offs += 2;
+
+ } else {
+ if (!_flags.isTalkie || cmd == 11) {
+ int len = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ if (_flags.isTalkie) {
+ vocLo = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ }
+ memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
+ _unkBuf500Bytes[len] = 0;
+ offs += len;
+ if (_flags.isTalkie)
+ continue;
+
+ } else if (_flags.isTalkie) {
+ int len = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ static const int irnv[] = { 91, 105, 110, 114, 118 };
+ vocHi = irnv[vocH - 1] + csEntry;
+ vocLo = READ_LE_UINT16(_dlgBuffer + offs);
+ offs += 2;
+ memcpy(_unkBuf500Bytes, _dlgBuffer + offs, len);
+ _unkBuf500Bytes[len] = 0;
+ offs += len;
+ }
+
+ if (_unkBuf500Bytes[0]) {
+ if ((!_flags.isTalkie && cmd == 11) || (_flags.isTalkie && cmd == 12)) {
+ if (activeTimSequence > -1) {
+ deinitTalkObject(activeTimSequence);
+ activeTimSequence = -1;
+ }
+ objectChat((const char*) _unkBuf500Bytes, 0, vocHi, vocLo);
+ } else {
+ if (activeTimSequence != nextTimSequence ) {
+ if (activeTimSequence > -1) {
+ deinitTalkObject(activeTimSequence);
+ activeTimSequence = -1;
+ }
+ initTalkObject(nextTimSequence);
+ activeTimSequence = nextTimSequence;
+ }
+ npcChatSequence((const char *)_unkBuf500Bytes, nextTimSequence, vocHi, vocLo);
+ }
+ }
+ }
+ }
+
+ if (activeTimSequence > -1)
+ deinitTalkObject(activeTimSequence);
+
+ _screen->showMouse();
+}
+
+void KyraEngine_v2::initTalkObject(int index) {
+ TalkObject &object = _talkObjectList[index];
char STAFilename[13];
- char TLKFilename[13];
char ENDFilename[13];
strcpy(STAFilename, object.filename);
- strcpy(TLKFilename, object.filename);
+ strcpy(_TLKFilename, object.filename);
strcpy(ENDFilename, object.filename);
strcpy(STAFilename + 4, "_STA.TIM");
- strcpy(TLKFilename + 4, "_TLK.TIM");
+ strcpy(_TLKFilename + 4, "_TLK.TIM");
strcpy(ENDFilename + 4, "_END.TIM");
- _currentTalkSections.STATim = loadTIMFile(STAFilename, NULL, 0);
- _currentTalkSections.TLKTim = loadTIMFile(TLKFilename, NULL, 0);
- _currentTalkSections.ENDTim = loadTIMFile(ENDFilename, NULL, 0);
+ _currentTalkSections.STATim = tim_loadFile(STAFilename, NULL, 0);
+ _currentTalkSections.TLKTim = tim_loadFile(_TLKFilename, NULL, 0);
+ _currentTalkSections.ENDTim = tim_loadFile(ENDFilename, NULL, 0);
if (object.scriptId != -1) {
_specialSceneScriptStateBackup[object.scriptId] = _specialSceneScriptState[object.scriptId];
_specialSceneScriptState[object.scriptId] = 1;
}
- /*if (_currentTalkObject.STATim) {
+ if (_currentTalkSections.STATim) {
_objectChatFinished = false;
while (!_objectChatFinished) {
- processTalkObject(_currentTalkObject.STATim, 0);
+ tim_processSequence(_currentTalkSections.STATim, 0);
if (_chatText)
updateWithText();
else
update();
}
- }*/
+ }
}
-void KyraEngine_v2::deinitTalkObject(int initObject) {
- TalkObject &object = _talkObjectList[initObject];
+void KyraEngine_v2::deinitTalkObject(int index) {
+ TalkObject &object = _talkObjectList[index];
- /*if (_currentTalkObject.ENDTim) {
+ if (_currentTalkSections.ENDTim) {
_objectChatFinished = false;
while (!_objectChatFinished) {
- processTalkObject(_currentTalkObject.ENDTim, 0);
+ tim_processSequence(_currentTalkSections.ENDTim, 0);
if (_chatText)
updateWithText();
else
update();
}
- }*/
+ }
if (object.scriptId != -1) {
_specialSceneScriptState[object.scriptId] = _specialSceneScriptStateBackup[object.scriptId];
}
if (_currentTalkSections.STATim != NULL) {
- freeTIM(_currentTalkSections.STATim);
+ tim_releaseBuffer(_currentTalkSections.STATim);
_currentTalkSections.STATim = NULL;
}
if (_currentTalkSections.TLKTim != NULL) {
- freeTIM(_currentTalkSections.TLKTim);
+ tim_releaseBuffer(_currentTalkSections.TLKTim);
_currentTalkSections.TLKTim = NULL;
}
if (_currentTalkSections.ENDTim != NULL) {
- freeTIM(_currentTalkSections.ENDTim);
+ tim_releaseBuffer(_currentTalkSections.ENDTim);
_currentTalkSections.ENDTim = NULL;
}
}
-byte *KyraEngine_v2::loadTIMFile(const char *filename, byte *buffer, int32 bufferSize) {
- ScriptFileParser file(filename, _res);
- if (!file) {
- error("Couldn't open script file '%s'", filename);
- return NULL;
- }
+void KyraEngine_v2::npcChatSequence(const char *str, int objectId, int vocHigh, int vocLow) {
+ _chatText = str;
+ _chatObject = objectId;
+ objectChatInit(str, objectId, vocHigh, vocLow);
- int32 formBlockSize = file.getFORMBlockSize();
- if (formBlockSize == -1) {
- error("No FORM chunk found in file: '%s'", filename);
- return NULL;
- }
+ if (!_currentTalkSections.TLKTim)
+ _currentTalkSections.TLKTim = tim_loadFile(_TLKFilename, 0, 0);
- if (formBlockSize < 20) {
- return NULL;
- }
+ setNextIdleAnimTimer();
- formBlockSize += sizeof(TIMHeader) + 120 + sizeof(TIMStructUnk1) * 10;
+ uint32 ct = chatCalcDuration(str);
+ uint32 time = _system->getMillis();
+ _chatEndTime = time + (3 + ct) * _tickLength;
+ uint32 chatAnimEndTime = time + (3 + (ct >> 1)) * _tickLength;
- TIMHeader *timHeader;
- if (buffer == NULL || bufferSize < formBlockSize) {
- buffer = new byte[formBlockSize];
- timHeader = (TIMHeader *)buffer;
- timHeader->deleteBufferFlag = 0xBABE;
- } else {
- timHeader = (TIMHeader *)buffer;
- timHeader->deleteBufferFlag = 0x0;
+ if (_chatVocHigh >= 0) {
+ playVoice(_chatVocHigh, _chatVocLow);
+ _chatVocHigh = _chatVocLow = -1;
}
- int32 chunkSize = file.getIFFBlockSize(AVTL_CHUNK);
- timHeader->unkFlag = -1;
- timHeader->unkFlag2 = 0;
- timHeader->unkOffset = sizeof(TIMHeader);
- timHeader->unkOffset2 = timHeader->unkOffset + sizeof(TIMStructUnk1) * 10;
- timHeader->AVTLOffset = timHeader->unkOffset2 + 120;
- timHeader->TEXTOffset = timHeader->AVTLOffset + chunkSize;
-
- _TIMBuffers.AVTLChunk = (uint16 *)(buffer + timHeader->AVTLOffset);
- _TIMBuffers.TEXTChunk = buffer + timHeader->TEXTOffset;
+ while (((textEnabled() && _chatEndTime > _system->getMillis()) || (speechEnabled() && snd_voiceIsPlaying())) && !(_quitFlag || _skipFlag)) {
+ if (!speechEnabled() && chatAnimEndTime > _system->getMillis() || speechEnabled() && snd_voiceIsPlaying()) {
+ _objectChatFinished = false;
- if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
- error("Couldn't load AVTL chunk from file: '%s'", filename);
- return NULL;
- }
+ while (!_objectChatFinished && !_skipFlag) {
+ if (_currentTalkSections.TLKTim)
+ tim_processSequence(_currentTalkSections.TLKTim, 0);
+ else
+ _objectChatFinished = false;
- _TIMBuffers.UnkChunk = (TIMStructUnk1 *)(buffer + timHeader->unkOffset);
+ updateWithText();
- for (int i = 0; i < 10; i++) {
- _TIMBuffers.UnkChunk[i].unk_0 = 0;
- _TIMBuffers.UnkChunk[i].unk_2 = 0;
- _TIMBuffers.UnkChunk[i].unk_20 = &_TIMBuffers.AVTLChunk[ _TIMBuffers.AVTLChunk[i] ];
- _TIMBuffers.UnkChunk[i].unk_4 = 0;
- _TIMBuffers.UnkChunk[i].unk_8 = 0;
+ int inputFlag = checkInput(0);
+ removeInputTop();
+ if (inputFlag == 198 || inputFlag == 199) {
+ //XXX
+ _skipFlag = true;
+ snd_stopVoice();
+ }
+ delay(10);
+ }
+ if (_currentTalkSections.TLKTim)
+ tim_o_abort(0);
+ }
+ updateWithText();
}
- chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
- if (chunkSize > 0) {
- if (!file.loadIFFBlock(TEXT_CHUNK, _TIMBuffers.TEXTChunk, chunkSize)) {
- error("Couldn't load TEXT chunk from file: '%s'", filename);
- return NULL;
- }
+ _skipFlag = false;
+
+ if (_currentTalkSections.TLKTim) {
+ tim_releaseBuffer(_currentTalkSections.TLKTim);
+ _currentTalkSections.TLKTim = 0;
}
- return buffer;
+ _text->restoreScreen();
+ _chatText = 0;
+ _chatObject = -1;
+ setNextIdleAnimTimer();
}
-void KyraEngine_v2::freeTIM(byte *buffer) {
- TIMHeader *timHeader = (TIMHeader *)buffer;
-
- if (timHeader->deleteBufferFlag == 0xBABE) {
- delete[] buffer;
- }
+void KyraEngine_v2::setNewDlgIndex(int dlgIndex) {
+ if (dlgIndex == _mainCharacter.dlgIndex)
+ return;
+ memset(_newSceneDlgState, 0, 32);
+ for (int i = 0; i < 19; i++)
+ memset(_conversationState[i], -1, 14);
+ _npcTalkUNK = 0;
+ _mainCharacter.dlgIndex = dlgIndex;
}
} // end of namespace Kyra
-
-