aboutsummaryrefslogtreecommitdiff
path: root/engines/agi
diff options
context:
space:
mode:
authorJussi Pitkanen2011-06-14 11:57:01 +0300
committerEugene Sandulenko2011-08-13 23:26:53 +0100
commit41dccce00cdd3c5e3692b2e8eb22de1ef0b9c1e1 (patch)
treec7d337985a49ab056645003cfcfb88e35b489883 /engines/agi
parenta4e0cd53f01afeac9f6cf0467a6b4174bf64215e (diff)
downloadscummvm-rg350-41dccce00cdd3c5e3692b2e8eb22de1ef0b9c1e1.tar.gz
scummvm-rg350-41dccce00cdd3c5e3692b2e8eb22de1ef0b9c1e1.tar.bz2
scummvm-rg350-41dccce00cdd3c5e3692b2e8eb22de1ef0b9c1e1.zip
AGI: Execute test commands only when needed
Diffstat (limited to 'engines/agi')
-rw-r--r--engines/agi/agi.h6
-rw-r--r--engines/agi/op_test.cpp119
-rw-r--r--engines/agi/opcodes.cpp5
-rw-r--r--engines/agi/opcodes.h3
4 files changed, 61 insertions, 72 deletions
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 2b41514122..55c1ab32e8 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -634,12 +634,8 @@ struct AgiGame {
Common::Rect mouseFence; /**< rectangle set by fence.mouse command */
- // IF conditions
+ // IF condition handling
int endTest;
- int orTest;
- int orVal;
- int notTest;
- int testVal;
int ec;
};
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index 0054fad6e8..7ccd30e42a 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -39,80 +39,63 @@ namespace Agi {
#define testHas(obj) (state->_vm->objectGetLocation(obj) == EGO_OWNED)
#define testObjInRoom(obj, v) (state->_vm->objectGetLocation(obj) == getvar(v))
-void cond_end(AgiGame *state, uint8 *p) {
- state->endTest = true;
- state->ec = true;
-}
-
void cond_equal(AgiGame *state, uint8 *p) {
if (p[0] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testEqual(p[0], p[1]);
}
void cond_equalv(AgiGame *state, uint8 *p) {
if (p[0] == 11 || p[1] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testEqual(p[0], getvar(p[1]));
}
void cond_less(AgiGame *state, uint8 *p) {
if (p[0] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testLess(p[0], p[1]);
}
void cond_lessv(AgiGame *state, uint8 *p) {
if (p[0] == 11 || p[1] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testLess(p[0], getvar(p[1]));
}
void cond_greater(AgiGame *state, uint8 *p) {
if (p[0] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testGreater(p[0], p[1]);
}
void cond_greaterv(AgiGame *state, uint8 *p) {
if (p[0] == 11 || p[1] == 11)
state->_vm->_timerHack++;
- ip += 2;
state->ec = testGreater(p[0], getvar(p[1]));
}
void cond_isset(AgiGame *state, uint8 *p) {
- ip += 1;
state->ec = testIsSet(p[0]);
}
void cond_issetv(AgiGame *state, uint8 *p) {
- ip += 1;
state->ec = testIsSet(getvar(p[1]));
}
void cond_has(AgiGame *state, uint8 *p) {
- ip += 1;
state->ec = testHas(p[0]);
}
void cond_obj_in_room(AgiGame *state, uint8 *p) {
- ip += 2;
state->ec = testObjInRoom(p[0], p[1]);
}
void cond_posn(AgiGame *state, uint8 *p) {
- ip += 5;
state->ec = state->_vm->testPosn(p[0], p[1], p[2], p[3], p[4]);
}
void cond_controller(AgiGame *state, uint8 *p) {
- ip += 1;
state->ec = state->_vm->testController(p[0]);
}
@@ -122,29 +105,23 @@ void cond_have_key(AgiGame *state, uint8 *p) {
void cond_said(AgiGame *state, uint8 *p) {
int ec = state->_vm->testSaid(p[0], p + 1);
- ip += p[0] * 2; // skip num_words * 2
- ip++; // skip num_words opcode
state->ec = ec;
}
void cond_compare_strings(AgiGame *state, uint8 *p) {
debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", state->strings[p[0]], state->strings[p[1]]);
- ip += 2;
state->ec = state->_vm->testCompareStrings(p[0], p[1]);
}
void cond_obj_in_box(AgiGame *state, uint8 *p) {
- ip += 5;
state->ec = state->_vm->testObjInBox(p[0], p[1], p[2], p[3], p[4]);
}
void cond_center_posn(AgiGame *state, uint8 *p) {
- ip += 5;
state->ec = state->_vm->testObjCenter(p[0], p[1], p[2], p[3], p[4]);
}
void cond_right_posn(AgiGame *state, uint8 *p) {
- ip += 5;
state->ec = state->_vm->testObjRight(p[0], p[1], p[2], p[3], p[4]);
}
@@ -164,22 +141,6 @@ void cond_unknown(AgiGame *state, uint8 *p) {
state->endTest = true;
}
-void cond_not(AgiGame *state, uint8 *p) {
- state->notTest = !state->notTest;
-}
-
-void cond_or(AgiGame *state, uint8 *p) {
- // if or_test is ON and we hit 0xFC, end of OR, then
- // or is STILL false so break.
- if (state->orTest) {
- state->orTest = false;
- state->testVal &= state->orVal;
- } else {
- state->orTest = true;
- state->orVal = false;
- }
-}
-
uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) {
char ms1[MAX_STRINGLEN];
char ms2[MAX_STRINGLEN];
@@ -349,49 +310,87 @@ uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) {
int AgiEngine::testIfCode(int lognum) {
AgiGame *state = &_game;
uint8 op = 0;
- uint16 lastIp = ip;
uint8 p[16] = { 0 };
state->ec = true;
- state->notTest = false;
- state->orTest = false;
+ int notTest = false;
+ int orTest = false;
+ int orVal = false;
state->endTest = false;
- state->testVal = true;
+ int testVal = true;
+ int skipTest = false;
+ int skipOr = false;
while (!(shouldQuit() || _restartGame) && !state->endTest) {
if (_debug.enabled && (_debug.logic0 || lognum))
debugConsole(lognum, lTEST_MODE, NULL);
- lastIp = ip;
op = *(code + ip++);
memmove(p, (code + ip), 16);
- _agiCondCommands[op](state, p);
- if (op == 0xFF || op == 0xFD || op == 0xFC)
+ // Execute test command if needed
+ switch (op) {
+ case 0xFC:
+ skipOr = false;
+ if (orTest) {
+ orTest = false;
+ testVal &= orVal;
+ if (!orVal)
+ skipTest = true;
+ } else {
+ orTest = true;
+ orVal = false;
+ }
continue;
+ case 0xFD:
+ notTest = true;
+ continue;
+ case 0x00:
+ case 0xFF:
+ state->endTest = true;
+ continue;
+
+ default:
+ if (!skipTest && !skipOr) {
+ _agiCondCommands[op](state, p);
+
+ // not is only enabled for 1 test command
+ if (notTest)
+ state->ec = !state->ec;
+ notTest = false;
+
+ if (orTest) {
+ orVal |= state->ec;
+ if (state->ec)
+ skipOr = true;
+ } else {
+ testVal &= state->ec;
+ if (!state->ec)
+ skipTest = true;
+ }
+ }
+ break;
+ }
- // not is only enabled for 1 test command
- if (state->notTest)
- state->ec = !state->ec;
- state->notTest = false;
-
- if (state->orTest)
- state->orVal |= state->ec;
- else
- state->testVal &= state->ec;
+ // Skip the instruction
+ if (op <= 0x13) {
+ if (op == 0x0E) // said()
+ ip += *(code + ip) * 2 + 1;
+ else
+ ip += logicNamesTest[op].argumentsLength();
+ }
}
- // Execute the following IF block if the condition is true, otherwise
- // skip the block.
- if (state->testVal)
+ // Skip the following IF block if the condition evaluates as false
+ if (testVal)
ip += 2;
else
ip += READ_LE_UINT16(code + ip) + 2;
if (_debug.enabled && (_debug.logic0 || lognum))
- debugConsole(lognum, 0xFF, state->testVal ? "=true" : "=false");
+ debugConsole(lognum, 0xFF, testVal ? "=true" : "=false");
- return state->testVal;
+ return testVal;
}
} // End of namespace Agi
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index aef7684226..301f22a3c5 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -26,7 +26,7 @@
namespace Agi {
AgiInstruction logicNamesTest[] = {
- { "", "", &cond_end }, // 00
+ { "", "", NULL }, // 00
{ "equaln", "vn", &cond_equal }, // 01
{ "equalv", "vv", &cond_equalv }, // 02
{ "lessn", "vn", &cond_less }, // 03
@@ -239,9 +239,6 @@ void AgiEngine::setupOpcodes() {
_agiCondCommands[i] = &cond_unknown;
for (int i = 0; i <= ARRAYSIZE(logicNamesTest); ++i)
_agiCondCommands[i] = logicNamesTest[i].func;
- _agiCondCommands[0xFF] = &cond_end;
- _agiCondCommands[0xFD] = &cond_not;
- _agiCondCommands[0xFC] = &cond_or;
for (int i = 0; i < ARRAYSIZE(logicNamesCmd); ++i)
_agiCommands[i] = logicNamesCmd[i].func;
diff --git a/engines/agi/opcodes.h b/engines/agi/opcodes.h
index 6007aa17df..075bd27f61 100644
--- a/engines/agi/opcodes.h
+++ b/engines/agi/opcodes.h
@@ -221,7 +221,6 @@ void cmd_mouse_posn(AgiGame *state, uint8 *p);
void cmd_release_key(AgiGame *state, uint8 *p);
void cmd_adj_ego_move_to_x_y(AgiGame *state, uint8 *p);
-void cond_end(AgiGame *state, uint8 *p);
void cond_equal(AgiGame *state, uint8 *p);
void cond_equalv(AgiGame *state, uint8 *p);
void cond_less(AgiGame *state, uint8 *p);
@@ -242,8 +241,6 @@ void cond_center_posn(AgiGame *state, uint8 *p);
void cond_right_posn(AgiGame *state, uint8 *p);
void cond_unknown_13(AgiGame *state, uint8 *p);
void cond_unknown(AgiGame *state, uint8 *p);
-void cond_not(AgiGame *state, uint8 *p);
-void cond_or(AgiGame *state, uint8 *p);
} // End of namespace Agi