diff options
author | Andrew Kurushin | 2005-01-22 14:43:49 +0000 |
---|---|---|
committer | Andrew Kurushin | 2005-01-22 14:43:49 +0000 |
commit | 4e7d58c843680463b3c4d2cf39aa415dcfe024e5 (patch) | |
tree | 25ae7fb57ae469ae4d48d1ed925ac9eb0e5c6f62 | |
parent | f3b62a9ed70c3161ec6af307d5b87b6df1013550 (diff) | |
download | scummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.tar.gz scummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.tar.bz2 scummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.zip |
rewritten 15 opcodes
svn-id: r16615
-rw-r--r-- | saga/script.h | 18 | ||||
-rw-r--r-- | saga/sthread.cpp | 244 |
2 files changed, 123 insertions, 139 deletions
diff --git a/saga/script.h b/saga/script.h index 7ab7fa3d99..ed58dffaf5 100644 --- a/saga/script.h +++ b/saga/script.h @@ -137,6 +137,22 @@ enum OpCodes { opEnter = 0x1A, opReturn = 0x1B, opReturnV = 0x1C, + opJmp = 0x1D, + opJmpTrueV = 0x1E, + opJmpFalseV = 0x1F, + opJmpTrue = 0x20, + opJmpFalse = 0x21, + opJmpSwitch = 0x22, +//... + opJmpRandom = 0x24, + opNegate = 0x25, + opNot = 0x26, + opCompl = 0x27, + opIncV = 0x28, + opDecV = 0x29, + opPostInc = 0x2A, + opPostDec = 0x2B, + //... opSpeak = 0x53, opDialogBegin = 0x54, @@ -226,7 +242,7 @@ public: uint _sleepTime; void *_threadObj; // which object we're handling - uint16 _returnValue; + int16 _returnValue; uint16 _instructionOffset; // Instruction offset diff --git a/saga/sthread.cpp b/saga/sthread.cpp index 3e89df19d4..ca2e106bbe 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -165,6 +165,7 @@ int Script::SThreadDebugStep() { } void Script::runThread(ScriptThread *thread, uint instructionLimit) { + const char*operandName; uint instructionCount; uint16 savedInstructionOffset; @@ -182,7 +183,7 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { uint16 data; int debug_print = 0; - int n_buf; +// int n_buf; // int bitstate; int operandChar; int i; @@ -213,14 +214,11 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { #define CASEOP(opName) case opName: \ if (operandChar == opName) { \ - debug(8, #opName); \ - _vm->_console->DebugPrintf(#opName); \ + operandName = #opName; \ } -// debug print (opCode name etc) should be placed here -// SDebugPrintInstr(thread) - debug(8, "Executing thread offset: %lu (%x) stack: %d", thread->_instructionOffset, operandChar, thread->pushedSize()); + operandName=""; switch (operandChar) { CASEOP(opNextBlock) // Some sort of "jump to the start of the next memory @@ -243,8 +241,8 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { break; CASEOP(opConstint) CASEOP(opStrlit) - param1 = scriptS.readUint16LE(); - thread->push(param1); + iparam1 = scriptS.readSint16LE(); + thread->push(iparam1); break; // DATA INSTRUCTIONS @@ -257,8 +255,8 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { break; CASEOP(opGetInt) addr = thread->baseAddress(scriptS.readByte()); - param1 = scriptS.readUint16LE(); - addr += param1; + iparam1 = scriptS.readSint16LE(); + addr += iparam1; thread->push(*((uint16*)addr)); break; CASEOP(opPutFlag) @@ -274,8 +272,8 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { break; CASEOP(opPutInt) addr = thread->baseAddress(scriptS.readByte()); - param1 = scriptS.readUint16LE(); - addr += param1; + iparam1 = scriptS.readSint16LE(); + addr += iparam1; *(uint16*)addr = thread->stackTop(); break; CASEOP(opPutFlagV) @@ -291,13 +289,12 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { break; CASEOP(opPutIntV) addr = thread->baseAddress(scriptS.readByte()); - param1 = scriptS.readUint16LE(); - addr += param1; + iparam1 = scriptS.readSint16LE(); + addr += iparam1; *(uint16*)addr = thread->pop(); break; // CONTROL INSTRUCTIONS - CASEOP(opCall) argumentsCount = scriptS.readByte(); param1 = scriptS.readByte(); @@ -305,8 +302,8 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { error("Script::runThread param1 != kAddressModule"); } addr = thread->baseAddress(param1); - param1 = scriptS.readUint16LE(); - addr += param1; + iparam1 = scriptS.readSint16LE(); + addr += iparam1; thread->push(argumentsCount); param2 = scriptS.pos(); @@ -314,7 +311,7 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { // counter as a pointer here. But I don't think // we will have to do that. thread->push(param2); - thread->_instructionOffset = param1; + thread->_instructionOffset = iparam1; break; CASEOP(opCcall) @@ -328,7 +325,7 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { debug(8, "Calling 0x%X %s", functionNumber, _scriptFunctionsList[functionNumber].scriptFunctionName); scriptFunction = _scriptFunctionsList[functionNumber].scriptFunction; scriptFunctionReturnValue = (this->*scriptFunction)(thread, argumentsCount); - if (scriptFunctionReturnValue != SUCCESS) { + if (scriptFunctionReturnValue != SUCCESS) { // TODO: scriptFunctionReturnValue should be ignored & removed _vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->_instructionOffset, scriptFunctionReturnValue); } @@ -347,7 +344,7 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { CASEOP(opEnter) thread->push(thread->_frameIndex); thread->_frameIndex = thread->_stackTopIndex; - thread->_stackTopIndex -= (scriptS.readUint16LE() / 2); + thread->_stackTopIndex -= (scriptS.readSint16LE() / 2); break; CASEOP(opReturn) thread->_returnValue = thread->pop(); @@ -355,14 +352,13 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { thread->_stackTopIndex = thread->_frameIndex; thread->_frameIndex = thread->pop(); if (thread->pushedSize() == 0) { - _vm->_console->DebugPrintf("Script execution complete.\n"); thread->_flags |= kTFlagFinished; - return; + break; } else { thread->_instructionOffset = thread->pop(); - param1 = thread->pop(); - param1 +=param1; - while (param1--) { + iparam1 = thread->pop(); + iparam1 += iparam1; + while (iparam1--) { thread->pop(); } @@ -373,139 +369,101 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { break; // BRANCH INSTRUCTIONS - - // (JMP): Unconditional jump - case 0x1D: + CASEOP(opJmp) param1 = scriptS.readUint16LE(); - thread->_instructionOffset = (unsigned long)param1; + thread->_instructionOffset = param1; break; - // (JNZP): Jump if nonzero + POP - case 0x1E: + CASEOP(opJmpTrueV) param1 = scriptS.readUint16LE(); - data = thread->pop(); - if (data) { - thread->_instructionOffset = (unsigned long)param1; + if (thread->pop()) { + thread->_instructionOffset = param1; } break; - // (JZP): Jump if zero + POP - case 0x1F: + CASEOP(opJmpFalseV) param1 = scriptS.readUint16LE(); - data = thread->pop(); - if (!data) { - thread->_instructionOffset = (unsigned long)param1; + if (!thread->pop()) { + thread->_instructionOffset = param1; } break; - // (JNZ): Jump if nonzero - case 0x20: + CASEOP(opJmpTrue) param1 = scriptS.readUint16LE(); - data = thread->stackTop(); - if (data) { - thread->_instructionOffset = (unsigned long)param1; + if (thread->stackTop()) { + thread->_instructionOffset = param1; } break; - // (JZ): Jump if zero - case 0x21: + CASEOP(opJmpFalse) param1 = scriptS.readUint16LE(); - data = thread->stackTop(); - if (!data) { - thread->_instructionOffset = (unsigned long)param1; + if (!thread->stackTop()) { + thread->_instructionOffset = param1; } break; - // (SWCH): Switch - case 0x22: - { - int n_switch; - uint16 switch_num; - unsigned int switch_jmp; - unsigned int default_jmp; - int case_found = 0; - - data = thread->pop(); - n_switch = scriptS.readUint16LE(); - - for (i = 0; i < n_switch; i++) { - switch_num = scriptS.readUint16LE(); - switch_jmp = scriptS.readUint16LE(); - // Found the specified case - if (data == switch_num) { - thread->_instructionOffset = switch_jmp; - case_found = 1; - break; - } - } - - // Jump to default case - if (!case_found) { - default_jmp = scriptS.readUint16LE(); - thread->_instructionOffset = default_jmp; + CASEOP(opJmpSwitch) + iparam1 = scriptS.readSint16LE(); + param1 = thread->pop(); + while (iparam1--) { + param2 = scriptS.readUint16LE(); + thread->_instructionOffset = scriptS.readUint16LE(); + if (param2 == param1) { + break; } } + if (iparam1 < 0) { + thread->_instructionOffset = scriptS.readUint16LE(); + } break; - // (RJMP): Random branch - case 0x24: - { - // Supposedly the number of possible branches. - // The original interpreter ignores it. - scriptS.readUint16LE(); - - uint16 probability = _vm->_rnd.getRandomNumber(scriptS.readUint16LE() - 1); - - while (1) { - uint16 branch_probability = scriptS.readUint16LE(); - uint16 offset = scriptS.readUint16LE(); - - if (branch_probability > probability) { - thread->_instructionOffset = offset; - break; - } - - probability -= branch_probability; + CASEOP(opJmpRandom) + // Supposedly the number of possible branches. + // The original interpreter ignores it. + scriptS.readUint16LE(); + iparam1 = scriptS.readSint16LE(); + iparam1 = _vm->_rnd.getRandomNumber(iparam1 - 1); + while (1) { + iparam2 = scriptS.readSint16LE(); + thread->_instructionOffset = scriptS.readUint16LE(); + + iparam1 -= iparam2; + if (iparam1 < 0) { + break; } } break; // UNARY INSTRUCTIONS - - // (NEG) Negate stack by 2's complement - case 0x25: - data = thread->pop(); - thread->push(-(int)data); + CASEOP(opNegate) + thread->push(-thread->pop()); break; - // (TSTZ) Test for zero - case 0x26: - data = thread->pop(); - thread->push(!data); + CASEOP(opNot) + thread->push(!thread->pop()); break; - // (NOT) Binary not - case 0x27: - data = thread->pop(); - thread->push(~data); + CASEOP(opCompl) + thread->push(~thread->pop()); break; - case 0x28: // inc_v increment, don't push - n_buf = scriptS.readByte(); - param1 = scriptS.readUint16LE(); - //getWord(n_buf, param1, &data); - //putWord(n_buf, param1, data + 1); + + CASEOP(opIncV) + addr = thread->baseAddress(scriptS.readByte()); + iparam1 = scriptS.readSint16LE(); + addr += iparam1; + *(uint16*)addr += 1; break; - case 0x29: // dec_v decrement, don't push - n_buf = scriptS.readByte(); - param1 = scriptS.readUint16LE(); - //getWord(n_buf, param1, &data); - //putWord(n_buf, param1, data - 1); + CASEOP(opDecV) + addr = thread->baseAddress(scriptS.readByte()); + iparam1 = scriptS.readSint16LE(); + addr += iparam1; + *(uint16*)addr -= 1; break; - case 0x2A: // postinc - n_buf = scriptS.readByte(); - param1 = scriptS.readUint16LE(); - //getWord(n_buf, param1, &data); -// thread->push(data); - //putWord(n_buf, param1, data + 1); + CASEOP(opPostInc) + addr = thread->baseAddress(scriptS.readByte()); + iparam1 = scriptS.readSint16LE(); + addr += iparam1; + thread->push(*(int16*)addr); + *(uint16*)addr += 1; break; - case 0x2B: // postdec - n_buf = scriptS.readByte(); - param1 = scriptS.readUint16LE(); - //getWord(n_buf, param1, &data); -// thread->push(data); - //putWord(n_buf, param1, data - 1); + CASEOP(opPostDec) + addr = thread->baseAddress(scriptS.readByte()); + iparam1 = scriptS.readSint16LE(); + addr += iparam1; + thread->push(*(int16*)addr); + *(uint16*)addr -= 1; break; // ARITHMETIC INSTRUCTIONS @@ -778,19 +736,29 @@ void Script::runThread(ScriptThread *thread, uint instructionLimit) { scriptError(thread, "Invalid opcode encountered"); return; } + debug(8, operandName); + _vm->_console->DebugPrintf("%s\n", operandName); - // Set instruction offset only if a previous instruction didn't branch - if (savedInstructionOffset == thread->_instructionOffset) { - thread->_instructionOffset = scriptS.pos(); + + if (thread->_flags & (kTFlagFinished | kTFlagAborted)) { + _vm->_console->DebugPrintf("Script finished\n"); + break; } else { - if (thread->_instructionOffset >= scriptS.size()) { - scriptError(thread, "Out of range script execution"); - return; - } - scriptS.seek(thread->_instructionOffset); + // Set instruction offset only if a previous instruction didn't branch + if (savedInstructionOffset == thread->_instructionOffset) { + thread->_instructionOffset = scriptS.pos(); + } else { + if (thread->_instructionOffset >= scriptS.size()) { + scriptError(thread, "Out of range script execution"); + return; + } + + scriptS.seek(thread->_instructionOffset); + } } + if (unhandled) { // TODO: remove it scriptError(thread, "Unhandled opcode"); } |