aboutsummaryrefslogtreecommitdiff
path: root/saga
diff options
context:
space:
mode:
authorAndrew Kurushin2005-01-22 14:43:49 +0000
committerAndrew Kurushin2005-01-22 14:43:49 +0000
commit4e7d58c843680463b3c4d2cf39aa415dcfe024e5 (patch)
tree25ae7fb57ae469ae4d48d1ed925ac9eb0e5c6f62 /saga
parentf3b62a9ed70c3161ec6af307d5b87b6df1013550 (diff)
downloadscummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.tar.gz
scummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.tar.bz2
scummvm-rg350-4e7d58c843680463b3c4d2cf39aa415dcfe024e5.zip
rewritten 15 opcodes
svn-id: r16615
Diffstat (limited to 'saga')
-rw-r--r--saga/script.h18
-rw-r--r--saga/sthread.cpp244
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");
}