diff options
author | Torbjörn Andersson | 2006-04-06 17:56:41 +0000 |
---|---|---|
committer | Torbjörn Andersson | 2006-04-06 17:56:41 +0000 |
commit | 1fa1f9520d1a021de6d16fc8dca523c031ea9f84 (patch) | |
tree | 539698d9147c7bc048417969ec0a7ebe5be51516 /engines | |
parent | 52d1d9ab8e8cf49894fa32ee3414e628dd9577f5 (diff) | |
download | scummvm-rg350-1fa1f9520d1a021de6d16fc8dca523c031ea9f84.tar.gz scummvm-rg350-1fa1f9520d1a021de6d16fc8dca523c031ea9f84.tar.bz2 scummvm-rg350-1fa1f9520d1a021de6d16fc8dca523c031ea9f84.zip |
Split the opcodes into separate functions, and use an array of function
pointers for decoding them, like we do in most other engines. And I just want
to say that this is the second biggest opcode table I've ever seen!
svn-id: r21644
Diffstat (limited to 'engines')
-rw-r--r-- | engines/simon/items.cpp | 2390 | ||||
-rw-r--r-- | engines/simon/simon.cpp | 2 | ||||
-rw-r--r-- | engines/simon/simon.h | 180 |
3 files changed, 1542 insertions, 1030 deletions
diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp index 8a8ecaeda2..2ac85484d3 100644 --- a/engines/simon/items.cpp +++ b/engines/simon/items.cpp @@ -34,1215 +34,1545 @@ extern bool isSmartphone(void); namespace Simon { -int SimonEngine::runScript() { - byte opcode; - bool flag, condition; +// Opcode table +void SimonEngine::setupOpcodes() { + // This opcode table is for Simon 1. Changes for Simon 2 and FF are + // made below. + + static OpcodeProc opcode_table[200] = { + // 0 - 4 + NULL, + &SimonEngine::o1_at, + &SimonEngine::o1_notAt, + NULL, + NULL, + // 5 - 9 + &SimonEngine::o1_carried, + &SimonEngine::o1_notCarried, + &SimonEngine::o1_isAt, + NULL, + NULL, + // 10 - 14 + NULL, + &SimonEngine::o1_zero, + &SimonEngine::o1_notZero, + &SimonEngine::o1_eq, + &SimonEngine::o1_notEq, + // 15 - 19 + &SimonEngine::o1_gt, + &SimonEngine::o1_lt, + &SimonEngine::o1_eqf, + &SimonEngine::o1_notEqf, + &SimonEngine::o1_ltf, + // 20 - 24 + &SimonEngine::o1_gtf, + NULL, + NULL, + &SimonEngine::o1_chance, + NULL, + // 25 - 29 + &SimonEngine::o1_isRoom, + &SimonEngine::o1_isObject, + &SimonEngine::o1_state, + &SimonEngine::o1_oflag, + NULL, + // 30 - 34 + NULL, + &SimonEngine::o1_destroy, + NULL, + &SimonEngine::o1_place, + NULL, + // 35 - 39 + NULL, + &SimonEngine::o1_copyff, + NULL, + NULL, + NULL, + // 40 - 44 + NULL, + &SimonEngine::o1_clear, + &SimonEngine::o1_let, + &SimonEngine::o1_add, + &SimonEngine::o1_sub, + // 45 - 49 + &SimonEngine::o1_addf, + &SimonEngine::o1_subf, + &SimonEngine::o1_mul, + &SimonEngine::o1_div, + &SimonEngine::o1_mulf, + // 50 - 54 + &SimonEngine::o1_divf, + &SimonEngine::o1_mod, + &SimonEngine::o1_modf, + &SimonEngine::o1_random, + NULL, + // 55 - 59 + &SimonEngine::o1_goto, + &SimonEngine::o1_oset, + &SimonEngine::o1_oclear, + &SimonEngine::o1_putBy, + &SimonEngine::o1_inc, + // 60 - 64 + &SimonEngine::o1_dec, + &SimonEngine::o1_setState, + &SimonEngine::o1_print, + &SimonEngine::o1_message, + &SimonEngine::o1_msg, + // 65 - 69 + &SimonEngine::o1_addTextBox, + &SimonEngine::o1_setShortText, + &SimonEngine::o1_setLongText, + &SimonEngine::o1_end, + &SimonEngine::o1_done, + // 70 - 74 + &SimonEngine::o1_printLongText, + &SimonEngine::o1_process, + NULL, + NULL, + NULL, + // 75 - 79 + NULL, + &SimonEngine::o1_when, + &SimonEngine::o1_if1, + &SimonEngine::o1_if2, + &SimonEngine::o1_isCalled, + // 80 - 84 + &SimonEngine::o1_is, + NULL, + &SimonEngine::o1_debug, + &SimonEngine::o1_rescan, + NULL, + // 85 - 89 + NULL, + NULL, + &SimonEngine::o1_comment, + &SimonEngine::o1_haltAnimation, + &SimonEngine::o1_restartAnimation, + // 90 - 94 + &SimonEngine::o1_getParent, + &SimonEngine::o1_getNext, + &SimonEngine::o1_getChildren, + NULL, + NULL, + // 95 - 99 + NULL, + &SimonEngine::o1_picture, + &SimonEngine::o1_loadZone, + &SimonEngine::o1_animate, + &SimonEngine::o1_stopAnimate, + // 100 - 104 + &SimonEngine::o1_killAnimate, + &SimonEngine::o1_defWindow, + &SimonEngine::o1_window, + &SimonEngine::o1_cls, + &SimonEngine::o1_closeWindow, + // 105 - 109 + NULL, + NULL, + &SimonEngine::o1_addBox, + &SimonEngine::o1_delBox, + &SimonEngine::o1_enableBox, + // 110 - 114 + &SimonEngine::o1_disableBox, + &SimonEngine::o1_moveBox, + NULL, + NULL, + &SimonEngine::o1_doIcons, + // 115 - 119 + &SimonEngine::o1_isClass, + &SimonEngine::o1_setClass, + &SimonEngine::o1_unsetClass, + NULL, + &SimonEngine::o1_waitSync, + // 120 - 124 + &SimonEngine::o1_sync, + &SimonEngine::o1_defObj, + NULL, + NULL, + NULL, + // 125 - 129 + &SimonEngine::o1_here, + &SimonEngine::o1_doClassIcons, + &SimonEngine::o1_playTune, + &SimonEngine::o1_waitEndTune, + &SimonEngine::o1_ifEndTune, + // 130 - 134 + &SimonEngine::o1_setAdjNoun, + NULL, + &SimonEngine::o1_saveUserGame, + &SimonEngine::o1_loadUserGame, + &SimonEngine::o1_stopTune, + // 135 - 139 + &SimonEngine::o1_pauseGame, + &SimonEngine::o1_copysf, + &SimonEngine::o1_restoreIcons, + &SimonEngine::o1_freezeZones, + &SimonEngine::o1_placeNoIcons, + // 140 - 144 + &SimonEngine::o1_clearTimers, + &SimonEngine::o1_setDollar, + &SimonEngine::o1_isBox, + &SimonEngine::o1_doTable, + NULL, + // 145 - 149 + NULL, + NULL, + NULL, + NULL, + NULL, + // 150 - 154 + NULL, + &SimonEngine::o1_storeItem, + &SimonEngine::o1_getItem, + &SimonEngine::o1_bSet, + &SimonEngine::o1_bClear, + // 155 - 159 + &SimonEngine::o1_bZero, + &SimonEngine::o1_bNotZero, + &SimonEngine::o1_getOValue, + &SimonEngine::o1_setOValue, + NULL, + // 160 - 164 + &SimonEngine::o1_ink, + &SimonEngine::o1_screenTextBox, + &SimonEngine::o1_screenTextMsg, + &SimonEngine::o1_playEffect, + &SimonEngine::o1_getDollar2, + // 165 - 169 + &SimonEngine::o1_isAdjNoun, + &SimonEngine::o1_b2Set, + &SimonEngine::o1_b2Clear, + &SimonEngine::o1_b2Zero, + &SimonEngine::o1_b2NotZero, + // 170 - 174 + NULL, + NULL, + NULL, + NULL, + NULL, + // 175 - 179 + &SimonEngine::o1_lockZones, + &SimonEngine::o1_unlockZones, + &SimonEngine::o1_screenTextPObj, + &SimonEngine::o1_getPathPosn, + &SimonEngine::o1_scnTxtLongText, + // 180 - 184 + &SimonEngine::o1_mouseOn, + &SimonEngine::o1_mouseOff, + &SimonEngine::o1_loadBeard, + &SimonEngine::o1_unloadBeard, + &SimonEngine::o1_unloadZone, + // 185 - 189 + &SimonEngine::o1_loadStrings, + &SimonEngine::o1_unfreezeZones, + &SimonEngine::o1_specialFade, + NULL, + NULL, + // 190 - 194 + NULL, + NULL, + NULL, + NULL, + NULL, + // 195 - 199 + NULL, + NULL, + NULL, + NULL, + NULL + }; + + _opcode_table = opcode_table; + _numOpcodes = ARRAYSIZE(opcode_table); + + switch (getGameType()) { + case GType_SIMON1: + break; + case GType_SIMON2: + opcode_table[70] = &SimonEngine::o2_printLongText; + opcode_table[83] = &SimonEngine::o2_rescan; + opcode_table[98] = &SimonEngine::o2_animate; + opcode_table[99] = &SimonEngine::o2_stopAnimate; + opcode_table[181] = &SimonEngine::o2_mouseOff; + opcode_table[185] = NULL; + opcode_table[187] = NULL; + opcode_table[188] = &SimonEngine::o2_isShortText; + opcode_table[189] = &SimonEngine::o2_clearMarks; + opcode_table[190] = &SimonEngine::o2_waitMark; + break; + case GType_FF: + opcode_table[37] = &SimonEngine::o3_jumpOut; + opcode_table[70] = &SimonEngine::o3_printLongText; + opcode_table[83] = &SimonEngine::o2_rescan; + opcode_table[98] = &SimonEngine::o2_animate; + opcode_table[99] = &SimonEngine::o2_stopAnimate; + opcode_table[122] = &SimonEngine::o3_oracleTextDown; + opcode_table[123] = &SimonEngine::o3_oracleTextUp; + opcode_table[124] = &SimonEngine::o3_ifTime; + opcode_table[131] = &SimonEngine::o3_setTime; + opcode_table[133] = &SimonEngine::o3_loadUserGame; + opcode_table[134] = &SimonEngine::o3_listSaveGames; + opcode_table[135] = &SimonEngine::o3_checkCD; + opcode_table[161] = &SimonEngine::o3_screenTextBox; + opcode_table[171] = &SimonEngine::o3_hyperLinkOn; + opcode_table[172] = &SimonEngine::o3_hyperLinkOff; + opcode_table[173] = &SimonEngine::o3_checkPaths; + opcode_table[181] = &SimonEngine::o2_mouseOff; + opcode_table[182] = &SimonEngine::o3_loadSmack; + opcode_table[183] = &SimonEngine::o3_playSmack; + opcode_table[185] = NULL; + opcode_table[187] = &SimonEngine::o3_centreScroll; + opcode_table[188] = &SimonEngine::o2_isShortText; + opcode_table[189] = &SimonEngine::o2_clearMarks; + opcode_table[190] = &SimonEngine::o2_waitMark; + opcode_table[191] = &SimonEngine::o3_resetPVCount; + opcode_table[192] = &SimonEngine::o3_setPathValues; + opcode_table[193] = &SimonEngine::o3_stopClock; + opcode_table[194] = &SimonEngine::o3_restartClock; + opcode_table[195] = &SimonEngine::o3_setColour; + opcode_table[196] = &SimonEngine::o3_b3Set; + opcode_table[197] = &SimonEngine::o3_b3Clear; + opcode_table[198] = &SimonEngine::o3_b3Zero; + opcode_table[199] = &SimonEngine::o3_b3NotZero; + break; + default: + error("setupOpcodes: Unknown game"); + } +} - do { - if (_continousMainScript) - dumpOpcode(_codePtr); +// ----------------------------------------------------------------------- +// Simon 1 Opcodes +// ----------------------------------------------------------------------- - opcode = getByte(); - if (opcode == 0xFF) - return 0; +void SimonEngine::o1_at(bool &cond, int &ret) { + // 1: ptrA parent is + cond = (getItem1Ptr()->parent == getNextItemID()); +} - if (_runScriptReturn1) - return 1; +void SimonEngine::o1_notAt(bool &cond, int &ret) { + // 2: ptrA parent is not + cond = (getItem1Ptr()->parent != getNextItemID()); +} - /* Invert condition? */ - flag = false; - if (opcode == 0) { - flag = true; - opcode = getByte(); - if (opcode == 0xFF) - return 0; - } +void SimonEngine::o1_carried(bool &cond, int &ret) { + // 5: parent is 1 + cond = (getNextItemPtr()->parent == getItem1ID()); +} - condition = true; +void SimonEngine::o1_notCarried(bool &cond, int &ret) { + // 6: parent isnot 1 + cond = (getNextItemPtr()->parent != getItem1ID()); +} - switch (opcode) { - case 1:{ /* ptrA parent is */ - condition = (getItem1Ptr()->parent == getNextItemID()); - } - break; +void SimonEngine::o1_isAt(bool &cond, int &ret) { + // 7: parent is + Item *item = getNextItemPtr(); + cond = (item->parent == getNextItemID()); +} - case 2:{ /* ptrA parent is not */ - condition = (getItem1Ptr()->parent != getNextItemID()); - } - break; +void SimonEngine::o1_zero(bool &cond, int &ret) { + // 11: is zero + cond = (getNextVarContents() == 0); +} - case 5:{ /* parent is 1 */ - condition = (getNextItemPtr()->parent == getItem1ID()); - } - break; +void SimonEngine::o1_notZero(bool &cond, int &ret) { + // 12: isnot zero + cond = (getNextVarContents() != 0); +} - case 6:{ /* parent isnot 1 */ - condition = (getNextItemPtr()->parent != getItem1ID()); - } - break; +void SimonEngine::o1_eq(bool &cond, int &ret) { + // 13: equal + uint tmp = getNextVarContents(); + cond = (tmp == getVarOrWord()); +} - case 7:{ /* parent is */ - Item *item = getNextItemPtr(); - condition = (item->parent == getNextItemID()); - } - break; +void SimonEngine::o1_notEq(bool &cond, int &ret) { + // 14: not equal + uint tmp = getNextVarContents(); + cond = (tmp != getVarOrWord()); +} - case 11:{ /* is zero */ - condition = (getNextVarContents() == 0); - } - break; +void SimonEngine::o1_gt(bool &cond, int &ret) { + // 15: is greater + uint tmp = getNextVarContents(); + cond = (tmp > getVarOrWord()); +} - case 12:{ /* isnot zero */ - condition = (getNextVarContents() != 0); - } - break; +void SimonEngine::o1_lt(bool &cond, int &ret) { + // 16: is less + uint tmp = getNextVarContents(); + cond = (tmp < getVarOrWord()); +} - case 13:{ /* equal */ - uint tmp = getNextVarContents(); - condition = (tmp == getVarOrWord()); - } - break; +void SimonEngine::o1_eqf(bool &cond, int &ret) { + // 17: is eq f + uint tmp = getNextVarContents(); + cond = (tmp == getNextVarContents()); +} - case 14:{ /* not equal */ - uint tmp = getNextVarContents(); - condition = (tmp != getVarOrWord()); - } - break; +void SimonEngine::o1_notEqf(bool &cond, int &ret) { + // 18: is not equal f + uint tmp = getNextVarContents(); + cond = (tmp != getNextVarContents()); +} - case 15:{ /* is greater */ - uint tmp = getNextVarContents(); - condition = (tmp > getVarOrWord()); - } - break; +void SimonEngine::o1_ltf(bool &cond, int &ret) { + // 19: is greater f + uint tmp = getNextVarContents(); + cond = (tmp < getNextVarContents()); +} - case 16:{ /* is less */ - uint tmp = getNextVarContents(); - condition = (tmp < getVarOrWord()); - } - break; +void SimonEngine::o1_gtf(bool &cond, int &ret) { + // 20: is less f + uint tmp = getNextVarContents(); + cond = (tmp > getNextVarContents()); +} - case 17:{ /* is eq f */ - uint tmp = getNextVarContents(); - condition = (tmp == getNextVarContents()); - } - break; +void SimonEngine::o1_chance(bool &cond, int &ret) { + // 23 + cond = o_chance(getVarOrWord()); +} - case 18:{ /* is not equal f */ - uint tmp = getNextVarContents(); - condition = (tmp != getNextVarContents()); - } - break; +void SimonEngine::o1_isRoom(bool &cond, int &ret) { + // 25: is room + cond = isRoom(getNextItemPtr()); +} - case 19:{ /* is greater f */ - uint tmp = getNextVarContents(); - condition = (tmp < getNextVarContents()); - } - break; +void SimonEngine::o1_isObject(bool &cond, int &ret) { + // 26: is object + cond = isObject(getNextItemPtr()); +} - case 20:{ /* is less f */ - uint tmp = getNextVarContents(); - condition = (tmp > getNextVarContents()); - } - break; +void SimonEngine::o1_state(bool &cond, int &ret) { + // 27: item state is + Item *item = getNextItemPtr(); + cond = ((uint) item->state == getVarOrWord()); +} - case 23:{ - condition = o_chance(getVarOrWord()); - } - break; +void SimonEngine::o1_oflag(bool &cond, int &ret) { + // 28: item has prop + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + byte num = getVarOrByte(); + cond = subObject != NULL && (subObject->objectFlags & (1 << num)) != 0; +} - case 25:{ /* is room */ - condition = isRoom(getNextItemPtr()); - } - break; +void SimonEngine::o1_destroy(bool &cond, int &ret) { + // 31: set no parent + setItemParent(getNextItemPtr(), NULL); +} - case 26:{ /* is object */ - condition = isObject(getNextItemPtr()); - } - break; +void SimonEngine::o1_place(bool &cond, int &ret) { + // 33: set item parent + Item *item = getNextItemPtr(); + setItemParent(item, getNextItemPtr()); +} - case 27:{ /* item state is */ - Item *item = getNextItemPtr(); - condition = ((uint) item->state == getVarOrWord()); - } - break; +void SimonEngine::o1_copyff(bool &cond, int &ret) { + // 36: copy var + uint value = getNextVarContents(); + writeNextVarContents(value); +} - case 28:{ /* item has prop */ - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); - byte num = getVarOrByte(); - condition = subObject != NULL && (subObject->objectFlags & (1 << num)) != 0; - } break; +void SimonEngine::o1_clear(bool &cond, int &ret) { + // 41: zero var + writeNextVarContents(0); +} - case 31:{ /* set no parent */ - setItemParent(getNextItemPtr(), NULL); - } - break; +void SimonEngine::o1_let(bool &cond, int &ret) { + // 42: set var + uint var = getVarOrByte(); + writeVariable(var, getVarOrWord()); +} - case 33:{ /* set item parent */ - Item *item = getNextItemPtr(); - setItemParent(item, getNextItemPtr()); - } - break; +void SimonEngine::o1_add(bool &cond, int &ret) { + // 43: add + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) + getVarOrWord()); +} - case 36:{ /* copy var */ - uint value = getNextVarContents(); - writeNextVarContents(value); - } - break; +void SimonEngine::o1_sub(bool &cond, int &ret) { + // 44: sub + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) - getVarOrWord()); +} - case 37:{ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o1_addf(bool &cond, int &ret) { + // 45: add f + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) + getNextVarContents()); +} - getVarOrByte(); - _runScriptReturn1 = 1; - } - break; +void SimonEngine::o1_subf(bool &cond, int &ret) { + // 46: sub f + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) - getNextVarContents()); +} - case 41:{ /* zero var */ - writeNextVarContents(0); - } - break; +void SimonEngine::o1_mul(bool &cond, int &ret) { + // 47: mul + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) * getVarOrWord()); +} - case 42:{ /* set var */ - uint var = getVarOrByte(); - writeVariable(var, getVarOrWord()); - } - break; +void SimonEngine::o1_div(bool &cond, int &ret) { + // 48: div + uint var = getVarOrByte(); + int value = getVarOrWord(); + if (value == 0) + error("o1_div: Division by zero"); + writeVariable(var, readVariable(var) / value); +} - case 43:{ /* add */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) + getVarOrWord()); - } - break; +void SimonEngine::o1_mulf(bool &cond, int &ret) { + // 49: mul f + uint var = getVarOrByte(); + writeVariable(var, readVariable(var) * getNextVarContents()); +} - case 44:{ /* sub */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) - getVarOrWord()); - } - break; +void SimonEngine::o1_divf(bool &cond, int &ret) { + // 50: div f + uint var = getVarOrByte(); + int value = getNextVarContents(); + if (value == 0) + error("o1_divf: Division by zero"); + writeVariable(var, readVariable(var) / value); +} - case 45:{ /* add f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) + getNextVarContents()); - } - break; +void SimonEngine::o1_mod(bool &cond, int &ret) { + // 51: mod + uint var = getVarOrByte(); + int value = getVarOrWord(); + if (value == 0) + error("o1_mod: Division by zero"); + writeVariable(var, readVariable(var) % value); +} - case 46:{ /* sub f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) - getNextVarContents()); - } - break; +void SimonEngine::o1_modf(bool &cond, int &ret) { + // 52: mod f + uint var = getVarOrByte(); + int value = getNextVarContents(); + if (value == 0) + error("o1_modf: Division by zero"); + writeVariable(var, readVariable(var) % value); +} - case 47:{ /* mul */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) * getVarOrWord()); - } - break; +void SimonEngine::o1_random(bool &cond, int &ret) { + // 53: random + uint var = getVarOrByte(); + uint value = (uint16)getVarOrWord(); - case 48:{ /* div */ - uint var = getVarOrByte(); - int value = getVarOrWord(); - if (value == 0) - error("Division by zero in div"); - writeVariable(var, readVariable(var) / value); - } - break; + // Disable random in simon1amiga for now + // Since copy protection screen is currently unreadable + if (getPlatform() == Common::kPlatformAmiga) + writeVariable(var, 4); + else + writeVariable(var, _rnd.getRandomNumber(value - 1)); +} - case 49:{ /* mul f */ - uint var = getVarOrByte(); - writeVariable(var, readVariable(var) * getNextVarContents()); - } - break; +void SimonEngine::o1_goto(bool &cond, int &ret) { + // 55: set itemA parent + setItemParent(getItem1Ptr(), getNextItemPtr()); +} - case 50:{ /* div f */ - uint var = getVarOrByte(); - int value = getNextVarContents(); - if (value == 0) - error("Division by zero in div f"); - writeVariable(var, readVariable(var) / value); - } - break; +void SimonEngine::o1_oset(bool &cond, int &ret) { + // 56: set child2 fr bit + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + int value = getVarOrByte(); + if (subObject != NULL && value >= 0x10) + subObject->objectFlags |= 1 << value; +} - case 51:{ /* mod */ - uint var = getVarOrByte(); - int value = getVarOrWord(); - if (value == 0) - error("Division by zero in mod"); - writeVariable(var, readVariable(var) % value); - } - break; +void SimonEngine::o1_oclear(bool &cond, int &ret) { + // 57: clear child2 fr bit + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + int value = getVarOrByte(); + if (subObject != NULL && value >= 0x10) + subObject->objectFlags &= ~(1 << value); +} - case 52:{ /* mod f */ - uint var = getVarOrByte(); - int value = getNextVarContents(); - if (value == 0) - error("Division by zero in mod f"); - writeVariable(var, readVariable(var) % value); - } - break; +void SimonEngine::o1_putBy(bool &cond, int &ret) { + // 58: make siblings + Item *item = getNextItemPtr(); + setItemParent(item, derefItem(getNextItemPtr()->parent)); +} - case 53:{ /* random */ - uint var = getVarOrByte(); - uint value = (uint16)getVarOrWord(); +void SimonEngine::o1_inc(bool &cond, int &ret) { + // 59: item inc state + Item *item = getNextItemPtr(); + if (item->state <= 30000) + setItemState(item, item->state + 1); +} - // Disable random in simon1amiga for now - // Since copy protection screen is currently unreadable - if (getPlatform() == Common::kPlatformAmiga) - writeVariable(var, 4); - else - writeVariable(var, _rnd.getRandomNumber(value - 1)); - } - break; +void SimonEngine::o1_dec(bool &cond, int &ret) { + // 60: item dec state + Item *item = getNextItemPtr(); + if (item->state >= 0) + setItemState(item, item->state - 1); +} - case 55:{ /* set itemA parent */ - setItemParent(getItem1Ptr(), getNextItemPtr()); - } - break; +void SimonEngine::o1_setState(bool &cond, int &ret) { + // 61: item set state + Item *item = getNextItemPtr(); + int value = getVarOrWord(); + if (value < 0) + value = 0; + if (value > 30000) + value = 30000; + setItemState(item, value); +} - case 56:{ /* set child2 fr bit */ - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); - int value = getVarOrByte(); - if (subObject != NULL && value >= 0x10) - subObject->objectFlags |= 1 << value; - } - break; +void SimonEngine::o1_print(bool &cond, int &ret) { + // 62: show int + showMessageFormat("%d", getNextVarContents()); +} - case 57:{ /* clear child2 fr bit */ - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); - int value = getVarOrByte(); - if (subObject != NULL && value >= 0x10) - subObject->objectFlags &= ~(1 << value); - } - break; +void SimonEngine::o1_message(bool &cond, int &ret) { + // 63: show string nl + showMessageFormat("%s\n", getStringPtrByID(getNextStringID())); +} - case 58:{ /* make siblings */ - Item *item = getNextItemPtr(); - setItemParent(item, derefItem(getNextItemPtr()->parent)); - } - break; +void SimonEngine::o1_msg(bool &cond, int &ret) { + // 64: show string + showMessageFormat("%s", getStringPtrByID(getNextStringID())); +} - case 59:{ /* item inc state */ - Item *item = getNextItemPtr(); - if (item->state <= 30000) - setItemState(item, item->state + 1); - } - break; +void SimonEngine::o1_addTextBox(bool &cond, int &ret) { + // 65: add hit area + int id = getVarOrWord(); + int x = getVarOrWord(); + int y = getVarOrWord(); + int w = getVarOrWord(); + int h = getVarOrWord(); + int number = getVarOrByte(); + if (number < 20) + addNewHitArea(id, x, y, w, h, (number << 8) + 129, 0xD0, _dummyItem2); +} - case 60:{ /* item dec state */ - Item *item = getNextItemPtr(); - if (item->state >= 0) - setItemState(item, item->state - 1); - } - break; +void SimonEngine::o1_setShortText(bool &cond, int &ret) { + // 66: set item name + uint var = getVarOrByte(); + uint stringId = getNextStringID(); + if (var < 20) + _stringIdArray2[var] = stringId; +} - case 61:{ /* item set state */ - Item *item = getNextItemPtr(); - int value = getVarOrWord(); - if (value < 0) - value = 0; - if (value > 30000) - value = 30000; - setItemState(item, value); - } - break; +void SimonEngine::o1_setLongText(bool &cond, int &ret) { + // 67: set item description + uint var = getVarOrByte(); + uint stringId = getNextStringID(); + if (getFeatures() & GF_TALKIE) { + uint speechId = getNextWord(); + if (var < 20) { + _stringIdArray3[var] = stringId; + _speechIdArray4[var] = speechId; + } + } else { + if (var < 20) { + _stringIdArray3[var] = stringId; + } + } +} - case 62:{ /* show int */ - showMessageFormat("%d", getNextVarContents()); - } - break; +void SimonEngine::o1_end(bool &cond, int &ret) { + // 68: exit interpreter + shutdown(); +} - case 63:{ /* show string nl */ - showMessageFormat("%s\n", getStringPtrByID(getNextStringID())); - } - break; +void SimonEngine::o1_done(bool &cond, int &ret) { + // 69: return 1 + ret = 1; +} - case 64:{ /* show string */ - showMessageFormat("%s", getStringPtrByID(getNextStringID())); - } - break; +void SimonEngine::o1_printLongText(bool &cond, int &ret) { + // 70: show string from array + const char *str = (const char *)getStringPtrByID(_stringIdArray3[getVarOrByte()]); + showMessageFormat("%s\n", str); +} - case 65:{ /* add hit area */ - int id = getVarOrWord(); - int x = getVarOrWord(); - int y = getVarOrWord(); - int w = getVarOrWord(); - int h = getVarOrWord(); - int number = getVarOrByte(); - if (number < 20) - addNewHitArea(id, x, y, w, h, (number << 8) + 129, 0xD0, _dummyItem2); - } - break; +void SimonEngine::o1_process(bool &cond, int &ret) { + // 71: start subroutine + Subroutine *sub = getSubroutineByID(getVarOrWord()); + if (sub != NULL) + startSubroutine(sub); +} - case 66:{ /* set item name */ - uint var = getVarOrByte(); - uint stringId = getNextStringID(); - if (var < 20) - _stringIdArray2[var] = stringId; - } - break; +void SimonEngine::o1_when(bool &cond, int &ret) { + // 76: add timeout + uint timeout = getVarOrWord(); + addTimeEvent(timeout, getVarOrWord()); +} - case 67:{ /* set item description */ - uint var = getVarOrByte(); - uint stringId = getNextStringID(); - if (getFeatures() & GF_TALKIE) { - uint speechId = getNextWord(); - if (var < 20) { - _stringIdArray3[var] = stringId; - _speechIdArray4[var] = speechId; - } - } else { - if (var < 20) { - _stringIdArray3[var] = stringId; - } - } - } - break; +void SimonEngine::o1_if1(bool &cond, int &ret) { + // 77: has item minus 1 + cond = _subjectItem != NULL; +} - case 68:{ /* exit interpreter */ - shutdown(); - } - break; +void SimonEngine::o1_if2(bool &cond, int &ret) { + // 78: has item minus 3 + cond = _objectItem != NULL; +} - case 69:{ /* return 1 */ - return 1; - } +void SimonEngine::o1_isCalled(bool &cond, int &ret) { + // 79: childstruct fr2 is + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + uint stringId = getNextStringID(); + cond = (subObject != NULL) && subObject->objectName == stringId; +} - case 70:{ /* show string from array */ - const char *str = (const char *)getStringPtrByID(_stringIdArray3[getVarOrByte()]); +void SimonEngine::o1_is(bool &cond, int &ret) { + // 80: item equal + cond = getNextItemPtr() == getNextItemPtr(); +} - if (getGameType() == GType_SIMON2) { - writeVariable(51, strlen(str) / 53 * 8 + 8); - } +void SimonEngine::o1_debug(bool &cond, int &ret) { + // 82: debug opcode + getVarOrByte(); +} - showMessageFormat("%s\n", str); - } - break; +void SimonEngine::o1_rescan(bool &cond, int &ret) { + // 83: restart subroutine + ret = -10; +} - case 71:{ /* start subroutine */ - Subroutine *sub = getSubroutineByID(getVarOrWord()); - if (sub != NULL) - startSubroutine(sub); - } - break; +void SimonEngine::o1_comment(bool &cond, int &ret) { + // 87: comment + getNextStringID(); +} - case 76:{ /* add timeout */ - uint timeout = getVarOrWord(); - addTimeEvent(timeout, getVarOrWord()); - } - break; +void SimonEngine::o1_haltAnimation(bool &cond, int &ret) { + // 88: stop animation + _lockWord |= 0x10; +} - case 77:{ /* has item minus 1 */ - condition = _subjectItem != NULL; - } - break; +void SimonEngine::o1_restartAnimation(bool &cond, int &ret) { + // 89: restart animation + _lockWord &= ~0x10; +} - case 78:{ /* has item minus 3 */ - condition = _objectItem != NULL; - } - break; +void SimonEngine::o1_getParent(bool &cond, int &ret) { + // 90: set minusitem to parent + Item *item = derefItem(getNextItemPtr()->parent); + switch (getVarOrByte()) { + case 0: + _objectItem = item; + break; + case 1: + _subjectItem = item; + break; + default: + error("o1_getParent: invalid subcode"); + } +} - case 79:{ /* childstruct fr2 is */ - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); - uint stringId = getNextStringID(); - condition = (subObject != NULL) && subObject->objectName == stringId; - } - break; +void SimonEngine::o1_getNext(bool &cond, int &ret) { + // 91: set minusitem to sibling + Item *item = derefItem(getNextItemPtr()->sibling); + switch (getVarOrByte()) { + case 0: + _objectItem = item; + break; + case 1: + _subjectItem = item; + break; + default: + error("o1_getNext: invalid subcode"); + } +} - case 80:{ /* item equal */ - condition = getNextItemPtr() == getNextItemPtr(); - } - break; +void SimonEngine::o1_getChildren(bool &cond, int &ret) { + // 92: set minusitem to child + Item *item = derefItem(getNextItemPtr()->child); + switch (getVarOrByte()) { + case 0: + _objectItem = item; + break; + case 1: + _subjectItem = item; + break; + default: + error("o1_getChildren: invalid subcode"); + } +} - case 82:{ /* debug opcode */ - getVarOrByte(); - } - break; +void SimonEngine::o1_picture(bool &cond, int &ret) { + // 96 + uint val = getVarOrWord(); + o_set_video_mode(getVarOrByte(), val); +} - case 83:{ /* restart subroutine */ - if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) - o_83_helper(); - return -10; - } +void SimonEngine::o1_loadZone(bool &cond, int &ret) { + // 97: load vga + o_loadZone(getVarOrWord()); +} - case 87:{ /* comment */ - getNextStringID(); - } - break; +void SimonEngine::o1_animate(bool &cond, int &ret) { + // 98: start vga + uint vga_res, vgaSpriteId, windowNum, x, y, palette; + vgaSpriteId = getVarOrWord(); + vga_res = vgaSpriteId / 100; + windowNum = getVarOrByte(); + x = getVarOrWord(); + y = getVarOrWord(); + palette = getVarOrWord(); + loadSprite(windowNum, vga_res, vgaSpriteId, x, y, palette); +} - case 88:{ /* stop animation */ - _lockWord |= 0x10; - } - break; +void SimonEngine::o1_stopAnimate(bool &cond, int &ret) { + // 99: kill sprite + o_kill_sprite_simon1(getVarOrWord()); +} - case 89:{ /* restart animation */ - _lockWord &= ~0x10; - } - break; +void SimonEngine::o1_killAnimate(bool &cond, int &ret) { + // 100: vga reset + o_vga_reset(); +} - case 90:{ /* set minusitem to parent */ - Item *item = derefItem(getNextItemPtr()->parent); - switch (getVarOrByte()) { - case 0: - _objectItem = item; - break; - case 1: - _subjectItem = item; - break; - default: - error("set minusitem to parent, invalid subcode"); - } - } - break; +void SimonEngine::o1_defWindow(bool &cond, int &ret) { + // 101 + uint num = getVarOrByte(); + uint x = getVarOrWord(); + uint y = getVarOrWord(); + uint w = getVarOrWord(); + uint h = getVarOrWord(); + uint flags = getVarOrWord(); + uint fill_color = getVarOrWord(); + o_defineWindow(num, x, y, w, h, flags, fill_color, 0); +} - case 91:{ /* set minusitem to sibling */ - Item *item = derefItem(getNextItemPtr()->sibling); - switch (getVarOrByte()) { - case 0: - _objectItem = item; - break; - case 1: - _subjectItem = item; - break; - default: - error("set minusitem to sibling, invalid subcode"); - } - } - break; +void SimonEngine::o1_window(bool &cond, int &ret) { + // 102 + changeWindow(getVarOrByte() & 7); +} - case 92:{ /* set minusitem to child */ - Item *item = derefItem(getNextItemPtr()->child); - switch (getVarOrByte()) { - case 0: - _objectItem = item; - break; - case 1: - _subjectItem = item; - break; - default: - error("set minusitem to child, invalid subcode"); - } - } - break; +void SimonEngine::o1_cls(bool &cond, int &ret) { + // 103 + o_unk_103(); +} - case 96:{ - uint val = getVarOrWord(); - o_set_video_mode(getVarOrByte(), val); - } - break; +void SimonEngine::o1_closeWindow(bool &cond, int &ret) { + // 104 + closeWindow(getVarOrByte() & 7); +} - case 97:{ /* load vga */ - o_loadZone(getVarOrWord()); - } - break; +void SimonEngine::o1_addBox(bool &cond, int &ret) { + // 107: add item hitarea + uint flags = 0; + uint id = getVarOrWord(); + uint params = id / 1000; + uint x, y, w, h, verb; + Item *item; + + id = id % 1000; + + if (params & 1) + flags |= 8; + if (params & 2) + flags |= 4; + if (params & 4) + flags |= 0x80; + if (params & 8) + flags |= 1; + if (params & 16) + flags |= 0x10; + + x = getVarOrWord(); + y = getVarOrWord(); + w = getVarOrWord(); + h = getVarOrWord(); + item = getNextItemPtrStrange(); + verb = getVarOrWord(); + if (x >= 1000) { + verb += 0x4000; + x -= 1000; + } + addNewHitArea(id, x, y, w, h, flags, verb, item); +} - case 98:{ /* start vga */ - uint vga_res, vgaSpriteId, windowNum, x, y, palette; - if (getGameType() == GType_SIMON1) { - vgaSpriteId = getVarOrWord(); - vga_res = vgaSpriteId / 100; - } else { - vga_res = getVarOrWord(); - vgaSpriteId = getVarOrWord(); - } - windowNum = getVarOrByte(); - x = getVarOrWord(); - y = getVarOrWord(); - palette = getVarOrWord(); - loadSprite(windowNum, vga_res, vgaSpriteId, x, y, palette); - } - break; +void SimonEngine::o1_delBox(bool &cond, int &ret) { + // 108: delete hitarea + delete_hitarea(getVarOrWord()); +} - case 99:{ /* kill sprite */ - if (getGameType() == GType_SIMON1) { - o_kill_sprite_simon1(getVarOrWord()); - } else { - uint a = getVarOrWord(); - uint b = getVarOrWord(); - o_kill_sprite_simon2(a, b); - } - } - break; +void SimonEngine::o1_enableBox(bool &cond, int &ret) { + // 109: clear hitarea bit 0x40 + clear_hitarea_bit_0x40(getVarOrWord()); +} - case 100:{ /* vga reset */ - o_vga_reset(); - } - break; +void SimonEngine::o1_disableBox(bool &cond, int &ret) { + // 110: set hitarea bit 0x40 + set_hitarea_bit_0x40(getVarOrWord()); +} - case 101:{ - uint num = getVarOrByte(); - uint x = getVarOrWord(); - uint y = getVarOrWord(); - uint w = getVarOrWord(); - uint h = getVarOrWord(); - uint flags = getVarOrWord(); - uint fill_color = getVarOrWord(); - o_defineWindow(num, x, y, w, h, flags, fill_color, 0); - } - break; +void SimonEngine::o1_moveBox(bool &cond, int &ret) { + // 111: set hitarea xy + uint hitarea_id = getVarOrWord(); + uint x = getVarOrWord(); + uint y = getVarOrWord(); + moveBox(hitarea_id, x, y); +} - case 102:{ - changeWindow(getVarOrByte() & 7); - } - break; +void SimonEngine::o1_doIcons(bool &cond, int &ret) { + // 114 + Item *item = getNextItemPtr(); + uint num = getVarOrByte(); + mouseOff(); + drawIconArray(num, item, 0, 0); + mouseOn(); +} - case 103:{ - o_unk_103(); - } - break; +void SimonEngine::o1_isClass(bool &cond, int &ret) { + // 115: item has flag + Item *item = getNextItemPtr(); + cond = (item->classFlags & (1 << getVarOrByte())) != 0; +} - case 104:{ - closeWindow(getVarOrByte() & 7); - } - break; +void SimonEngine::o1_setClass(bool &cond, int &ret) { + // 116: item set flag + Item *item = getNextItemPtr(); + item->classFlags |= (1 << getVarOrByte()); +} - case 107:{ /* add item hitarea */ - uint flags = 0; - uint id = getVarOrWord(); - uint params = id / 1000; - uint x, y, w, h, verb; - Item *item; - - id = id % 1000; - - if (params & 1) - flags |= 8; - if (params & 2) - flags |= 4; - if (params & 4) - flags |= 0x80; - if (params & 8) - flags |= 1; - if (params & 16) - flags |= 0x10; - - x = getVarOrWord(); - y = getVarOrWord(); - w = getVarOrWord(); - h = getVarOrWord(); - item = getNextItemPtrStrange(); - verb = getVarOrWord(); - if (x >= 1000) { - verb += 0x4000; - x -= 1000; - } - addNewHitArea(id, x, y, w, h, flags, verb, item); - } - break; +void SimonEngine::o1_unsetClass(bool &cond, int &ret) { + // 117: item clear flag + Item *item = getNextItemPtr(); + item->classFlags &= ~(1 << getVarOrByte()); +} - case 108:{ /* delete hitarea */ - delete_hitarea(getVarOrWord()); - } - break; +void SimonEngine::o1_waitSync(bool &cond, int &ret) { + // 119: wait vga + uint var = getVarOrWord(); + _scriptVar2 = (var == 200); - case 109:{ /* clear hitarea bit 0x40 */ - clear_hitarea_bit_0x40(getVarOrWord()); - } - break; + if (var != 200 || !_skipVgaWait) + o_waitForSync(var); + _skipVgaWait = false; +} - case 110:{ /* set hitarea bit 0x40 */ - set_hitarea_bit_0x40(getVarOrWord()); - } - break; +void SimonEngine::o1_sync(bool &cond, int &ret) { + // 120: sync + o_sync(getVarOrWord()); +} - case 111:{ /* set hitarea xy */ - uint hitarea_id = getVarOrWord(); - uint x = getVarOrWord(); - uint y = getVarOrWord(); - moveBox(hitarea_id, x, y); - } - break; +void SimonEngine::o1_defObj(bool &cond, int &ret) { + // 121: set vga item + uint slot = getVarOrByte(); + _vcItemArray[slot] = getNextItemPtr(); +} - case 114:{ - Item *item = getNextItemPtr(); - uint num = getVarOrByte(); - mouseOff(); - drawIconArray(num, item, 0, 0); - mouseOn(); - } - break; +void SimonEngine::o1_here(bool &cond, int &ret) { + // 125: item is sibling with item 1 + Item *item = getNextItemPtr(); + cond = (getItem1Ptr()->parent == item->parent); +} - case 115:{ /* item has flag */ - Item *item = getNextItemPtr(); - condition = (item->classFlags & (1 << getVarOrByte())) != 0; - } - break; +void SimonEngine::o1_doClassIcons(bool &cond, int &ret) { + // 126 + Item *item = getNextItemPtr(); + uint num = getVarOrByte(); + uint a = 1 << getVarOrByte(); + mouseOff(); + drawIconArray(num, item, 1, a); + mouseOn(); +} - case 116:{ /* item set flag */ - Item *item = getNextItemPtr(); - item->classFlags |= (1 << getVarOrByte()); - } - break; +void SimonEngine::o1_playTune(bool &cond, int &ret) { + // 127: deals with music + o_playMusic(); +} - case 117:{ /* item clear flag */ - Item *item = getNextItemPtr(); - item->classFlags &= ~(1 << getVarOrByte()); - } - break; +void SimonEngine::o1_waitEndTune(bool &cond, int &ret) { + // 128: dummy instruction + getVarOrWord(); +} - case 119:{ /* wait vga */ - uint var = getVarOrWord(); - _scriptVar2 = (var == 200); +void SimonEngine::o1_ifEndTune(bool &cond, int &ret) { + // 129: dummy instruction + getVarOrWord(); + cond = true; +} - if (var != 200 || !_skipVgaWait) - o_waitForSync(var); - _skipVgaWait = false; - } - break; +void SimonEngine::o1_setAdjNoun(bool &cond, int &ret) { + // 130: set adj noun + uint var = getVarOrByte(); + if (var == 1) { + _scriptAdj1 = getNextWord(); + _scriptNoun1 = getNextWord(); + } else { + _scriptAdj2 = getNextWord(); + _scriptNoun2 = getNextWord(); + } +} - case 120:{ - o_sync(getVarOrWord()); - } - break; +void SimonEngine::o1_saveUserGame(bool &cond, int &ret) { + // 132: save game + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + o_saveGame(); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); +} - case 121:{ /* set vga item */ - uint slot = getVarOrByte(); - _vcItemArray[slot] = getNextItemPtr(); - } - break; +void SimonEngine::o1_loadUserGame(bool &cond, int &ret) { + // 133: load game + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + o_loadGame(); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); +} - case 122:{ /* oracle text down */ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o1_stopTune(bool &cond, int &ret) { + // 134: dummy opcode? + midi.stop(); + _lastMusicPlayed = -1; +} - oracleTextDown(); - } - break; +void SimonEngine::o1_pauseGame(bool &cond, int &ret) { + // 135: quit if user presses y + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); + o_confirmQuit(); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); +} - case 123:{ /* oracle text down */ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o1_copysf(bool &cond, int &ret) { + // 136: set var to item unk3 + Item *item = getNextItemPtr(); + writeNextVarContents(item->state); +} - oracleTextUp(); - } - break; +void SimonEngine::o1_restoreIcons(bool &cond, int &ret) { + // 137 + o_restoreIconArray(getVarOrByte()); +} - case 124:{ /* if time */ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o1_freezeZones(bool &cond, int &ret) { + // 138: vga pointer op 4 + o_freezeBottom(); +} - uint time = getVarOrWord(); - condition = 1; - warning("STUB: script opcode 124 (%d)", time); - } - break; +void SimonEngine::o1_placeNoIcons(bool &cond, int &ret) { + // 139: set parent special + Item *item = getNextItemPtr(); + _noParentNotify = true; + setItemParent(item, getNextItemPtr()); + _noParentNotify = false; +} - case 125:{ /* item is sibling with item 1 */ - Item *item = getNextItemPtr(); - condition = (getItem1Ptr()->parent == item->parent); - } - break; +void SimonEngine::o1_clearTimers(bool &cond, int &ret) { + // 140: del te and add one + killAllTimers(); + addTimeEvent(3, 0xA0); +} - case 126:{ - Item *item = getNextItemPtr(); - uint num = getVarOrByte(); - uint a = 1 << getVarOrByte(); - mouseOff(); - drawIconArray(num, item, 1, a); - mouseOn(); - } - break; +void SimonEngine::o1_setDollar(bool &cond, int &ret) { + // 141: set m1 to m3 + uint which = getVarOrByte(); + Item *item = getNextItemPtr(); + if (which == 1) { + _subjectItem = item; + } else { + _objectItem = item; + } +} - case 127:{ /* deals with music */ - o_playMusic(); - } - break; +void SimonEngine::o1_isBox(bool &cond, int &ret) { + // 142: is hitarea 0x40 clear + cond = is_hitarea_0x40_clear(getVarOrWord()); +} - case 128:{ /* dummy instruction */ - getVarOrWord(); - } - break; +void SimonEngine::o1_doTable(bool &cond, int &ret) { + // 143: start item sub + SubRoom *subRoom = (SubRoom *)findChildOfType(getNextItemPtr(), 1); + if (subRoom != NULL) { + Subroutine *sub = getSubroutineByID(subRoom->subroutine_id); + if (sub) + startSubroutine(sub); + } +} - case 129:{ /* dummy instruction */ - getVarOrWord(); - condition = true; - } - break; +void SimonEngine::o1_storeItem(bool &cond, int &ret) { + // 151: set array6 to item + uint var = getVarOrByte(); + Item *item = getNextItemPtr(); + _itemArray6[var] = item; +} - case 130:{ /* set adj noun */ - uint var = getVarOrByte(); - if (var == 1) { - _scriptAdj1 = getNextWord(); - _scriptNoun1 = getNextWord(); - } else { - _scriptAdj2 = getNextWord(); - _scriptNoun2 = getNextWord(); - } - } - break; +void SimonEngine::o1_getItem(bool &cond, int &ret) { + // 152: set m1 to m3 to array 6 + Item *item = _itemArray6[getVarOrByte()]; + uint var = getVarOrByte(); + if (var == 1) { + _subjectItem = item; + } else { + _objectItem = item; + } +} - case 131:{ - warning("STUB: script opcode 131"); - } - break; +void SimonEngine::o1_bSet(bool &cond, int &ret) { + // 153: set bit + setBitFlag(getVarOrByte(), true); +} - case 132:{ /* save game */ - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - o_saveGame(); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - } - break; +void SimonEngine::o1_bClear(bool &cond, int &ret) { + // 154: clear bit + setBitFlag(getVarOrByte(), false); +} - case 133:{ /* load game */ - if (getGameType() == GType_FF) { - loadGame(readVariable(55)); - } else { - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - o_loadGame(); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - } - } - break; +void SimonEngine::o1_bZero(bool &cond, int &ret) { + // 155: is bit clear + cond = !getBitFlag(getVarOrByte()); +} - case 134:{ /* dummy opcode? */ - if (getGameType() == GType_FF) { - listSaveGames(1); - } else { - midi.stop(); - _lastMusicPlayed = -1; - } - } - break; +void SimonEngine::o1_bNotZero(bool &cond, int &ret) { + // 156: is bit set + uint bit = getVarOrByte(); - case 135:{ /* quit if user presses y */ - if (getGameType() == GType_FF) { - // Switch CD - debug(1, "Switch to CD number %d", readVariable(97)); - } else { - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - o_confirmQuit(); - _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - } - } - break; + // WORKAROUND: Fix for glitch in some versions + if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) { + bit = 50; + } - case 136:{ /* set var to item unk3 */ - Item *item = getNextItemPtr(); - writeNextVarContents(item->state); - } - break; + cond = getBitFlag(bit); +} - case 137:{ - o_restoreIconArray(getVarOrByte()); - } - break; +void SimonEngine::o1_getOValue(bool &cond, int &ret) { + // 157: get item int prop + Item *item = getNextItemPtr(); + SubObject *subObject = (SubObject *)findChildOfType(item, 2); + uint prop = getVarOrByte(); - case 138:{ /* vga pointer op 4 */ - o_freezeBottom(); - } - break; + if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { + uint offs = getOffsetOfChild2Param(subObject, 1 << prop); + writeNextVarContents(subObject->objectFlagValue[offs]); + } else { + writeNextVarContents(0); + } +} - case 139:{ /* set parent special */ - Item *item = getNextItemPtr(); - _noParentNotify = true; - setItemParent(item, getNextItemPtr()); - _noParentNotify = false; - } - break; +void SimonEngine::o1_setOValue(bool &cond, int &ret) { + // 158: set item prop + Item *item = getNextItemPtr(); + SubObject *subObject = (SubObject *)findChildOfType(item, 2); + uint prop = getVarOrByte(); + int value = getVarOrWord(); - case 140:{ /* del te and add one */ - killAllTimers(); - addTimeEvent(3, 0xA0); - } - break; + if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { + uint offs = getOffsetOfChild2Param(subObject, 1 << prop); + subObject->objectFlagValue[offs] = value; + } +} - case 141:{ /* set m1 or m3 */ - uint which = getVarOrByte(); - Item *item = getNextItemPtr(); - if (which == 1) { - _subjectItem = item; - } else { - _objectItem = item; - } - } - break; +void SimonEngine::o1_ink(bool &cond, int &ret) { + // 160 + o_setTextColor(getVarOrByte()); +} - case 142:{ /* is hitarea 0x40 clear */ - condition = is_hitarea_0x40_clear(getVarOrWord()); - } - break; +void SimonEngine::o1_screenTextBox(bool &cond, int &ret) { + // 161: setup text + TextLocation *tl = getTextLocation(getVarOrByte()); - case 143:{ /* start item sub */ - SubRoom *subRoom = (SubRoom *)findChildOfType(getNextItemPtr(), 1); - if (subRoom != NULL) { - Subroutine *sub = getSubroutineByID(subRoom->subroutine_id); - if (sub) - startSubroutine(sub); - } - } - break; + tl->x = getVarOrWord(); + tl->y = getVarOrByte(); + tl->width = getVarOrWord(); +} + +void SimonEngine::o1_screenTextMsg(bool &cond, int &ret) { + // 162: print string + o_printStr(); +} - case 151:{ /* set array6 to item */ - uint var = getVarOrByte(); - Item *item = getNextItemPtr(); - _itemArray6[var] = item; - } - break; +void SimonEngine::o1_playEffect(bool &cond, int &ret) { + // 163: play sound + o_playSFX(getVarOrWord()); +} - case 152:{ /* set m1 or m3 to array6 */ - Item *item = _itemArray6[getVarOrByte()]; - uint var = getVarOrByte(); - if (var == 1) { - _subjectItem = item; - } else { - _objectItem = item; - } - } - break; +void SimonEngine::o1_getDollar2(bool &cond, int &ret) { + // 164 + _showPreposition = true; + o_setup_cond_c(); + _showPreposition = false; +} - case 153:{ /* set bit */ - setBitFlag(getVarOrByte(), true); - break; - } +void SimonEngine::o1_isAdjNoun(bool &cond, int &ret) { + // 165: item unk1 unk2 is + Item *item = getNextItemPtr(); + int16 a = getNextWord(), b = getNextWord(); + cond = (item->adjective == a && item->noun == b); +} - case 154:{ /* clear bit */ - setBitFlag(getVarOrByte(), false); - break; - } +void SimonEngine::o1_b2Set(bool &cond, int &ret) { + // 166: set bit2 + setBitFlag(256 + getVarOrByte(), true); +} - case 155:{ /* is bit clear */ - condition = !getBitFlag(getVarOrByte()); - } - break; +void SimonEngine::o1_b2Clear(bool &cond, int &ret) { + // 167: clear bit2 + setBitFlag(256 + getVarOrByte(), false); +} - case 156:{ /* is bit set */ - uint bit = getVarOrByte(); - if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) { - bit = 50; - } - condition = getBitFlag(bit); - } - break; +void SimonEngine::o1_b2Zero(bool &cond, int &ret) { + // 168: is bit2 clear + cond = !getBitFlag(256 + getVarOrByte()); +} - case 157:{ /* get item int prop */ - Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); - uint prop = getVarOrByte(); +void SimonEngine::o1_b2NotZero(bool &cond, int &ret) { + // 169: is bit2 set + cond = getBitFlag(256 + getVarOrByte()); +} - if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { - uint offs = getOffsetOfChild2Param(subObject, 1 << prop); - writeNextVarContents(subObject->objectFlagValue[offs]); - } else { - writeNextVarContents(0); - } - } - break; +void SimonEngine::o1_lockZones(bool &cond, int &ret) { + // 175: vga pointer op 1 + o_lockZone(); +} - case 158:{ /* set item prop */ - Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); - uint prop = getVarOrByte(); - int value = getVarOrWord(); +void SimonEngine::o1_unlockZones(bool &cond, int &ret) { + // 176: vga pointer op 2 + o_unlockZone(); +} - if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { - uint offs = getOffsetOfChild2Param(subObject, 1 << prop); - subObject->objectFlagValue[offs] = value; - } - } - break; +void SimonEngine::o1_screenTextPObj(bool &cond, int &ret) { + // 177: inventory descriptions + o_inventory_descriptions(); +} - case 160:{ - o_setTextColor(getVarOrByte()); - } - break; +void SimonEngine::o1_getPathPosn(bool &cond, int &ret) { + // 178: path find + uint a = getVarOrWord(); + uint b = getVarOrWord(); + uint c = getVarOrByte(); + uint d = getVarOrByte(); + o_pathfind(a, b, c, d); +} - case 161:{ /* setup text */ - TextLocation *tl = getTextLocation(getVarOrByte()); +void SimonEngine::o1_scnTxtLongText(bool &cond, int &ret) { + // 179: conversation responses and room descriptions + uint vgaSpriteId = getVarOrByte(); + uint color = getVarOrByte(); + uint stringId = getVarOrByte(); + uint speechId = 0; + + const char *string_ptr = (const char *)getStringPtrByID(_stringIdArray3[stringId]); + TextLocation *tl = getTextLocation(vgaSpriteId); + if (getFeatures() & GF_TALKIE) + speechId = _speechIdArray4[stringId]; + + if (_speech && speechId != 0) + playSpeech(speechId, vgaSpriteId); + if (string_ptr != NULL && _subtitles) + printText(vgaSpriteId, color, string_ptr, tl->x, tl->y, tl->width); +} - tl->x = getVarOrWord(); - if (getGameType() == GType_FF) - tl->y = getVarOrWord(); - else - tl->y = getVarOrByte(); - tl->width = getVarOrWord(); - } - break; +void SimonEngine::o1_mouseOn(bool &cond, int &ret) { + // 180: force mouseOn + o_mouseOn(); +} - case 162:{ /* print string */ - o_printStr(); - } - break; +void SimonEngine::o1_mouseOff(bool &cond, int &ret) { + // 181: force mouseOff + o_mouseOff(); +} - case 163:{ /* play sound */ - o_playSFX(getVarOrWord()); - } - break; +void SimonEngine::o1_loadBeard(bool &cond, int &ret) { + // 182: load beard + o_loadBeard(); +} - case 164:{ - _showPreposition = true; - o_setup_cond_c(); - _showPreposition = false; - } - break; +void SimonEngine::o1_unloadBeard(bool &cond, int &ret) { + // 183: unload beard + o_unloadBeard(); +} - case 165:{ /* item unk1 unk2 is */ - Item *item = getNextItemPtr(); - int16 a = getNextWord(), b = getNextWord(); - condition = (item->adjective == a && item->noun == b); - } break; +void SimonEngine::o1_unloadZone(bool &cond, int &ret) { + // 184: clear vgapointer entry + o_unloadZone(getVarOrWord()); +} - case 166:{ /* set bit2 */ - setBitFlag(256 + getVarOrByte(), true); - } - break; +void SimonEngine::o1_loadStrings(bool &cond, int &ret) { + // 185: load sound files + _soundFileId = getVarOrWord(); + if (getPlatform() == Common::kPlatformAmiga && getFeatures() & GF_TALKIE) { + char buf[10]; + sprintf(buf, "%d%s", _soundFileId, "Effects"); + _sound->readSfxFile(buf); + sprintf(buf, "%d%s", _soundFileId, "simon"); + _sound->readVoiceFile(buf); + } +} - case 167:{ /* clear bit2 */ - setBitFlag(256 + getVarOrByte(), false); - } - break; +void SimonEngine::o1_unfreezeZones(bool &cond, int &ret) { + // 186: vga pointer op 3 + o_unfreezeBottom(); +} - case 168:{ /* is bit2 clear */ - condition = !getBitFlag(256 + getVarOrByte()); - } - break; +void SimonEngine::o1_specialFade(bool &cond, int &ret) { + // 187: fade to black + o_fadeToBlack(); +} - case 169:{ /* is bit2 set */ - condition = getBitFlag(256 + getVarOrByte()); - } - break; +// ----------------------------------------------------------------------- +// Simon 2 Opcodes +// ----------------------------------------------------------------------- - case 171:{ /* oracle hyperlink on */ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o2_printLongText(bool &cond, int &ret) { + // 70: show string from array + const char *str = (const char *)getStringPtrByID(_stringIdArray3[getVarOrByte()]); + writeVariable(51, strlen(str) / 53 * 8 + 8); + showMessageFormat("%s\n", str); +} - hyperLinkOn(getVarOrWord()); - } - break; +void SimonEngine::o2_rescan(bool &cond, int &ret) { + // 83: restart subroutine + o_83_helper(); + ret = -10; +} - case 172:{ /* oracle hyperlink off */ - if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) - goto invalid_opcode; +void SimonEngine::o2_animate(bool &cond, int &ret) { + // 98: start vga + uint vga_res, vgaSpriteId, windowNum, x, y, palette; + vga_res = getVarOrWord(); + vgaSpriteId = getVarOrWord(); + windowNum = getVarOrByte(); + x = getVarOrWord(); + y = getVarOrWord(); + palette = getVarOrWord(); + loadSprite(windowNum, vga_res, vgaSpriteId, x, y, palette); +} - hyperLinkOff(); - } - break; +void SimonEngine::o2_stopAnimate(bool &cond, int &ret) { + // 99: kill sprite + uint a = getVarOrWord(); + uint b = getVarOrWord(); + o_kill_sprite_simon2(a, b); +} - case 173:{ - warning("STUB: script opcode 173"); - } - break; +void SimonEngine::o2_mouseOff(bool &cond, int &ret) { + // 181: force mouseOff + o_mouseOff(); + changeWindow(1); + showMessageFormat("\xC"); +} - case 175:{ /* vga pointer op 1 */ - o_lockZone(); - } - break; +void SimonEngine::o2_isShortText(bool &cond, int &ret) { + // 188: string2 is + uint i = getVarOrByte(); + uint str = getNextStringID(); + cond = (str < 20 && _stringIdArray2[i] == str); +} - case 176:{ /* vga pointer op 2 */ - o_unlockZone(); - } - break; +void SimonEngine::o2_clearMarks(bool &cond, int &ret) { + // 189: clear_op189_flag + _marks = 0; +} - case 177:{ /* inventory descriptions */ - o_inventory_descriptions(); - } - break; +void SimonEngine::o2_waitMark(bool &cond, int &ret) { + // 190 + uint i = getVarOrByte(); + if (!(_marks & (1 << i))) + o_waitForMark(i); +} - case 178:{ /* path find */ - uint a = getVarOrWord(); - uint b = getVarOrWord(); - uint c = getVarOrByte(); - uint d = getVarOrByte(); - o_pathfind(a, b, c, d); - } - break; +// ----------------------------------------------------------------------- +// Feeble Files Opcodes +// ----------------------------------------------------------------------- - case 179:{ /* conversation responses */ - uint vgaSpriteId = getVarOrByte(); /* and room descriptions */ - uint color = getVarOrByte(); - uint stringId = getVarOrByte(); - uint speechId = 0; - - const char *string_ptr = (const char *)getStringPtrByID(_stringIdArray3[stringId]); - TextLocation *tl = getTextLocation(vgaSpriteId); - if (getFeatures() & GF_TALKIE) - speechId = _speechIdArray4[stringId]; - - if (_speech && speechId != 0) - playSpeech(speechId, vgaSpriteId); - if (string_ptr != NULL && _subtitles) - printText(vgaSpriteId, color, string_ptr, tl->x, tl->y, tl->width); - } - break; +void SimonEngine::o3_jumpOut(bool &cond, int &ret) { + // 37 + getVarOrByte(); + ret = 1; +} - case 180:{ /* force mouseOn */ - o_mouseOn(); - } - break; +void SimonEngine::o3_printLongText(bool &cond, int &ret) { + // 70: show string from array + int tmp = getVarOrByte(); + const char *str = (const char *)getStringPtrByID(_stringIdArray3[tmp]); + showMessageFormat("%d. %s\n", tmp, str); +} - case 181:{ /* force mouseOff */ - o_mouseOff(); - if (getGameType() == GType_SIMON2) { - changeWindow(1); - showMessageFormat("\xC"); - } - } - break; +void SimonEngine::o3_oracleTextDown(bool &cond, int &ret) { + // 122: oracle text down + oracleTextDown(); +} - case 182:{ /* load beard */ - if (getGameType() == GType_FF) { - // Load video file - debug(1,"Load video file: %s", getStringPtrByID(getNextStringID())); - } else if (getGameType() == GType_SIMON2) { - goto invalid_opcode; - } else { - o_loadBeard(); - } - } - break; +void SimonEngine::o3_oracleTextUp(bool &cond, int &ret) { + // 123: oracle text up + oracleTextUp(); +} - case 183:{ /* unload beard */ - if (getGameType() == GType_FF) { - // Play video - debug(1, "Play video"); - } else if (getGameType() == GType_SIMON2) { - goto invalid_opcode; - } else { - o_unloadBeard(); - } - } - break; +void SimonEngine::o3_ifTime(bool &cond, int &ret) { + // 124: if time + uint time = getVarOrWord(); + cond = true; + warning("STUB: script opcode 124 (%d)", time); +} - case 184:{ /* clear vgapointer entry */ - o_unloadZone(getVarOrWord()); - } - break; +void SimonEngine::o3_setTime(bool &cond, int &ret) { + // 131 + warning("STUB: script opcode 131"); +} - case 185:{ /* load sound files */ - if (getGameType() == GType_SIMON2) - goto invalid_opcode; - - _soundFileId = getVarOrWord(); - if (getPlatform() == Common::kPlatformAmiga && getFeatures() & GF_TALKIE) { - char buf[10]; - sprintf(buf, "%d%s", _soundFileId, "Effects"); - _sound->readSfxFile(buf); - sprintf(buf, "%d%s", _soundFileId, "simon"); - _sound->readVoiceFile(buf); - } +void SimonEngine::o3_loadUserGame(bool &cond, int &ret) { + // 133: load game + loadGame(readVariable(55)); +} - } - break; +void SimonEngine::o3_listSaveGames(bool &cond, int &ret) { + // 134: dummy opcode? + listSaveGames(1); +} - case 186:{ /* vga pointer op 3 */ - o_unfreezeBottom(); - } - break; +void SimonEngine::o3_checkCD(bool &cond, int &ret) { + // 135: switch CD + debug(1, "Switch to CD number %d", readVariable(97)); +} - case 187:{ /* fade to black */ - if (getGameType() == GType_FF) { - warning("STUB: script opcode 187"); - } else if (getGameType() == GType_SIMON2) { - goto invalid_opcode; - } else { - o_fadeToBlack(); - } - } - break; +void SimonEngine::o3_screenTextBox(bool &cond, int &ret) { + // 161: setup text + TextLocation *tl = getTextLocation(getVarOrByte()); - case 188: /* string2 is */ - if (getGameType() == GType_SIMON1) - goto invalid_opcode; - { - uint i = getVarOrByte(); - uint str = getNextStringID(); - condition = (str < 20 && _stringIdArray2[i] == str); - } - break; + tl->x = getVarOrWord(); + tl->y = getVarOrWord(); + tl->width = getVarOrWord(); +} - case 189:{ /* clear_op189_flag */ - if (getGameType() == GType_SIMON1) - goto invalid_opcode; - _marks = 0; - } - break; +void SimonEngine::o3_hyperLinkOn(bool &cond, int &ret) { + // 171: oracle hyperlink on + hyperLinkOn(getVarOrWord()); +} - case 190:{ - uint i; - if (getGameType() == GType_SIMON1) - goto invalid_opcode; - i = getVarOrByte(); - if (!(_marks & (1 << i))) - o_waitForMark(i); - } - break; +void SimonEngine::o3_hyperLinkOff(bool &cond, int &ret) { + // 172: oracle hyperlink off + hyperLinkOff(); +} - // Feeble opcodes - case 191: - if (getBitFlag(83)) { - _PVCount1 = 0; - _GPVCount1 = 0; - } else { - _PVCount = 0; - _GPVCount = 0; - } - break; +void SimonEngine::o3_checkPaths(bool &cond, int &ret) { + // 173 + warning("STUB: script opcode 173"); +} - case 192:{ - uint8 a = getVarOrByte(); - uint8 b = getVarOrByte(); - uint8 c = getVarOrByte(); - uint8 d = getVarOrByte(); - if (getBitFlag(83)) { - _pathValues1[_PVCount1++] = a; - _pathValues1[_PVCount1++] = b; - _pathValues1[_PVCount1++] = c; - _pathValues1[_PVCount1++] = d; - } else { - _pathValues[_PVCount++] = a; - _pathValues[_PVCount++] = b; - _pathValues[_PVCount++] = c; - _pathValues[_PVCount++] = d; - } - } - break; +void SimonEngine::o3_loadSmack(bool &cond, int &ret) { + // 182: load video file + debug(1,"Load video file: %s", getStringPtrByID(getNextStringID())); +} - case 193: - // pause clock - warning("STUB: script opcode 193"); - break; +void SimonEngine::o3_playSmack(bool &cond, int &ret) { + // 183: play video + debug(1, "Play video"); +} - case 194: - // resume clock - warning("STUB: script opcode 194"); - break; +void SimonEngine::o3_centreScroll(bool &cond, int &ret) { + // 187 + warning("STUB: script opcode 187"); +} - case 195:{ - // Set palette colour? - uint blue = getVarOrByte(); - uint green = getVarOrByte(); - uint red = getVarOrByte(); - uint color = getVarOrByte(); - warning("STUB: script opcode 195 (%d, %d, %d, %d)", blue, green, red, color); - } - break; +void SimonEngine::o3_resetPVCount(bool &cond, int &ret) { + // 191 + if (getBitFlag(83)) { + _PVCount1 = 0; + _GPVCount1 = 0; + } else { + _PVCount = 0; + _GPVCount = 0; + } +} - case 196:{ /* set bit3 */ - setBitFlag(512 + getVarOrByte(), true); - } - break; +void SimonEngine::o3_setPathValues(bool &cond, int &ret) { + // 192 + uint8 a = getVarOrByte(); + uint8 b = getVarOrByte(); + uint8 c = getVarOrByte(); + uint8 d = getVarOrByte(); + if (getBitFlag(83)) { + _pathValues1[_PVCount1++] = a; + _pathValues1[_PVCount1++] = b; + _pathValues1[_PVCount1++] = c; + _pathValues1[_PVCount1++] = d; + } else { + _pathValues[_PVCount++] = a; + _pathValues[_PVCount++] = b; + _pathValues[_PVCount++] = c; + _pathValues[_PVCount++] = d; + } +} - case 197:{ /* clear bit3 */ - setBitFlag(512 + getVarOrByte(), false); - } - break; +void SimonEngine::o3_stopClock(bool &cond, int &ret) { + // 193: pause clock + warning("STUB: script opcode 193"); +} - case 198:{ /* is bit3 clear */ - condition = !getBitFlag(512 + getVarOrByte()); - } - break; +void SimonEngine::o3_restartClock(bool &cond, int &ret) { + // 194: resume clock + warning("STUB: script opcode 194"); +} - case 199:{ /* is bit3 set */ - condition = getBitFlag(512 + getVarOrByte()); - } - break; +void SimonEngine::o3_setColour(bool &cond, int &ret) { + // 195: set palette colour? + uint blue = getVarOrByte(); + uint green = getVarOrByte(); + uint red = getVarOrByte(); + uint color = getVarOrByte(); + warning("STUB: script opcode 195 (%d, %d, %d, %d)", blue, green, red, color); +} - default: - invalid_opcode:; - error("Invalid opcode '%d'", opcode); +void SimonEngine::o3_b3Set(bool &cond, int &ret) { + // 196: set bit3 + setBitFlag(512 + getVarOrByte(), true); +} + +void SimonEngine::o3_b3Clear(bool &cond, int &ret) { + // 197: clear bit3 + setBitFlag(512 + getVarOrByte(), false); +} + +void SimonEngine::o3_b3Zero(bool &cond, int &ret) { + // 198: is bit3 clear + cond = !getBitFlag(512 + getVarOrByte()); +} + +void SimonEngine::o3_b3NotZero(bool &cond, int &ret) { + // 199: is bit3 set + cond = getBitFlag(512 + getVarOrByte()); +} + +// ----------------------------------------------------------------------- + +int SimonEngine::runScript() { + byte opcode; + int ret; + bool flag, condition; + + // NOTE: It is tempting to make 'ret' and 'condition' class variables + // to avoid having to pass them to each opcode function. Before you + // succumb to that temptation, please remember that this function will + // be called recursively. + + ret = 0; + + do { + if (_continousMainScript) + dumpOpcode(_codePtr); + + opcode = getByte(); + if (opcode == 0xFF) + return 0; + + + if (_runScriptReturn1) + return 1; + + /* Invert condition? */ + flag = false; + if (opcode == 0) { + flag = true; + opcode = getByte(); + if (opcode == 0xFF) + return 0; } - } while (condition != flag); + condition = true; - return 0; + if (opcode > _numOpcodes || !_opcode_table[opcode]) + error("Invalid opcode '%d' encountered", opcode); + + (this->*_opcode_table[opcode]) (condition, ret); + } while (condition != flag && !ret); + + return ret; } int SimonEngine::startSubroutine(Subroutine *sub) { diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp index 7c522c4ab1..906bdb578b 100644 --- a/engines/simon/simon.cpp +++ b/engines/simon/simon.cpp @@ -483,6 +483,8 @@ int SimonEngine::init(GameDetector &detector) { return -1; } + setupOpcodes(); + if (getGameType() == GType_FF) { _screenWidth = 640; _screenHeight = 480; diff --git a/engines/simon/simon.h b/engines/simon/simon.h index 34949a4aa9..8c6b2042b2 100644 --- a/engines/simon/simon.h +++ b/engines/simon/simon.h @@ -143,6 +143,11 @@ class SimonEngine : public Engine { void errorString(const char *buf_input, char *buf_output); + typedef void (SimonEngine::*OpcodeProc) (bool &cond, int &ret); + void setupOpcodes(); + const OpcodeProc *_opcode_table; + int _numOpcodes; + typedef void (SimonEngine::*VgaOpcodeProc) (); void setupVgaOpcodes(); const VgaOpcodeProc *_vga_opcode_table; @@ -799,6 +804,181 @@ public: void vc83_playSoundLoop(); void vc84_stopSoundLoop(); + // Opcodes, Simon 1 and later + void o1_at(bool &cond, int &ret); + void o1_notAt(bool &cond, int &ret); + void o1_carried(bool &cond, int &ret); + void o1_notCarried(bool &cond, int &ret); + void o1_isAt(bool &cond, int &ret); + void o1_zero(bool &cond, int &ret); + void o1_notZero(bool &cond, int &ret); + void o1_eq(bool &cond, int &ret); + void o1_notEq(bool &cond, int &ret); + void o1_gt(bool &cond, int &ret); + void o1_lt(bool &cond, int &ret); + void o1_eqf(bool &cond, int &ret); + void o1_notEqf(bool &cond, int &ret); + void o1_ltf(bool &cond, int &ret); + void o1_gtf(bool &cond, int &ret); + void o1_chance(bool &cond, int &ret); + void o1_isRoom(bool &cond, int &ret); + void o1_isObject(bool &cond, int &ret); + void o1_state(bool &cond, int &ret); + void o1_oflag(bool &cond, int &ret); + void o1_destroy(bool &cond, int &ret); + void o1_place(bool &cond, int &ret); + void o1_copyff(bool &cond, int &ret); + void o1_clear(bool &cond, int &ret); + void o1_let(bool &cond, int &ret); + void o1_add(bool &cond, int &ret); + void o1_sub(bool &cond, int &ret); + void o1_addf(bool &cond, int &ret); + void o1_subf(bool &cond, int &ret); + void o1_mul(bool &cond, int &ret); + void o1_div(bool &cond, int &ret); + void o1_mulf(bool &cond, int &ret); + void o1_divf(bool &cond, int &ret); + void o1_mod(bool &cond, int &ret); + void o1_modf(bool &cond, int &ret); + void o1_random(bool &cond, int &ret); + void o1_goto(bool &cond, int &ret); + void o1_oset(bool &cond, int &ret); + void o1_oclear(bool &cond, int &ret); + void o1_putBy(bool &cond, int &ret); + void o1_inc(bool &cond, int &ret); + void o1_dec(bool &cond, int &ret); + void o1_setState(bool &cond, int &ret); + void o1_print(bool &cond, int &ret); + void o1_message(bool &cond, int &ret); + void o1_msg(bool &cond, int &ret); + void o1_addTextBox(bool &cond, int &ret); + void o1_setShortText(bool &cond, int &ret); + void o1_setLongText(bool &cond, int &ret); + void o1_end(bool &cond, int &ret); + void o1_done(bool &cond, int &ret); + void o1_printLongText(bool &cond, int &ret); + void o1_process(bool &cond, int &ret); + void o1_when(bool &cond, int &ret); + void o1_if1(bool &cond, int &ret); + void o1_if2(bool &cond, int &ret); + void o1_isCalled(bool &cond, int &ret); + void o1_is(bool &cond, int &ret); + void o1_debug(bool &cond, int &ret); + void o1_rescan(bool &cond, int &ret); + void o1_comment(bool &cond, int &ret); + void o1_haltAnimation(bool &cond, int &ret); + void o1_restartAnimation(bool &cond, int &ret); + void o1_getParent(bool &cond, int &ret); + void o1_getNext(bool &cond, int &ret); + void o1_getChildren(bool &cond, int &ret); + void o1_picture(bool &cond, int &ret); + void o1_loadZone(bool &cond, int &ret); + void o1_animate(bool &cond, int &ret); + void o1_stopAnimate(bool &cond, int &ret); + void o1_killAnimate(bool &cond, int &ret); + void o1_defWindow(bool &cond, int &ret); + void o1_window(bool &cond, int &ret); + void o1_cls(bool &cond, int &ret); + void o1_closeWindow(bool &cond, int &ret); + void o1_addBox(bool &cond, int &ret); + void o1_delBox(bool &cond, int &ret); + void o1_enableBox(bool &cond, int &ret); + void o1_disableBox(bool &cond, int &ret); + void o1_moveBox(bool &cond, int &ret); + void o1_doIcons(bool &cond, int &ret); + void o1_isClass(bool &cond, int &ret); + void o1_setClass(bool &cond, int &ret); + void o1_unsetClass(bool &cond, int &ret); + void o1_waitSync(bool &cond, int &ret); + void o1_sync(bool &cond, int &ret); + void o1_defObj(bool &cond, int &ret); + void o1_here(bool &cond, int &ret); + void o1_doClassIcons(bool &cond, int &ret); + void o1_playTune(bool &cond, int &ret); + void o1_waitEndTune(bool &cond, int &ret); + void o1_ifEndTune(bool &cond, int &ret); + void o1_setAdjNoun(bool &cond, int &ret); + void o1_saveUserGame(bool &cond, int &ret); + void o1_loadUserGame(bool &cond, int &ret); + void o1_stopTune(bool &cond, int &ret); + void o1_pauseGame(bool &cond, int &ret); + void o1_copysf(bool &cond, int &ret); + void o1_restoreIcons(bool &cond, int &ret); + void o1_freezeZones(bool &cond, int &ret); + void o1_placeNoIcons(bool &cond, int &ret); + void o1_clearTimers(bool &cond, int &ret); + void o1_setDollar(bool &cond, int &ret); + void o1_isBox(bool &cond, int &ret); + void o1_doTable(bool &cond, int &ret); + void o1_storeItem(bool &cond, int &ret); + void o1_getItem(bool &cond, int &ret); + void o1_bSet(bool &cond, int &ret); + void o1_bClear(bool &cond, int &ret); + void o1_bZero(bool &cond, int &ret); + void o1_bNotZero(bool &cond, int &ret); + void o1_getOValue(bool &cond, int &ret); + void o1_setOValue(bool &cond, int &ret); + void o1_ink(bool &cond, int &ret); + void o1_screenTextBox(bool &cond, int &ret); + void o1_screenTextMsg(bool &cond, int &ret); + void o1_playEffect(bool &cond, int &ret); + void o1_getDollar2(bool &cond, int &ret); + void o1_isAdjNoun(bool &cond, int &ret); + void o1_b2Set(bool &cond, int &ret); + void o1_b2Clear(bool &cond, int &ret); + void o1_b2Zero(bool &cond, int &ret); + void o1_b2NotZero(bool &cond, int &ret); + void o1_lockZones(bool &cond, int &ret); + void o1_unlockZones(bool &cond, int &ret); + void o1_screenTextPObj(bool &cond, int &ret); + void o1_getPathPosn(bool &cond, int &ret); + void o1_scnTxtLongText(bool &cond, int &ret); + void o1_mouseOn(bool &cond, int &ret); + void o1_mouseOff(bool &cond, int &ret); + void o1_loadBeard(bool &cond, int &ret); + void o1_unloadBeard(bool &cond, int &ret); + void o1_unloadZone(bool &cond, int &ret); + void o1_loadStrings(bool &cond, int &ret); + void o1_unfreezeZones(bool &cond, int &ret); + void o1_specialFade(bool &cond, int &ret); + + // Opcodes, Simon 2 and later + void o2_printLongText(bool &cond, int &ret); + void o2_rescan(bool &cond, int &ret); + void o2_animate(bool &cond, int &ret); + void o2_stopAnimate(bool &cond, int &ret); + void o2_mouseOff(bool &cond, int &ret); + void o2_isShortText(bool &cond, int &ret); + void o2_clearMarks(bool &cond, int &ret); + void o2_waitMark(bool &cond, int &ret); + + // Opcodes, Feeble Files + void o3_jumpOut(bool &cond, int &ret); + void o3_printLongText(bool &cond, int &ret); + void o3_oracleTextDown(bool &cond, int &ret); + void o3_oracleTextUp(bool &cond, int &ret); + void o3_ifTime(bool &cond, int &ret); + void o3_setTime(bool &cond, int &ret); + void o3_loadUserGame(bool &cond, int &ret); + void o3_listSaveGames(bool &cond, int &ret); + void o3_checkCD(bool &cond, int &ret); + void o3_screenTextBox(bool &cond, int &ret); + void o3_hyperLinkOn(bool &cond, int &ret); + void o3_hyperLinkOff(bool &cond, int &ret); + void o3_checkPaths(bool &cond, int &ret); + void o3_loadSmack(bool &cond, int &ret); + void o3_playSmack(bool &cond, int &ret); + void o3_centreScroll(bool &cond, int &ret); + void o3_resetPVCount(bool &cond, int &ret); + void o3_setPathValues(bool &cond, int &ret); + void o3_stopClock(bool &cond, int &ret); + void o3_restartClock(bool &cond, int &ret); + void o3_setColour(bool &cond, int &ret); + void o3_b3Set(bool &cond, int &ret); + void o3_b3Clear(bool &cond, int &ret); + void o3_b3Zero(bool &cond, int &ret); + void o3_b3NotZero(bool &cond, int &ret); + protected: void drawImages(VC10_state *state); void drawImages_Feeble(VC10_state *state); |