diff options
Diffstat (limited to 'engines/agos')
-rw-r--r-- | engines/agos/agos.h | 39 | ||||
-rw-r--r-- | engines/agos/pn.cpp | 10 | ||||
-rw-r--r-- | engines/agos/script_pn.cpp | 117 |
3 files changed, 81 insertions, 85 deletions
diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 263811b78a..536c1ca3ab 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -1265,20 +1265,6 @@ protected: #ifdef ENABLE_PN class AGOSEngine_PN : public AGOSEngine { - struct StackFrame { - StackFrame *nextframe; - int16 flag[6]; - int16 param[8]; - int16 classnum; - uint8 *linpos; - uint8 *lbase; - int16 ll; - int16 linenum; - int16 process; - jmp_buf *savearea; - StackFrame() { memset(this, 0, sizeof(*this)); } - }; - virtual Common::Error go(); void demoSeq(); @@ -1358,8 +1344,30 @@ public: void opn_opcode62(); void opn_opcode63(); +protected: + struct StackFrame { + StackFrame *nextframe; + int16 flag[6]; + int16 param[8]; + int16 classnum; + uint8 *linpos; + uint8 *lbase; + int16 ll; + int16 linenum; + int16 process; + int tagOfParentDoline; ///< tag of the doline "instance" to which this StackFrame belongs + StackFrame() { memset(this, 0, sizeof(*this)); } + }; + + StackFrame *_stackbase; + int _tagOfActiveDoline; ///< tag of the active doline "instance" + int _dolineReturnVal; + + jmp_buf _loadfail; + + byte *_dataBase, *_textBase; uint32 _dataBaseSize, _textBaseSize; @@ -1404,8 +1412,6 @@ public: int _linembr; uint8 *_linebase; uint8 *_workptr; - jmp_buf *_cjmpbuff; - jmp_buf _loadfail; uint16 getptr(uint32 pos); uint32 getlong(uint32 pos); @@ -1429,7 +1435,6 @@ public: void addstack(int type); void dumpstack(); - void junkstack(); void popstack(int type); void funccpy(int *store); void funcentry(int *storestore, int procn); diff --git a/engines/agos/pn.cpp b/engines/agos/pn.cpp index d92efa9077..6ba5e8c891 100644 --- a/engines/agos/pn.cpp +++ b/engines/agos/pn.cpp @@ -35,6 +35,10 @@ namespace AGOS { AGOSEngine_PN::AGOSEngine_PN(OSystem *system) : AGOSEngine(system) { + _stackbase = 0; + _tagOfActiveDoline = 0; + _dolineReturnVal = 0; + _dataBase = 0; _dataBaseSize = 0; _textBase = 0; @@ -70,7 +74,7 @@ AGOSEngine_PN::AGOSEngine_PN(OSystem *system) _objects = 0; _objectCountS = 0; - _bp = 0; + _bp = 0; _xofs = 0; _havinit = 0; _seed = 0; @@ -84,16 +88,12 @@ AGOSEngine_PN::AGOSEngine_PN(OSystem *system) _linebase = 0; _workptr = 0; - - _cjmpbuff = NULL; } AGOSEngine_PN::~AGOSEngine_PN() { free(_dataBase); free(_textBase); - free(_cjmpbuff); - free(_stackbase); } const byte egaPalette[48] = { diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp index 4f9aab2965..116f1e1975 100644 --- a/engines/agos/script_pn.cpp +++ b/engines/agos/script_pn.cpp @@ -324,8 +324,8 @@ void AGOSEngine_PN::opn_opcode24() { // That value then is returned to actCallD, which once again // returns it. In the end, this amounts to a setScriptReturn(true) // (but possibly in a different level than the current one). - longjmp(*(_stackbase->savearea), 2); - setScriptReturn(false); + _dolineReturnVal = 2; + _tagOfActiveDoline = _stackbase->tagOfParentDoline; } void AGOSEngine_PN::opn_opcode25() { @@ -334,13 +334,13 @@ void AGOSEngine_PN::opn_opcode25() { // That value then is returned to actCallD, which once again // returns it. In the end, this amounts to a setScriptReturn(false) // (but possibly in a different level than the current one). - longjmp(*(_stackbase->savearea), 1); - setScriptReturn(false); + _dolineReturnVal = 1; + _tagOfActiveDoline = _stackbase->tagOfParentDoline; } void AGOSEngine_PN::opn_opcode26() { while ((_stackbase != NULL) && (_stackbase->classnum != kJmpClassNum)) - junkstack(); + dumpstack(); dumpstack(); setScriptReturn(true); } @@ -353,16 +353,16 @@ void AGOSEngine_PN::opn_opcode27() { void AGOSEngine_PN::opn_opcode28() { addstack(varval()); - _stackbase->savearea = _cjmpbuff; + _stackbase->tagOfParentDoline = _tagOfActiveDoline; setScriptReturn(false); } void AGOSEngine_PN::opn_opcode29() { popstack(varval()); - // Jump back to the last doline indicated by the top stackfram. + // Jump back to the last doline indicated by the top stackframe. // The -1 tells it to simply go on with its business. - longjmp(*(_stackbase->savearea), -1); - setScriptReturn(false); + _dolineReturnVal = -1; + _tagOfActiveDoline = _stackbase->tagOfParentDoline; } void AGOSEngine_PN::opn_opcode30() { @@ -520,19 +520,32 @@ void AGOSEngine_PN::opn_opcode39() { } void AGOSEngine_PN::opn_opcode40() { - setScriptReturn(doaction() | doaction()); + int a = doaction(); + if (_dolineReturnVal != 0) + return; + int b = doaction(); + setScriptReturn(a | b); } void AGOSEngine_PN::opn_opcode41() { - setScriptReturn(doaction() & doaction()); + int a = doaction(); + if (_dolineReturnVal != 0) + return; + int b = doaction(); + setScriptReturn(a & b); } void AGOSEngine_PN::opn_opcode42() { - setScriptReturn(doaction() ^ doaction()); + int a = doaction(); + if (_dolineReturnVal != 0) + return; + int b = doaction(); + setScriptReturn(a ^ b); } void AGOSEngine_PN::opn_opcode43() { - setScriptReturn(!(doaction())); + int a = doaction(); + setScriptReturn(!a); } void AGOSEngine_PN::opn_opcode44() { @@ -874,41 +887,14 @@ int AGOSEngine_PN::doaction() { } int AGOSEngine_PN::doline(int needsave) { - int x; - jmp_buf *old_jmpbuf = NULL; - jmp_buf *mybuf; + assert(!_stackbase == !needsave); - mybuf = (jmp_buf *)malloc(sizeof(jmp_buf)); - if (mybuf == NULL) - error("doline: Out of memory - stack overflow"); - - x = setjmp(*mybuf); - // Looking at the longjmp calls below, x can be -1, 1 or 2 - // (and of course 0 when it returns directly, as always). - if (x > 0) { - dumpstack(); - // Restore the active jmpbuf to its previous value, - // then return the longjmp value (will be 2-1=1 or 1-1=0). - _cjmpbuff = old_jmpbuf; - free((char *)mybuf); - return (x - 1); - } + int x; + int myTag = ++_tagOfActiveDoline; // Obtain a unique tag for this doline invocation + _dolineReturnVal = 0; - if (x == -1) { - // Make this doline instance the active one (again). - // This is used to "return" over possibly multiple - // layers of nested script invocations. - // Kind of like throwing an exception. - _cjmpbuff = mybuf; - goto carryon; - } - - // Remember the previous active jmpbuf (gets restored - // above when a longjmp with a positive param occurs). - old_jmpbuf = _cjmpbuff; - _cjmpbuff = mybuf; if (needsave) - _stackbase->savearea = mybuf; + _stackbase->tagOfParentDoline = myTag; do { _linct = ((*_linebase) & 127) - 1; @@ -919,9 +905,25 @@ int AGOSEngine_PN::doline(int needsave) { goto skipln; } -carryon: do { x = doaction(); + + if (_dolineReturnVal != 0) { + if (_tagOfActiveDoline != myTag) + return 0; + + x = _dolineReturnVal; + _dolineReturnVal = 0; + + if (x > 0) { + dumpstack(); + // Restore the active jmpbuf to its previous value, + // then return the longjmp value (will be 2-1=1 or 1-1=0). + _tagOfActiveDoline = myTag - 1; + return (x - 1); + } + } + } while (x && !shouldQuit()); skipln: @@ -1063,7 +1065,7 @@ void AGOSEngine_PN::addstack(int type) { StackFrame *a; int i; - a = (StackFrame *)malloc(sizeof(StackFrame)); + a = (StackFrame *)calloc(1, sizeof(StackFrame)); if (a == NULL) error("addstack: Out of memory - stack overflow"); @@ -1093,24 +1095,13 @@ void AGOSEngine_PN::dumpstack() { _stackbase = a; } -void AGOSEngine_PN::junkstack() { - StackFrame *a; - - if (_stackbase == NULL) - error("junkstack: Stack underflow or unknown longjmp"); - - a = _stackbase->nextframe; - if (_stackbase->classnum == kJmpClassNum) - free((char *)_stackbase->savearea); - free((char *)_stackbase); - _stackbase = a; -} - void AGOSEngine_PN::popstack(int type) { - int i; + int i = 0; - while ((_stackbase != NULL) && (_stackbase->classnum != type)) - junkstack(); + while ((_stackbase != NULL) && (_stackbase->classnum != type)) { + dumpstack(); + ++i; + } if (_stackbase == NULL) error("popstack: Stack underflow or unknown longjmp"); |