aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/kyra_v2.cpp13
-rw-r--r--engines/kyra/kyra_v2.h59
-rw-r--r--engines/kyra/script.cpp5
-rw-r--r--engines/kyra/script.h6
-rw-r--r--engines/kyra/script_v2.cpp16
-rw-r--r--engines/kyra/text_v2.cpp151
6 files changed, 227 insertions, 23 deletions
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 306cdbed14..87ab508773 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -75,6 +75,10 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngi
_chatText = 0;
_chatObject = -1;
+ _currentTalkSections.STATim = NULL;
+ _currentTalkSections.TLKTim = NULL;
+ _currentTalkSections.ENDTim = NULL;
+
memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
}
@@ -247,8 +251,8 @@ void KyraEngine_v2::startup() {
_maskPage = 0;//_screen->getPagePtr(5);
_screen->_curPage = 0;
- _objectList = new Object[72];
- memset(_objectList, 0, sizeof(Object)*72);
+ _talkObjectList = new TalkObject[72];
+ memset(_talkObjectList, 0, sizeof(TalkObject)*72);
_shapeDescTable = new ShapeDesc[55];
memset(_shapeDescTable, 0, sizeof(ShapeDesc)*55);
@@ -705,7 +709,7 @@ void KyraEngine_v2::cleanup() {
delete [] _optionsBuffer;
delete [] _chapterBuffer;
- delete [] _objectList;
+ delete [] _talkObjectList;
delete [] _shapeDescTable;
delete [] _gfxBackUpRect;
@@ -1638,9 +1642,10 @@ void KyraEngine_v2::setupOpcodeTable() {
Opcode(o2_countItemInstances),
OpcodeUnImpl(),
OpcodeUnImpl(),
+ Opcode(o2_initObject),
OpcodeUnImpl(),
// 0x8c
- OpcodeUnImpl(),
+ Opcode(o2_deinitObject),
OpcodeUnImpl(),
OpcodeUnImpl(),
Opcode(o2_setSpecialSceneScriptState),
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index f8ac4fb763..264ec4a923 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -235,6 +235,7 @@ protected:
SceneAnim _sceneAnims[10];
WSAMovieV2 *_sceneAnimMovie[10];
bool _specialSceneScriptState[10];
+ bool _specialSceneScriptStateBackup[10];
ScriptState _sceneSpecialScripts[10];
uint32 _sceneSpecialScriptsTimer[10];
int _lastProcessedSceneScript;
@@ -520,6 +521,8 @@ protected:
void objectChatPrintText(const char *text, int object);
void objectChatProcess(const char *script);
void objectChatWaitToFinish();
+ void initTalkObject(int initObject);
+ void deinitTalkObject(int initObject);
// sound
int _oldTalkFile;
@@ -543,6 +546,51 @@ 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);
+
// opcodes
int o2_setCharacterFacingRefresh(ScriptState *script);
int o2_setCharacterPos(ScriptState *script);
@@ -598,6 +646,8 @@ protected:
int o2_updateSceneAnim(ScriptState *script);
int o2_defineRoom(ScriptState *script);
int o2_countItemInstances(ScriptState *script);
+ int o2_initObject(ScriptState *script);
+ int o2_deinitObject(ScriptState *script);
int o2_setSpecialSceneScriptState(ScriptState *script);
int o2_clearSpecialSceneScriptState(ScriptState *script);
int o2_querySpecialSceneScriptState(ScriptState *script);
@@ -640,15 +690,6 @@ protected:
// pathfinder
int _pathfinderFlag;
- // unk
- struct Object {
- char filename[13];
- uint8 scriptId;
- int16 x, y;
- int8 color;
- };
- Object *_objectList;
-
uint8 *_unkBuf500Bytes;
uint8 *_unkBuf200kByte;
bool _unkFlag1;
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index 0f8de17174..25f1d2331d 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -32,11 +32,6 @@
#include "kyra/resource.h"
#include "kyra/script.h"
-#define FORM_CHUNK 0x4D524F46
-#define TEXT_CHUNK 0x54584554
-#define DATA_CHUNK 0x41544144
-#define ORDR_CHUNK 0x5244524F
-
namespace Kyra {
ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) {
#define COMMAND(x) { &ScriptHelper::x, #x }
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 293f328483..244547b372 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -55,6 +55,12 @@ struct ScriptState {
#define stackPos(x) (script->stack[script->sp+x])
#define stackPosString(x) ((const char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])])
+#define FORM_CHUNK 0x4D524F46
+#define TEXT_CHUNK 0x54584554
+#define DATA_CHUNK 0x41544144
+#define ORDR_CHUNK 0x5244524F
+#define AVTL_CHUNK 0x4C545641
+
class ScriptFileParser {
public:
ScriptFileParser() : _scriptFile(), _startOffset(0), _endOffset(0) {}
diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp
index 83f68c3747..f984dbb66b 100644
--- a/engines/kyra/script_v2.cpp
+++ b/engines/kyra/script_v2.cpp
@@ -61,7 +61,7 @@ int KyraEngine_v2::o2_setCharacterPos(ScriptState *script) {
int KyraEngine_v2::o2_defineObject(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "o2_defineObject(%p) (%d, '%s', %d, %d, %d, %d)", (const void *)script,
stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
- Object *object = &_objectList[stackPos(0)];
+ TalkObject *object = &_talkObjectList[stackPos(0)];
strcpy(object->filename, stackPosString(1));
object->scriptId = stackPos(2);
object->x = stackPos(3);
@@ -667,6 +667,20 @@ int KyraEngine_v2::o2_countItemInstances(ScriptState *script) {
return count;
}
+int KyraEngine_v2::o2_initObject(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_initObject(%p) (%d)", (const void *)script, stackPos(0));
+ initTalkObject(stackPos(0));
+
+ return 0;
+}
+
+int KyraEngine_v2::o2_deinitObject(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_deinitObject(%p) (%d)", (const void *)script, stackPos(0));
+ deinitTalkObject(stackPos(0));
+
+ return 0;
+}
+
int KyraEngine_v2::o2_setSpecialSceneScriptState(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "o2_setSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
_specialSceneScriptState[stackPos(0)] = 1;
diff --git a/engines/kyra/text_v2.cpp b/engines/kyra/text_v2.cpp
index bb8b65c476..491caeb53f 100644
--- a/engines/kyra/text_v2.cpp
+++ b/engines/kyra/text_v2.cpp
@@ -190,8 +190,8 @@ void KyraEngine_v2::objectChatInit(const char *str, int object, int vocHigh, int
yPos = _mainCharacter.y1 - ((_mainCharacter.height * scale) >> 8) - 8;
xPos = _mainCharacter.x1;
} else {
- yPos = _objectList[object].y;
- xPos = _objectList[object].x;
+ yPos = _talkObjectList[object].y;
+ xPos = _talkObjectList[object].x;
}
yPos -= lineNum * 10;
@@ -227,11 +227,11 @@ void KyraEngine_v2::objectChatInit(const char *str, int object, int vocHigh, int
}
void KyraEngine_v2::objectChatPrintText(const char *str, int object) {
- int c1 = _objectList[object].color;
+ int c1 = _talkObjectList[object].color;
str = _text->preprocessString(str);
int lineNum = _text->buildMessageSubstrings(str);
int maxWidth = _text->getWidestLineWidth(lineNum);
- int x = (object == 0) ? _mainCharacter.x1 : _objectList[object].x;
+ int x = (object == 0) ? _mainCharacter.x1 : _talkObjectList[object].x;
int cX1 = 0, cX2 = 0;
_text->calcWidestLineBounds(cX1, cX2, maxWidth, x);
@@ -330,5 +330,148 @@ void KyraEngine_v2::objectChatWaitToFinish() {
resetCharacterAnimDim();
}
+void KyraEngine_v2::initTalkObject(int initObject) {
+ TalkObject &object = _talkObjectList[initObject];
+
+ char STAFilename[13];
+ char TLKFilename[13];
+ char ENDFilename[13];
+
+ strcpy(STAFilename, object.filename);
+ strcpy(TLKFilename, object.filename);
+ strcpy(ENDFilename, object.filename);
+
+ strcpy(STAFilename + 4, "_STA.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);
+
+ if (object.scriptId != -1) {
+ _specialSceneScriptStateBackup[object.scriptId] = _specialSceneScriptState[object.scriptId];
+ _specialSceneScriptState[object.scriptId] = 1;
+ }
+
+ /*if (_currentTalkObject.STATim) {
+ _objectChatFinished = false;
+ while (!_objectChatFinished) {
+ processTalkObject(_currentTalkObject.STATim, 0);
+ if (_chatText)
+ updateWithText();
+ else
+ update();
+ }
+ }*/
+}
+
+void KyraEngine_v2::deinitTalkObject(int initObject) {
+ TalkObject &object = _talkObjectList[initObject];
+
+ /*if (_currentTalkObject.ENDTim) {
+ _objectChatFinished = false;
+ while (!_objectChatFinished) {
+ processTalkObject(_currentTalkObject.ENDTim, 0);
+ if (_chatText)
+ updateWithText();
+ else
+ update();
+ }
+ }*/
+
+ if (object.scriptId != -1) {
+ _specialSceneScriptState[object.scriptId] = _specialSceneScriptStateBackup[object.scriptId];
+ }
+
+ if (_currentTalkSections.STATim != NULL) {
+ freeTIM(_currentTalkSections.STATim);
+ _currentTalkSections.STATim = NULL;
+ }
+
+ if (_currentTalkSections.TLKTim != NULL) {
+ freeTIM(_currentTalkSections.TLKTim);
+ _currentTalkSections.TLKTim = NULL;
+ }
+
+ if (_currentTalkSections.ENDTim != NULL) {
+ freeTIM(_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;
+ }
+
+ int32 formBlockSize = file.getFORMBlockSize();
+ if (formBlockSize == -1) {
+ error("No FORM chunk found in file: '%s'", filename);
+ return NULL;
+ }
+
+ if (formBlockSize < 20) {
+ return NULL;
+ }
+
+ formBlockSize += 120 + sizeof(TIMStructUnk1) * 10;
+
+ 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->unkOffset = 14;
+ 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;
+
+ if (!file.loadIFFBlock(AVTL_CHUNK, _TIMBuffers.AVTLChunk, chunkSize)) {
+ error("Couldn't load AVTL chunk from file: '%s'", filename);
+ return NULL;
+ }
+
+ _TIMBuffers.UnkChunk = (TIMStructUnk1 *)(buffer + timHeader->unkOffset);
+
+ 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;
+ }
+
+ 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::freeTIM(byte *buffer) {
+ TIMHeader *timHeader = (TIMHeader *)buffer;
+
+ if (timHeader->deleteBufferFlag == 0xBABE) {
+ delete[] buffer;
+ }
+}
} // end of namespace Kyra