From 64a91605a11152e2b1c54eba0e5ae9d514530028 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 9 Oct 2004 07:39:46 +0000 Subject: Initial attempt at fixing the SData problem. I'm still not sure exactly how to fix the script "static" area, though. In addition, initialise a few variables, and test for NULL-ness of a few pointers. This fixes a few crashes I saw with yesterday's CVS snapshot. There's still an unexpected scene change in the intro (I think it triggers on Rhene walking too close to the exit), but at least it no longer crashes. svn-id: r15484 --- saga/isomap.cpp | 1 + saga/render.cpp | 6 ++++-- saga/scene.cpp | 19 ++++++++++++++++--- saga/script.cpp | 2 +- saga/script.h | 10 ++++++++++ saga/sdata.cpp | 33 ++++++++++++++++++++++++++------- saga/sthread.cpp | 18 +++++++++++++++--- saga/xref.txt | 5 ++++- 8 files changed, 77 insertions(+), 17 deletions(-) diff --git a/saga/isomap.cpp b/saga/isomap.cpp index ccb2398bbb..bf8a6ef2b2 100644 --- a/saga/isomap.cpp +++ b/saga/isomap.cpp @@ -34,6 +34,7 @@ namespace Saga { IsoMap::IsoMap(Gfx *gfx) { _gfx = gfx; _init = 1; + _tiles_loaded = 0; } int IsoMap::loadTileset(const byte *tileres_p, size_t tileres_len) { diff --git a/saga/render.cpp b/saga/render.cpp index 10c26a661c..f401611412 100644 --- a/saga/render.cpp +++ b/saga/render.cpp @@ -134,8 +134,10 @@ int Render::drawScene() { // Display scene maps, if applicable if (getFlags() & RF_OBJECTMAP_TEST) { - _vm->_scene->_objectMap->draw(backbuf_surface, mouse_pt, _vm->_gfx->getWhite(), _vm->_gfx->getBlack()); - _vm->_scene->_actionMap->draw(backbuf_surface, _vm->_gfx->matchColor(R_RGB_RED)); + if (_vm->_scene->_objectMap) + _vm->_scene->_objectMap->draw(backbuf_surface, mouse_pt, _vm->_gfx->getWhite(), _vm->_gfx->getBlack()); + if (_vm->_scene->_actionMap) + _vm->_scene->_actionMap->draw(backbuf_surface, _vm->_gfx->matchColor(R_RGB_RED)); } // Draw queued actors diff --git a/saga/scene.cpp b/saga/scene.cpp index 13ef26c975..f2eadaea0b 100644 --- a/saga/scene.cpp +++ b/saga/scene.cpp @@ -138,6 +138,8 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { _animEntries = 0; _animList = NULL; _sceneProc = NULL; + _objectMap = NULL; + _actionMap = NULL; memset(&_bg, 0, sizeof(_bg)); memset(&_bgMask, 0, sizeof(_bgMask)); @@ -858,6 +860,9 @@ int Scene::endScene() { delete _objectMap; delete _actionMap; + _objectMap = NULL; + _actionMap = NULL; + ys_dll_destroy(_animList); _animEntries = 0; @@ -984,6 +989,12 @@ int Scene::defaultScene(int param, R_SCENE_INFO *scene_info) { _vm->_console->print("Thread creation failed."); break; } + + _startScriptThread->threadVars[kVarAction] = 0; + _startScriptThread->threadVars[kVarObject] = _sceneNumber; + _startScriptThread->threadVars[kVarWithObject] = 0; // TOTO: entrance + _startScriptThread->threadVars[kVarActor] = 0; + _vm->_script->SThreadExecute(_startScriptThread, _desc.startScriptNum); _vm->_script->SThreadCompleteThread(); } @@ -998,7 +1009,7 @@ int Scene::defaultScene(int param, R_SCENE_INFO *scene_info) { _vm->_events->queue(&event); } else _vm->_music->stop(); - //break; //HACK to disable faery script + if (_desc.sceneScriptNum > 0) { R_SCRIPT_THREAD *_sceneScriptThread; @@ -1010,8 +1021,10 @@ int Scene::defaultScene(int param, R_SCENE_INFO *scene_info) { break; } - // TODO: Set up thread variables. First we'll need to - // add the concept of thread variables... + _sceneScriptThread->threadVars[kVarAction] = 0; + _sceneScriptThread->threadVars[kVarObject] = _sceneNumber; + _sceneScriptThread->threadVars[kVarWithObject] = 0; // TODO: entrance + _sceneScriptThread->threadVars[kVarActor] = 0; // TODO: VERB_ENTER _vm->_script->SThreadExecute(_sceneScriptThread, _desc.sceneScriptNum); } diff --git a/saga/script.cpp b/saga/script.cpp index d2b25f699e..6d4f11f6b8 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -112,7 +112,7 @@ Script::Script() { // Skip the unused portion of the structure for (j = scriptS.pos(); j < prevTell + _scriptLUTEntryLen; j++) { if (scriptS.readByte() != 0) - error("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", i, j); + warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", i, j); } } diff --git a/saga/script.h b/saga/script.h index 91f4317964..1ca262d060 100644 --- a/saga/script.h +++ b/saga/script.h @@ -68,6 +68,13 @@ struct R_SEMAPHORE { int hold_count; }; +enum { + kVarObject = 0, + kVarWithObject, + kVarAction, + kVarActor +}; + struct R_SCRIPT_THREAD { int executing; @@ -87,6 +94,8 @@ struct R_SCRIPT_THREAD { int stackPtr; int framePtr; + SDataWord_T threadVars[4]; + SDataWord_T retVal; SDataWord_T stackTop() { @@ -203,6 +212,7 @@ public: int SThreadDestroy(R_SCRIPT_THREAD *thread); private: + void setFramePtr(R_SCRIPT_THREAD *thread, int newPtr); unsigned char *SThreadGetReadPtr(R_SCRIPT_THREAD *thread); unsigned long SThreadGetReadOffset(const byte *read_p); size_t SThreadGetReadLen(R_SCRIPT_THREAD *thread); diff --git a/saga/sdata.cpp b/saga/sdata.cpp index bcdaa9d99b..e1a26a8b8c 100644 --- a/saga/sdata.cpp +++ b/saga/sdata.cpp @@ -30,29 +30,48 @@ namespace Saga { SData::SData() { - unsigned int i; void *alloc_ptr; + int i; debug(0, "Initializing script data buffers"); + for (i = 0; i < R_SCRIPT_DATABUF_NUM; i++) { alloc_ptr = malloc(sizeof *_vm->_script->dataBuffer(0)); + if (alloc_ptr == NULL) { error("Couldn't allocate memory for script data buffer %d", i); } _vm->_script->setBuffer(i, (R_SCRIPT_DATABUF *)alloc_ptr); - alloc_ptr = calloc(R_SCRIPT_DATABUF_LEN, sizeof(SDataWord_T)); + } - if (alloc_ptr == NULL) { - error("Couldn't allocate memory for script data buffer %d", i); - } + alloc_ptr = calloc(R_SCRIPT_DATABUF_LEN, sizeof(SDataWord_T)); + + if (alloc_ptr == NULL) { + error("Couldn't allocate memory for shared script buffer"); + } + + // Buffer 0 is the shared data buffer. All scripts can access this. + _vm->_script->dataBuffer(0)->len = R_SCRIPT_DATABUF_LEN; + _vm->_script->dataBuffer(0)->data = (SDataWord_T *)alloc_ptr; + + // FIXME: Buffer 1 is the script's static area. The original + // interpreter uses part of buffer 0 for this, but I don't yet + // understand quite how. + + _vm->_script->setBuffer(1, (R_SCRIPT_DATABUF *)alloc_ptr); + _vm->_script->dataBuffer(1)->len = R_SCRIPT_DATABUF_LEN; + _vm->_script->dataBuffer(1)->data = (SDataWord_T *)alloc_ptr; - _vm->_script->dataBuffer(i)->len = R_SCRIPT_DATABUF_LEN; - _vm->_script->dataBuffer(i)->data = (SDataWord_T *)alloc_ptr; + // Remaining buffers are per-script. + for (i = 2; i < R_SCRIPT_DATABUF_NUM; i++) { + _vm->_script->dataBuffer(i)->len = 0; + _vm->_script->dataBuffer(i)->data = NULL; } } SData::~SData() { + // TODO: Free the script data buffers } int SData::getWord(int n_buf, int n_word, SDataWord_T *data) { diff --git a/saga/sthread.cpp b/saga/sthread.cpp index 68adc7e565..68f80ff054 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -35,6 +35,12 @@ namespace Saga { +void Script::setFramePtr(R_SCRIPT_THREAD *thread, int newPtr) { + thread->framePtr = newPtr; + dataBuffer(3)->len = 2 * (ARRAYSIZE(thread->stackBuf) - thread->framePtr); + dataBuffer(3)->data = (SDataWord_T *) &(thread->stackBuf[newPtr]); +} + R_SCRIPT_THREAD *Script::SThreadCreate() { YS_DL_NODE *new_node; R_SCRIPT_THREAD *new_thread; @@ -49,7 +55,10 @@ R_SCRIPT_THREAD *Script::SThreadCreate() { } new_thread->stackPtr = ARRAYSIZE(new_thread->stackBuf) - 1; - new_thread->framePtr = ARRAYSIZE(new_thread->stackBuf) - 1; + setFramePtr(new_thread, new_thread->stackPtr); + + dataBuffer(4)->len = sizeof(new_thread->threadVars); + dataBuffer(4)->data = new_thread->threadVars; new_node = ys_dll_add_head(threadList(), new_thread, sizeof *new_thread); @@ -199,6 +208,9 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) { MemoryReadStream scriptS(currentScript()->bytecode->bytecode_p, currentScript()->bytecode->bytecode_len); + dataBuffer(2)->len = currentScript()->bytecode->bytecode_len; + dataBuffer(2)->data = (SDataWord_T *) currentScript()->bytecode->bytecode_p; + scriptS.seek(thread->i_offset); for (instr_count = 0; instr_count < instr_limit; instr_count++) { @@ -353,7 +365,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) { break; case 0x1A: // (ENTR) Enter the dragon thread->push(thread->framePtr); - thread->framePtr = thread->stackPtr; + setFramePtr(thread, thread->stackPtr); param1 = scriptS.readUint16LE(); thread->stackPtr -= (param1 / 2); break; @@ -362,7 +374,7 @@ int Script::SThreadRun(R_SCRIPT_THREAD *thread, int instr_limit, int msec) { // FALL THROUGH case 0x1C: // Return with void thread->stackPtr = thread->framePtr; - thread->framePtr = thread->pop(); + setFramePtr(thread, thread->pop()); if (thread->stackSize() == 0) { _vm->_console->print("Script execution complete."); thread->executing = 0; diff --git a/saga/xref.txt b/saga/xref.txt index 4a26f4a2d3..ad1415287b 100644 --- a/saga/xref.txt +++ b/saga/xref.txt @@ -65,4 +65,7 @@ Interp.c ModuleEntry->codeID _scriptLUT->script_rn ModuleEntry->strID _scriptLUT->diag_list_rn ModuleEntry->vtableID _scriptLUT->voice_lut_rn - + threadBase.theAction threadVars[kVarAction] + threadBase.theObject threadVars[kVarObject] + threadBase.withObject threadVars[kVarWithObject] + threadBase.theActor threadVars[kVarActor] -- cgit v1.2.3