diff options
author | Filippos Karapetis | 2012-06-23 21:38:46 +0300 |
---|---|---|
committer | Filippos Karapetis | 2012-06-23 21:45:26 +0300 |
commit | 20b677080881580706652b17dd5a4c3ed3e36c07 (patch) | |
tree | 299521363c9962767c2acc7f28a6bb4f8aa747de /engines | |
parent | c1eb93bc5a9866787f27add5ca1d821e1470a4be (diff) | |
download | scummvm-rg350-20b677080881580706652b17dd5a4c3ed3e36c07.tar.gz scummvm-rg350-20b677080881580706652b17dd5a4c3ed3e36c07.tar.bz2 scummvm-rg350-20b677080881580706652b17dd5a4c3ed3e36c07.zip |
SCI: Change the program counter (PC) to be a 32-bit variable
This is needed for future support of large SCI3 scripts. The program
counter is isolated and does not interfere with other parts of the VM,
plus it does not get stored in saved games, so it's pretty straightforward
to convert
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/console.cpp | 14 | ||||
-rw-r--r-- | engines/sci/console.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/script.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/script.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 15 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/vm_types.h | 43 |
8 files changed, 69 insertions, 19 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b0ed7e6225..40a6fd1415 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2913,7 +2913,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) { if (jumpTarget > farthestTarget) farthestTarget = jumpTarget; } - addr = disassemble(_engine->_gamestate, addr, printBWTag, printBytecode); + // TODO: Use a true 32-bit reg_t for the position (addr) + addr = disassemble(_engine->_gamestate, make_reg32(addr.getSegment(), addr.getOffset()), printBWTag, printBytecode); if (addr.isNull() && prevAddr < farthestTarget) addr = prevAddr + 1; // skip past the ret } while (addr.getOffset() > 0); @@ -2961,7 +2962,8 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { } do { - vpc = disassemble(_engine->_gamestate, vpc, printBWTag, printBytes); + // TODO: Use a true 32-bit reg_t for the position (vpc) + vpc = disassemble(_engine->_gamestate, make_reg32(vpc.getSegment(), vpc.getOffset()), printBWTag, printBytes); } while ((vpc.getOffset() > 0) && (vpc.getOffset() + 6 < size) && (--opCount)); return true; @@ -3652,10 +3654,14 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV relativeOffset = true; if (!scumm_strnicmp(str + 1, "PC", 2)) { - *dest = s->_executionStack.back().addr.pc; + // TODO: Handle 32-bit PC addresses + reg32_t pc = s->_executionStack.back().addr.pc; + *dest = make_reg(pc.getSegment(), (uint16)pc.getOffset()); offsetStr = str + 3; } else if (!scumm_strnicmp(str + 1, "P", 1)) { - *dest = s->_executionStack.back().addr.pc; + // TODO: Handle 32-bit PC addresses + reg32_t pc = s->_executionStack.back().addr.pc; + *dest = make_reg(pc.getSegment(), (uint16)pc.getOffset()); offsetStr = str + 2; } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { *dest = s->r_prev; diff --git a/engines/sci/console.h b/engines/sci/console.h index be17fdb728..1c54748842 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -33,7 +33,7 @@ namespace Sci { class SciEngine; struct List; -reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode); +reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printBytecode); bool isJumpOpcode(EngineState *s, reg_t pos, reg_t& jumpOffset); class Console : public GUI::Debugger { diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 80aaedfece..57334b89aa 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { +uint32 Script::validateExportFunc(int pubfunct, bool relocateSci3) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { @@ -396,7 +396,7 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { if (exportsAreWide) pubfunct *= 2; - uint16 offset; + uint32 offset; if (getSciVersion() != SCI_VERSION_3) { offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 9747f072c5..1fc8caf313 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -201,7 +201,7 @@ public: * @return NULL if the public function is invalid, its * offset into the script's segment otherwise */ - uint16 validateExportFunc(int pubfunct, bool relocateSci3); + uint32 validateExportFunc(int pubfunct, bool relocateSci3); /** * Marks the script as deleted. diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 04cbf1d97c..d3abb9ff41 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -68,7 +68,7 @@ const char *opcodeNames[] = { #endif // REDUCE_MEMORY_USAGE // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. -reg_t disassemble(EngineState *s, reg_t pos, bool printBWTag, bool printBytecode) { +reg_t disassemble(EngineState *s, reg32_t pos, bool printBWTag, bool printBytecode) { SegmentObj *mobj = s->_segMan->getSegment(pos.getSegment(), SEG_TYPE_SCRIPT); Script *script_entity = NULL; const byte *scr; @@ -347,7 +347,7 @@ void SciEngine::scriptDebug() { } if (_debugState.seeking != kDebugSeekNothing) { - const reg_t pc = s->xs->addr.pc; + const reg32_t pc = s->xs->addr.pc; SegmentObj *mobj = s->_segMan->getSegment(pc.getSegment(), SEG_TYPE_SCRIPT); if (mobj) { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a42606a6a6..5a2a39def2 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -233,7 +233,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP g_sci->checkExportBreakpoint(script, pubfunct); ExecStack xstack(calling_obj, calling_obj, sp, argc, argp, - seg, make_reg(seg, exportAddr), -1, pubfunct, -1, + seg, make_reg32(seg, exportAddr), -1, pubfunct, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); s->_executionStack.push_back(xstack); return &(s->_executionStack.back()); @@ -289,11 +289,12 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt ExecStackType stackType = EXEC_STACK_TYPE_VARSELECTOR; StackPtr curSP = NULL; - reg_t curFP = NULL_REG; + reg32_t curFP = make_reg32(0, 0); if (selectorType == kSelectorMethod) { stackType = EXEC_STACK_TYPE_CALL; curSP = sp; - curFP = funcp; + // TODO: Will this offset suffice for large SCI3 scripts? + curFP = make_reg32(funcp.getSegment(), funcp.getOffset()); sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over } @@ -327,7 +328,7 @@ static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, // Add stack frame to indicate we're executing a callk. // This is useful in debugger backtraces if this // kernel function calls a script itself. - ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, NULL_REG, + ExecStack xstack(NULL_REG, NULL_REG, NULL, argc, argv - 1, 0xFFFF, make_reg32(0, 0), kernelCallNr, -1, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_KERNEL); s->_executionStack.push_back(xstack); } @@ -818,11 +819,11 @@ void run_vm(EngineState *s) { StackPtr call_base = s->xs->sp - argc; s->xs->sp[1].incOffset(s->r_rest); - uint16 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0]; + uint32 localCallOffset = s->xs->addr.pc.getOffset() + opparams[0]; ExecStack xstack(s->xs->objp, s->xs->objp, s->xs->sp, (call_base->requireUint16()) + s->r_rest, call_base, - s->xs->local_segment, make_reg(s->xs->addr.pc.getSegment(), localCallOffset), + s->xs->local_segment, make_reg32(s->xs->addr.pc.getSegment(), localCallOffset), NULL_SELECTOR, -1, localCallOffset, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); @@ -1117,7 +1118,7 @@ void run_vm(EngineState *s) { switch (g_sci->_features->detectLofsType()) { case SCI_VERSION_0_EARLY: - r_temp.setOffset(s->xs->addr.pc.getOffset() + opparams[0]); + r_temp.setOffset((uint16)s->xs->addr.pc.getOffset() + opparams[0]); break; case SCI_VERSION_1_MIDDLE: r_temp.setOffset(opparams[0]); diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index f2d225b1d8..a0fd6689df 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -82,7 +82,7 @@ struct ExecStack { union { ObjVarRef varp; // Variable pointer for r/w access - reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element + reg32_t pc; // Pointer to the initial program counter. Not accurate for the TOS element } addr; StackPtr fp; // Frame pointer @@ -102,7 +102,7 @@ struct ExecStack { reg_t* getVarPointer(SegManager *segMan) const; ExecStack(reg_t objp_, reg_t sendp_, StackPtr sp_, int argc_, StackPtr argp_, - SegmentId localsSegment_, reg_t pc_, Selector debugSelector_, + SegmentId localsSegment_, reg32_t pc_, Selector debugSelector_, int debugExportId_, int debugLocalCallOffset_, int debugOrigin_, ExecStackType type_) { objp = objp_; diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 2995ba3c12..9a7589e9a7 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -169,6 +169,49 @@ static inline reg_t make_reg(SegmentId segment, uint16 offset) { #define PRINT_REG(r) (0xffff) & (unsigned) (r).getSegment(), (unsigned) (r).getOffset() +// A true 32-bit reg_t +struct reg32_t { + // Segment and offset. These should never be accessed directly + SegmentId _segment; + uint32 _offset; + + inline SegmentId getSegment() const { + return _segment; + } + + inline void setSegment(SegmentId segment) { + _segment = segment; + } + + inline uint32 getOffset() const { + return _offset; + } + + inline void setOffset(uint32 offset) { + _offset = offset; + } + + inline void incOffset(int32 offset) { + setOffset(getOffset() + offset); + } + + // Comparison operators + bool operator==(const reg32_t &x) const { + return (getOffset() == x.getOffset()) && (getSegment() == x.getSegment()); + } + + bool operator!=(const reg32_t &x) const { + return (getOffset() != x.getOffset()) || (getSegment() != x.getSegment()); + } +}; + +static inline reg32_t make_reg32(SegmentId segment, uint32 offset) { + reg32_t r; + r.setSegment(segment); + r.setOffset(offset); + return r; +} + // Stack pointer type typedef reg_t *StackPtr; |