From af3b84c29746a2f38de8d009b8e7149470564726 Mon Sep 17 00:00:00 2001 From: Oystein Eftevaag Date: Sun, 14 Oct 2007 16:58:11 +0000 Subject: TIM file loading/unloading for HoF svn-id: r29217 --- engines/kyra/kyra_v2.cpp | 13 ++-- engines/kyra/kyra_v2.h | 59 +++++++++++++++--- engines/kyra/script.cpp | 5 -- engines/kyra/script.h | 6 ++ engines/kyra/script_v2.cpp | 16 ++++- engines/kyra/text_v2.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++-- 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 -- cgit v1.2.3