aboutsummaryrefslogtreecommitdiff
path: root/engines/m4/ws_machine.cpp
diff options
context:
space:
mode:
authorFilippos Karapetis2008-04-20 14:47:37 +0000
committerFilippos Karapetis2008-04-20 14:47:37 +0000
commit7ca439f410ac1c46a387567b30271ae4e4a2ed30 (patch)
tree4d4154169b074293581ad6a11ee821290418f4fb /engines/m4/ws_machine.cpp
parentd0590a09eac68d5cde64d37fb2e5bbd1471a676a (diff)
downloadscummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.tar.gz
scummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.tar.bz2
scummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.zip
Initial import of the work in progress M4 engine
svn-id: r31600
Diffstat (limited to 'engines/m4/ws_machine.cpp')
-rw-r--r--engines/m4/ws_machine.cpp422
1 files changed, 422 insertions, 0 deletions
diff --git a/engines/m4/ws_machine.cpp b/engines/m4/ws_machine.cpp
new file mode 100644
index 0000000000..ece76fe5ab
--- /dev/null
+++ b/engines/m4/ws_machine.cpp
@@ -0,0 +1,422 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/woodscript.h"
+
+namespace M4 {
+
+bool (Machine::*machineCommandsTable[])(Instruction &instruction) = {
+ NULL,
+ NULL,//TODO: nop
+ &Machine::m1_gotoState,
+ &Machine::m1_jump,
+ &Machine::m1_terminate,
+ &Machine::m1_startSequence,
+ &Machine::m1_pauseSequence,
+ &Machine::m1_resumeSequence,
+ &Machine::m1_storeValue,
+ &Machine::m1_sendMessage,
+ &Machine::m1_broadcastMessage,
+ &Machine::m1_replyMessage,
+ &Machine::m1_sendSystemMessage,
+ &Machine::m1_createMachine,
+ &Machine::m1_createMachineEx,
+ &Machine::m1_clearVars
+};
+
+void (Machine::*machineConditionalsTable[])(Instruction &instruction) = {
+ NULL,//TODO: after
+ &Machine::m1_onEndSequence,
+ &Machine::m1_onMessage,
+ NULL,//TODO: on_p_msg
+ &Machine::m1_switchLt,
+ &Machine::m1_switchLe,
+ &Machine::m1_switchEq,
+ &Machine::m1_switchNe,
+ &Machine::m1_switchGe,
+ &Machine::m1_switchGt,
+};
+
+Machine::Machine(WoodScript *ws, int32 machineHash, Sequence *parentSeq, int32 dataHash,
+ int32 dataRowIndex, int callbackHandler, Common::String machineName, int32 id) {
+
+ _ws = ws;
+
+ _machHash = machineHash;
+ _name = machineName;
+ _id = id;
+
+ // initialize the machine's bytecode
+ MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash);
+ byte *code;
+ uint32 codeSize;
+ machineAsset->getCode(code, codeSize);
+ _code = new Bytecode(_ws, code, codeSize, NULL);
+
+ // initialize the machine's data
+ if (dataHash >= 0) {
+ DataAsset *dataAsset = _ws->assets()->getData(dataHash);
+ _dataRow = dataAsset->getRow(dataRowIndex);
+ } else {
+ _dataRow = NULL;
+ }
+
+ _recursionLevel = 0;
+ _currentState = 0;
+ _sequence = NULL;
+ _parentSequence = parentSeq;
+ _targetCount = 0;
+
+}
+
+Machine::~Machine() {
+ delete _code;
+}
+
+void Machine::clearMessages() {
+}
+
+void Machine::clearPersistentMessages() {
+}
+
+void Machine::restorePersistentMessages() {
+}
+
+void Machine::sendMessage(uint32 messageHash, long messageValue, Machine *sender) {
+}
+
+void Machine::resetSwitchTime() {
+}
+
+bool Machine::changeSequenceProgram(int32 sequenceHash) {
+ return _sequence->changeProgram(sequenceHash);
+}
+
+bool Machine::searchMessages(uint32 messageHash, uint32 messageValue, Machine *sender) {
+ return false;
+}
+
+bool Machine::searchPersistentMessages(uint32 messageHash, uint32 messageValue, Machine *sender) {
+ return false;
+}
+
+void Machine::enterState() {
+
+ MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash);
+
+ _code->jumpAbsolute(machineAsset->getStateOffset(_currentState));
+
+ int32 instruction = -1;
+
+ _recursionLevel++;
+
+ int32 oldId = _id;
+ int32 oldRecursionLevel = _recursionLevel;
+
+ while (instruction && instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) {
+ instruction = execInstruction();
+ }
+
+ if (instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) {
+ _recursionLevel--;
+ }
+
+}
+
+int32 Machine::execInstruction() {
+
+ //printf("Machine::execInstruction()\n"); fflush(stdout);
+
+ bool done = false;
+ Instruction instruction;
+ //Sequence *sequence;
+ int32 machID = _id;
+
+ _code->loadInstruction(instruction);
+
+ if (instruction.instr >= 64) {
+ if (machineConditionalsTable[instruction.instr - 64] != NULL)
+ (this->*machineConditionalsTable[instruction.instr - 64])(instruction);
+ /* The next line is to yield on unimplemented opcodes */
+ else { fflush(stdout); g_system->delayMillis(5000); }
+ } else if (instruction.instr > 0) {
+ if (machineCommandsTable[instruction.instr] != NULL)
+ done = !(this->*machineCommandsTable[instruction.instr])(instruction);
+ /* The next line is to yield on unimplemented opcodes */
+ else { fflush(stdout); g_system->delayMillis(5000); }
+ if (done) {
+ if (_id == machID) {
+ //TODO: Cancel all requests
+ if (_currentState == -1) {
+ // TODO: Set terminated flag and delete machine in WoodScript update
+ }
+ else {
+ // initialize new state
+ enterState();
+ }
+ }
+ }
+ }
+
+ return instruction.instr;
+
+}
+
+void Machine::execBlock(int32 offset, int32 count) {
+
+ // MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash);
+
+ int32 startOffset = offset, endOffset = offset + count;
+
+ _recursionLevel++;
+
+ int32 oldId = _id;
+ int32 oldRecursionLevel = _recursionLevel;
+
+ _code->jumpAbsolute(offset);
+
+ int32 instruction = -1;
+
+ //printf("---------------------------------------\n"); fflush(stdout);
+
+ while (instruction && instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel &&
+ _code->pos() >= (uint32)startOffset && _code->pos() < (uint32)endOffset) {
+
+ instruction = execInstruction();
+ //g_system->delayMillis(500);
+ }
+
+ //printf("---------------------------------------\n"); fflush(stdout);
+
+ if (instruction == 3) {
+ execInstruction();
+ }
+
+ if (instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) {
+ _recursionLevel--;
+ }
+
+}
+
+bool Machine::m1_gotoState(Instruction &instruction) {
+ //printf("Machine::m1_gotoState() state = %d\n", (int32)instruction.argv[0] >> 16);
+
+ _currentState = (int32)instruction.argv[0] >> 16;
+ _recursionLevel = 0;
+ return false;
+}
+
+bool Machine::m1_jump(Instruction &instruction) {
+ //printf("Machine::m1_jump() ofs = %08X\n", (int32)instruction.argv[0] >> 16);
+
+ _code->jumpRelative((int32)instruction.argv[0] >> 16);
+ return true;
+}
+
+bool Machine::m1_terminate(Instruction &instruction) {
+ //printf("Machine::m1_terminate()\n"); fflush(stdout);
+
+ _currentState = -1;
+ _recursionLevel = 0;
+ return false;
+}
+
+bool Machine::m1_startSequence(Instruction &instruction) {
+ //printf("Machine::m1_startSequence() sequence hash = %d\n", (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ int32 sequenceHash = instruction.argv[0] >> 16;
+ if (_sequence == NULL) {
+ //printf("Machine::m1_startSequence() creating new sequence\n");
+ _sequence = _ws->createSequence(this, sequenceHash);
+ _code->setSequence(_sequence);
+ } else {
+ //printf("Machine::m1_startSequence() using existing sequence\n");
+ _sequence->changeProgram(sequenceHash);
+ //_code->setSequence(_sequence);
+ }
+ return true;
+}
+
+bool Machine::m1_pauseSequence(Instruction &instruction) {
+ //printf("Machine::m1_pauseSequence()\n"); fflush(stdout);
+
+ _sequence->pause();
+ return true;
+}
+
+bool Machine::m1_resumeSequence(Instruction &instruction) {
+ //printf("Machine::m1_resumeSequence()\n"); fflush(stdout);
+
+ _sequence->resume();
+ return true;
+}
+
+bool Machine::m1_storeValue(Instruction &instruction) {
+ //printf("Machine::m1_storeValue() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]);
+
+ *instruction.argp[0] = instruction.getValue();
+ return true;
+}
+
+bool Machine::m1_sendMessage(Instruction &instruction) {
+ //printf("Machine::m1_sendMessage() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]);
+
+#if 0
+//TODO
+ long messageValue;
+
+ if (instruction.argc == 3) {
+ messageValue = instruction.argv[2];
+ } else {
+ messageValue = 0;
+ }
+ //_ws->sendMessage((uint32)instruction.argv[1], messageValue, (uint32)instruction.argv[0] >> 16);
+ //void SendWSMessage(uint32 msgHash, long msgValue, machine *recvM, uint32 machHash, machine *sendM, int32 msgCount) {
+#endif
+ return true;
+
+}
+
+bool Machine::m1_broadcastMessage(Instruction &instruction) {
+ //printf("Machine::m1_broadcastMessage() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]);
+
+#if 0
+//TODO
+ long messageValue;
+
+ if (instruction.argc == 3) {
+ messageValue = instruction.argv[2];
+ } else {
+ messageValue = 0;
+ }
+ //_ws->sendMessage((uint32)instruction.argv[1], messageValue, (uint32)instruction.argv[0] >> 16);
+#endif
+ return true;
+}
+
+bool Machine::m1_replyMessage(Instruction &instruction) {
+ //printf("Machine::m1_replyMessage() messageHash = %d; messageValue = %d\n", (uint32)instruction.argv[0], (uint32)instruction.argv[1]);
+#if 0
+ if (myArg2) {
+ msgValue = *myArg2;
+ }
+ else {
+ msgValue = 0;
+ }
+ SendWSMessage(*myArg1, msgValue, m->msgReplyXM, 0, m, 1);
+#endif
+ return true;
+}
+
+bool Machine::m1_sendSystemMessage(Instruction &instruction) {
+ //printf("Machine::m1_sendSystemMessage() messageValue = %d\n", (uint32)instruction.argv[0]);
+#if 0
+#endif
+ return true;
+}
+
+bool Machine::m1_createMachine(Instruction &instruction) {
+ //printf("Machine::m1_createMachine()\n");
+#if 0
+#endif
+ return true;
+}
+
+bool Machine::m1_createMachineEx(Instruction &instruction) {
+ //printf("Machine::m1_createMachineEx()\n");
+#if 0
+#endif
+ return true;
+}
+
+bool Machine::m1_clearVars(Instruction &instruction) {
+ //printf("Machine::m1_clearVars()\n"); fflush(stdout);
+
+ _sequence->clearVars();
+ return true;
+}
+
+
+void Machine::m1_onEndSequence(Instruction &instruction) {
+ //printf("Machine::m1_onEndSequence() count = %08X\n", (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ int32 count = instruction.argv[0] >> 16;
+ _sequence->issueEndOfSequenceRequest(_code->pos(), count);
+ _code->jumpRelative(count);
+}
+
+void Machine::m1_onMessage(Instruction &instruction) {
+ //printf("Machine::m1_onEndSequence() count = %08X\n", (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ // TODO: Add message to list
+
+ int32 count = instruction.argv[0] >> 16;
+ _code->jumpRelative(count);
+
+}
+
+void Machine::m1_switchLt(Instruction &instruction) {
+ //printf("Machine::m1_switchLt() %d < %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] >= instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+void Machine::m1_switchLe(Instruction &instruction) {
+ //printf("Machine::m1_switchLe() %d <= %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] > instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+void Machine::m1_switchEq(Instruction &instruction) {
+ //printf("Machine::m1_switchEq() %d == %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] != instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+void Machine::m1_switchNe(Instruction &instruction) {
+ //printf("Machine::m1_switchNe() %d != %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] == instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+void Machine::m1_switchGe(Instruction &instruction) {
+ //printf("Machine::m1_switchGe() %d >= %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] < instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+void Machine::m1_switchGt(Instruction &instruction) {
+ //printf("Machine::m1_switchGt() %d > %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); fflush(stdout);
+
+ if (instruction.argv[1] <= instruction.argv[2])
+ _code->jumpRelative(instruction.argv[0] >> 16);
+}
+
+}