[Scummvm-cvs-logs] SF.net SVN: scummvm:[47956] scummvm/trunk/engines/sci/engine

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Sun Feb 7 13:13:59 CET 2010


Revision: 47956
          http://scummvm.svn.sourceforge.net/scummvm/?rev=47956&view=rev
Author:   fingolfin
Date:     2010-02-07 12:13:59 +0000 (Sun, 07 Feb 2010)

Log Message:
-----------
SCI: Add function readPMachineInstruction()

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/vm.cpp
    scummvm/trunk/engines/sci/engine/vm.h

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2010-02-07 12:13:34 UTC (rev 47955)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2010-02-07 12:13:59 UTC (rev 47956)
@@ -584,6 +584,75 @@
 
 static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1};
 
+
+int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) {
+	uint offset = 0;
+	extOpcode = src[offset++]; // Get "extended" opcode (lower bit has special meaning)
+	const byte opnumber = extOpcode >> 1;	// get the actual opcode
+
+	memset(opparams, 0, sizeof(opparams));
+
+	for (int i = 0; g_opcode_formats[opnumber][i]; ++i) {
+		//printf("Opcode: 0x%x, Opnumber: 0x%x, temp: %d\n", opcode, opnumber, temp);
+		assert(i < 4);
+		switch (g_opcode_formats[opnumber][i]) {
+
+		case Script_Byte:
+			opparams[i] = src[offset++];
+			break;
+		case Script_SByte:
+			opparams[i] = (int8)src[offset++];
+			break;
+
+		case Script_Word:
+			opparams[i] = READ_LE_UINT16(src + offset);
+			offset += 2;
+			break;
+		case Script_SWord:
+			opparams[i] = (int16)READ_LE_UINT16(src + offset);
+			offset += 2;
+			break;
+
+		case Script_Variable:
+		case Script_Property:
+
+		case Script_Local:
+		case Script_Temp:
+		case Script_Global:
+		case Script_Param:
+
+		case Script_Offset:
+			if (extOpcode & 1) {
+				opparams[i] = src[offset++];
+			} else {
+				opparams[i] = READ_LE_UINT16(src + offset);
+				offset += 2;
+			}
+			break;
+
+		case Script_SVariable:
+		case Script_SRelative:
+			if (extOpcode & 1) {
+				opparams[i] = (int8)src[offset++];
+			} else {
+				opparams[i] = (int16)READ_LE_UINT16(src + offset);
+				offset += 2;
+			}
+			break;
+
+		case Script_None:
+		case Script_End:
+			break;
+
+		case Script_Invalid:
+		default:
+			error("opcode %02x: Invalid", extOpcode);
+		}
+	}
+
+	return offset;
+}
+
 void run_vm(EngineState *s, bool restoring) {
 	assert(s);
 
@@ -635,8 +704,6 @@
 	s->_executionStackPosChanged = true; // Force initialization
 
 	while (1) {
-		byte opcode;
-		byte opnumber;
 		int var_type; // See description below
 		int var_number;
 
@@ -720,57 +787,11 @@
 			error("run_vm(): program counter gone astray");
 #endif
 
-		opcode = GET_OP_BYTE(); // Get opcode
+		// Get opcode
+		byte opcode;
+		scriptState.xs->addr.pc.offset += readPMachineInstruction(code_buf + scriptState.xs->addr.pc.offset, opcode, opparams);
+		const byte opnumber = opcode >> 1;
 
-		opnumber = opcode >> 1;
-
-		for (temp = 0; g_opcode_formats[opnumber][temp]; temp++) {
-			//printf("Opcode: 0x%x, Opnumber: 0x%x, temp: %d\n", opcode, opnumber, temp);
-			switch (g_opcode_formats[opnumber][temp]) {
-
-			case Script_Byte:
-				opparams[temp] = GET_OP_BYTE();
-				break;
-			case Script_SByte:
-				opparams[temp] = GET_OP_SIGNED_BYTE();
-				break;
-
-			case Script_Word:
-				opparams[temp] = GET_OP_WORD();
-				break;
-			case Script_SWord:
-				opparams[temp] = GET_OP_SIGNED_WORD();
-				break;
-
-			case Script_Variable:
-			case Script_Property:
-
-			case Script_Local:
-			case Script_Temp:
-			case Script_Global:
-			case Script_Param:
-				opparams[temp] = GET_OP_FLEX();
-				break;
-
-			case Script_SVariable:
-			case Script_SRelative:
-				opparams[temp] = GET_OP_SIGNED_FLEX();
-				break;
-
-			case Script_Offset:
-				opparams[temp] = GET_OP_FLEX();
-				break;
-
-			case Script_None:
-			case Script_End:
-				break;
-
-			case Script_Invalid:
-			default:
-				error("opcode %02x: Invalid", opcode);
-			}
-		}
-
 		switch (opnumber) {
 
 		case op_bnot: // 0x00 (00)

Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h	2010-02-07 12:13:34 UTC (rev 47955)
+++ scummvm/trunk/engines/sci/engine/vm.h	2010-02-07 12:13:59 UTC (rev 47956)
@@ -523,6 +523,24 @@
  */
 void shrink_execution_stack(EngineState *s, uint size);
 
+/**
+ * Read a PMachine instruction from a memory buffer and return its length.
+ *
+ * @param[in] src		address from which to start parsing
+ * @param[out] extOpcode	"extended" opcode of the parsed instruction
+ * @param[out] opparams	parameter for the parsed instruction
+ * @return the length in bytes of the instruction
+ *
+ * @todo How about changing opparams from int16 to int / int32 to preserve
+ *       unsigned 16bit words as read for Script_Word? In the past, this
+ *       was irrelevant as only a debug opcode used Script_Word. But with
+ *       SCI32 we are now using Script_Word for more opcodes. Maybe this is
+ *       just a mistake and those opcodes should used Script_SWord -- but if
+ *       not then we definitely should change this to int, else we might run
+ *       into trouble if we encounter high value words. *If* those exist at all.
+ */
+int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]);
+
 } // End of namespace Sci
 
 #endif // SCI_ENGINE_VM_H


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list