aboutsummaryrefslogtreecommitdiff
path: root/engines/agi/opcodes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agi/opcodes.cpp')
-rw-r--r--engines/agi/opcodes.cpp140
1 files changed, 108 insertions, 32 deletions
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 472917de77..be6748b40c 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -25,10 +25,7 @@
namespace Agi {
-AgiInstruction *logicNamesTest;
-AgiInstruction *logicNamesCmd;
-
-AgiInstruction insV1Test[] = {
+const AgiOpCodeDefinitionEntry opCodesV1Cond[] = {
{ "", "", &condUnknown }, // 00
{ "equaln", "vn", &condEqual }, // 01
{ "equalv", "vv", &condEqualV }, // 02
@@ -48,7 +45,7 @@ AgiInstruction insV1Test[] = {
{ "bit", "nv", &condBit }, // 10
};
-AgiInstruction insV1[] = {
+const AgiOpCodeDefinitionEntry opCodesV1[] = {
{ "return", "", NULL }, // 00
{ "increment", "v", &cmdIncrement }, // 01
{ "decrement", "v", &cmdDecrement }, // 02
@@ -149,7 +146,7 @@ AgiInstruction insV1[] = {
{ "...", "nv", &cmdUnknown }, // 61 # clearbit
};
-AgiInstruction insV2Test[] = {
+AgiOpCodeDefinitionEntry opCodesV2Cond[] = {
{ "", "", &condUnknown }, // 00
{ "equaln", "vn", &condEqual }, // 01
{ "equalv", "vv", &condEqualV }, // 02
@@ -172,7 +169,7 @@ AgiInstruction insV2Test[] = {
{ "in.motion.using.mouse", "", &condUnknown13 } // 13
};
-AgiInstruction insV2[] = {
+AgiOpCodeDefinitionEntry opCodesV2[] = {
{ "return", "", NULL }, // 00
{ "increment", "v", &cmdIncrement }, // 01
{ "decrement", "v", &cmdDecrement }, // 02
@@ -358,36 +355,115 @@ AgiInstruction insV2[] = {
{ "adj.ego.move.to.xy", "", &cmdAdjEgoMoveToXY } // C6
};
-void AgiEngine::setupOpcodes() {
- if (getVersion() >= 0x2000) {
- for (int i = 0; i < ARRAYSIZE(insV2Test); ++i)
- _agiCondCommands[i] = insV2Test[i].func;
- for (int i = 0; i < ARRAYSIZE(insV2); ++i)
- _agiCommands[i] = insV2[i].func;
+//
+// Currently, there is no known difference between v3.002.098 -> v3.002.149
+// So version emulated;
+// 0x0086,
+// 0x0149
+//
- logicNamesTest = insV2Test;
- logicNamesCmd = insV2;
+void AgiEngine::setupOpCodes(uint16 version) {
+ const AgiOpCodeDefinitionEntry *opCodesTable = nullptr;
+ const AgiOpCodeDefinitionEntry *opCodesCondTable = nullptr;
+ uint16 opCodesTableSize = 0;
+ uint16 opCodesCondTableSize = 0;
+ uint16 opCodesTableMaxSize = sizeof(_opCodes) / sizeof(AgiOpCodeEntry);
+ uint16 opCodesCondTableMaxSize = sizeof(_opCodesCond) / sizeof(AgiOpCodeEntry);
- // Alter opcode parameters for specific games
- // TODO: This could be either turned into a game feature, or a version
- // specific check, instead of a game version check
+ debug(0, "Setting up for version 0x%04X", version);
- // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
- // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
- if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
- getPlatform() == Common::kPlatformApple2GS) {
- logicNamesCmd[176].args = "n"; // hide.mouse
- logicNamesCmd[178].args = "n"; // show.mouse
- }
+ if (version >= 0x2000) {
+ opCodesTable = opCodesV2;
+ opCodesCondTable = opCodesV2Cond;
+ opCodesTableSize = ARRAYSIZE(opCodesV2);
+ opCodesCondTableSize = ARRAYSIZE(opCodesV2Cond);
} else {
- for (int i = 0; i < ARRAYSIZE(insV1Test); ++i)
- _agiCondCommands[i] = insV1Test[i].func;
- for (int i = 0; i < ARRAYSIZE(insV1); ++i)
- _agiCommands[i] = insV1[i].func;
+ opCodesTable = opCodesV1;
+ opCodesCondTable = opCodesV1Cond;
+ opCodesTableSize = ARRAYSIZE(opCodesV1);
+ opCodesCondTableSize = ARRAYSIZE(opCodesV1Cond);
+ }
- logicNamesTest = insV1Test;
- logicNamesCmd = insV1;
+ // copy data over
+ for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
+ _opCodes[opCodeNr].name = opCodesTable[opCodeNr].name;
+ _opCodes[opCodeNr].parameters = opCodesTable[opCodeNr].parameters;
+ _opCodes[opCodeNr].functionPtr = opCodesTable[opCodeNr].functionPtr;
}
-}
+ for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].name = opCodesCondTable[opCodeNr].name;
+ _opCodesCond[opCodeNr].parameters = opCodesCondTable[opCodeNr].parameters;
+ _opCodesCond[opCodeNr].functionPtr = opCodesCondTable[opCodeNr].functionPtr;
+ }
+
+ // Alter opcode parameters for specific games
+ if ((version >= 0x2000) && (version < 0x3000)) {
+ // AGI3 adjustments
+
+ // 'quit' takes 0 args for 2.089
+ if (version == 0x2089)
+ _opCodes[0x86].parameters = "";
+
+ // 'print.at' and 'print.at.v' take 3 args before 2.272
+ // This is documented in the specs as only < 2.440, but it seems
+ // that KQ3 (2.272) needs a 'print.at' taking 4 args.
+ if (version < 0x2272) {
+ _opCodes[0x97].parameters = "vvv";
+ _opCodes[0x98].parameters = "vvv";
+ }
+ }
+
+ if (version >= 0x3000) {
+ // AGI3 adjustments
+ // 'unknown176' takes 1 arg for 3.002.086, not 0 args.
+ // 'unknown173' also takes 1 arg for 3.002.068, not 0 args.
+ // Is this actually used anywhere? -- dsymonds
+ if (version == 0x3086) {
+ _opCodes[0xb0].parameters = "n";
+ _opCodes[0xad].parameters = "n";
+ }
+ }
+
+ // TODO: This could be either turned into a game feature, or a version
+ // specific check, instead of a game version check
+ // The Apple IIGS versions of MH1 and Goldrush both have a parameter for
+ // show.mouse and hide.mouse. Fixes bugs #3577754 and #3426946.
+ if ((getGameID() == GID_MH1 || getGameID() == GID_GOLDRUSH) &&
+ getPlatform() == Common::kPlatformApple2GS) {
+ _opCodes[176].parameters = "n"; // hide.mouse
+ _opCodes[178].parameters = "n"; // show.mouse
+ }
+
+ // FIXME: Apply this fix to other games also that use 2 arguments for command 182.
+ // 'adj.ego.move.to.x.y' (i.e. command 182) takes 2 arguments for at least the
+ // Amiga Gold Rush! (v2.05 1989-03-09) using Amiga AGI 2.316. Amiga's Gold Rush
+ // has been set to use AGI 3.149 in ScummVM so that's why this initialization is
+ // here and not in setupV2Game.
+ if (getGameID() == GID_GOLDRUSH && getPlatform() == Common::kPlatformAmiga)
+ _opCodes[182].parameters = "vv";
+
+ // add invalid entries for every opcode, that is not defined at all
+ for (int opCodeNr = opCodesTableSize; opCodeNr < opCodesTableMaxSize; opCodeNr++) {
+ _opCodes[opCodeNr].name = "illegal";
+ _opCodes[opCodeNr].parameters = "";
+ _opCodes[opCodeNr].functionPtr = nullptr;
+ }
+
+ for (int opCodeNr = opCodesCondTableSize; opCodeNr < opCodesCondTableMaxSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].name = "illegal";
+ _opCodesCond[opCodeNr].parameters = "";
+ _opCodesCond[opCodeNr].functionPtr = nullptr;
+ }
+
+ // calculate parameter size
+ for (int opCodeNr = 0; opCodeNr < opCodesTableSize; opCodeNr++) {
+ _opCodes[opCodeNr].parameterSize = strlen( _opCodes[opCodeNr].parameters);
+ }
+
+ for (int opCodeNr = 0; opCodeNr < opCodesCondTableSize; opCodeNr++) {
+ _opCodesCond[opCodeNr].parameterSize = strlen( _opCodesCond[opCodeNr].parameters);
+ }
}
+
+} // End of namespace Agi