aboutsummaryrefslogtreecommitdiff
path: root/engines/simon/items.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/simon/items.cpp')
-rw-r--r--engines/simon/items.cpp1685
1 files changed, 1685 insertions, 0 deletions
diff --git a/engines/simon/items.cpp b/engines/simon/items.cpp
new file mode 100644
index 0000000000..d1df1aa82c
--- /dev/null
+++ b/engines/simon/items.cpp
@@ -0,0 +1,1685 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Item script opcodes for Simon1/Simon2
+
+#include "common/stdafx.h"
+#include "simon/simon.h"
+#include "simon/intern.h"
+
+#include "common/system.h"
+
+#ifdef _WIN32_WCE
+extern bool isSmartphone(void);
+#endif
+
+namespace Simon {
+
+int SimonEngine::runScript() {
+ byte opcode;
+ bool flag, condition;
+
+ 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;
+ }
+
+ condition = true;
+
+ switch (opcode) {
+ case 1:{ /* ptrA parent is */
+ condition = (getItem1Ptr()->parent == getNextItemID());
+ }
+ break;
+
+ case 2:{ /* ptrA parent is not */
+ condition = (getItem1Ptr()->parent != getNextItemID());
+ }
+ break;
+
+ case 5:{ /* parent is 1 */
+ condition = (getNextItemPtr()->parent == getItem1ID());
+ }
+ break;
+
+ case 6:{ /* parent isnot 1 */
+ condition = (getNextItemPtr()->parent != getItem1ID());
+ }
+ break;
+
+ case 7:{ /* parent is */
+ Item *item = getNextItemPtr();
+ condition = (item->parent == getNextItemID());
+ }
+ break;
+
+ case 11:{ /* is zero */
+ condition = (getNextVarContents() == 0);
+ }
+ break;
+
+ case 12:{ /* isnot zero */
+ condition = (getNextVarContents() != 0);
+ }
+ break;
+
+ case 13:{ /* equal */
+ uint tmp = getNextVarContents();
+ condition = (tmp == getVarOrWord());
+ }
+ break;
+
+ case 14:{ /* not equal */
+ uint tmp = getNextVarContents();
+ condition = (tmp != getVarOrWord());
+ }
+ break;
+
+ case 15:{ /* is greater */
+ uint tmp = getNextVarContents();
+ condition = (tmp > getVarOrWord());
+ }
+ break;
+
+ case 16:{ /* is less */
+ uint tmp = getNextVarContents();
+ condition = (tmp < getVarOrWord());
+ }
+ break;
+
+ case 17:{ /* is eq f */
+ uint tmp = getNextVarContents();
+ condition = (tmp == getNextVarContents());
+ }
+ break;
+
+ case 18:{ /* is not equal f */
+ uint tmp = getNextVarContents();
+ condition = (tmp != getNextVarContents());
+ }
+ break;
+
+ case 19:{ /* is greater f */
+ uint tmp = getNextVarContents();
+ condition = (tmp < getNextVarContents());
+ }
+ break;
+
+ case 20:{ /* is less f */
+ uint tmp = getNextVarContents();
+ condition = (tmp > getNextVarContents());
+ }
+ break;
+
+ case 23:{
+ condition = o_chance(getVarOrWord());
+ }
+ break;
+
+ case 25:{ /* is room */
+ condition = isRoom(getNextItemPtr());
+ }
+ break;
+
+ case 26:{ /* is object */
+ condition = isObject(getNextItemPtr());
+ }
+ break;
+
+ case 27:{ /* item state is */
+ Item *item = getNextItemPtr();
+ condition = ((uint) item->state == getVarOrWord());
+ }
+ break;
+
+ case 28:{ /* item has prop */
+ Child2 *child = (Child2 *)findChildOfType(getNextItemPtr(), 2);
+ byte num = getVarOrByte();
+ condition = child != NULL && (child->avail_props & (1 << num)) != 0;
+ } break;
+
+ case 31:{ /* set no parent */
+ setItemParent(getNextItemPtr(), NULL);
+ }
+ break;
+
+ case 33:{ /* set item parent */
+ Item *item = getNextItemPtr();
+ setItemParent(item, getNextItemPtr());
+ }
+ break;
+
+ case 36:{ /* copy var */
+ uint value = getNextVarContents();
+ writeNextVarContents(value);
+ }
+ break;
+
+ case 41:{ /* zero var */
+ writeNextVarContents(0);
+ }
+ break;
+
+ case 42:{ /* set var */
+ uint var = getVarOrByte();
+ writeVariable(var, getVarOrWord());
+ }
+ break;
+
+ case 43:{ /* add */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) + getVarOrWord());
+ }
+ break;
+
+ case 44:{ /* sub */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) - getVarOrWord());
+ }
+ break;
+
+ case 45:{ /* add f */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) + getNextVarContents());
+ }
+ break;
+
+ case 46:{ /* sub f */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) - getNextVarContents());
+ }
+ break;
+
+ case 47:{ /* mul */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) * getVarOrWord());
+ }
+ break;
+
+ case 48:{ /* div */
+ uint var = getVarOrByte();
+ int value = getVarOrWord();
+ if (value == 0)
+ error("Division by zero in div");
+ writeVariable(var, readVariable(var) / value);
+ }
+ break;
+
+ case 49:{ /* mul f */
+ uint var = getVarOrByte();
+ writeVariable(var, readVariable(var) * getNextVarContents());
+ }
+ break;
+
+ 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;
+
+ case 51:{ /* mod */
+ uint var = getVarOrByte();
+ int value = getVarOrWord();
+ if (value == 0)
+ error("Division by zero in mod");
+ writeVariable(var, readVariable(var) % value);
+ }
+ break;
+
+ 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;
+
+ case 53:{ /* random */
+ uint var = getVarOrByte();
+ uint value = (uint16)getVarOrWord();
+
+ // 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;
+
+ case 55:{ /* set itemA parent */
+ setItemParent(getItem1Ptr(), getNextItemPtr());
+ }
+ break;
+
+ case 56:{ /* set child2 fr bit */
+ Child2 *child = (Child2 *)findChildOfType(getNextItemPtr(), 2);
+ int value = getVarOrByte();
+ if (child != NULL && value >= 0x10)
+ child->avail_props |= 1 << value;
+ }
+ break;
+
+ case 57:{ /* clear child2 fr bit */
+ Child2 *child = (Child2 *)findChildOfType(getNextItemPtr(), 2);
+ int value = getVarOrByte();
+ if (child != NULL && value >= 0x10)
+ child->avail_props &= ~(1 << value);
+ }
+ break;
+
+ case 58:{ /* make siblings */
+ Item *item = getNextItemPtr();
+ setItemParent(item, derefItem(getNextItemPtr()->parent));
+ }
+ break;
+
+ case 59:{ /* item inc state */
+ Item *item = getNextItemPtr();
+ if (item->state <= 30000)
+ setItemState(item, item->state + 1);
+ }
+ break;
+
+ case 60:{ /* item dec state */
+ Item *item = getNextItemPtr();
+ if (item->state >= 0)
+ setItemState(item, item->state - 1);
+ }
+ break;
+
+ 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;
+
+ case 62:{ /* show int */
+ showMessageFormat("%d", getNextVarContents());
+ }
+ break;
+
+ case 63:{ /* show string nl */
+ showMessageFormat("%s\n", getStringPtrByID(getNextStringID()));
+ }
+ break;
+
+ case 64:{ /* show string */
+ showMessageFormat("%s", getStringPtrByID(getNextStringID()));
+ }
+ break;
+
+ 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;
+
+ case 66:{ /* set item name */
+ uint var = getVarOrByte();
+ uint string_id = getNextStringID();
+ if (var < 20)
+ _stringIdArray2[var] = string_id;
+ }
+ break;
+
+ case 67:{ /* set item description */
+ uint var = getVarOrByte();
+ uint string_id = getNextStringID();
+ if (getFeatures() & GF_TALKIE) {
+ uint speechId = getNextWord();
+ if (var < 20) {
+ _stringIdArray3[var] = string_id;
+ _speechIdArray4[var] = speechId;
+ }
+ } else {
+ if (var < 20) {
+ _stringIdArray3[var] = string_id;
+ }
+ }
+ }
+ break;
+
+ case 68:{ /* exit interpreter */
+ shutdown();
+ }
+ break;
+
+ case 69:{ /* return 1 */
+ return 1;
+ }
+
+ case 70:{ /* show string from array */
+ const char *str = (const char *)getStringPtrByID(_stringIdArray3[getVarOrByte()]);
+
+ if (getGameType() == GType_SIMON2) {
+ writeVariable(51, strlen(str) / 53 * 8 + 8);
+ }
+
+ showMessageFormat("%s\n", str);
+ }
+ break;
+
+ case 71:{ /* start subroutine */
+ Subroutine *sub = getSubroutineByID(getVarOrWord());
+ if (sub != NULL)
+ startSubroutine(sub);
+ }
+ break;
+
+ case 76:{ /* add timeout */
+ uint timeout = getVarOrWord();
+ addTimeEvent(timeout, getVarOrWord());
+ }
+ break;
+
+ case 77:{ /* has item minus 1 */
+ condition = _subjectItem != NULL;
+ }
+ break;
+
+ case 78:{ /* has item minus 3 */
+ condition = _objectItem != NULL;
+ }
+ break;
+
+ case 79:{ /* childstruct fr2 is */
+ Child2 *child = (Child2 *)findChildOfType(getNextItemPtr(), 2);
+ uint string_id = getNextStringID();
+ condition = (child != NULL) && child->string_id == string_id;
+ }
+ break;
+
+ case 80:{ /* item equal */
+ condition = getNextItemPtr() == getNextItemPtr();
+ }
+ break;
+
+ case 82:{ /* debug opcode */
+ getVarOrByte();
+ }
+ break;
+
+ case 83:{ /* restart subroutine */
+ if (getGameType() == GType_SIMON2 || getGameType() == GType_FF)
+ o_83_helper();
+ return -10;
+ }
+
+ case 87:{ /* comment */
+ getNextStringID();
+ }
+ break;
+
+ case 88:{ /* stop animation */
+ _lockWord |= 0x10;
+ }
+ break;
+
+ case 89:{ /* restart animation */
+ _lockWord &= ~0x10;
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ case 96:{
+ uint val = getVarOrWord();
+ o_set_video_mode(getVarOrByte(), val);
+ }
+ break;
+
+ case 97:{ /* load vga */
+ o_loadZone(getVarOrWord());
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ case 100:{ /* vga reset */
+ o_vga_reset();
+ }
+ break;
+
+ case 101:{
+ uint a = getVarOrByte();
+ uint b = getVarOrWord();
+ uint c = getVarOrWord();
+ uint d = getVarOrWord();
+ uint e = getVarOrWord();
+ uint f = getVarOrWord();
+ uint g = getVarOrWord();
+ o_defineWindow(a, b, c, d, e, f, g, 0);
+ }
+ break;
+
+ case 102:{
+ changeWindow(getVarOrByte() & 7);
+ }
+ break;
+
+ case 103:{
+ o_unk_103();
+ }
+ break;
+
+ case 104:{
+ closeWindow(getVarOrByte() & 7);
+ }
+ break;
+
+ case 107:{ /* add item hitarea */
+ uint flags = 0;
+ uint id = getVarOrWord();
+ uint params = id / 1000;
+ uint x, y, w, h, unk3;
+ 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();
+ unk3 = getVarOrWord();
+ if (x >= 1000) {
+ unk3 += 0x4000;
+ x -= 1000;
+ }
+ addNewHitArea(id, x, y, w, h, flags, unk3, item);
+ }
+ break;
+
+ case 108:{ /* delete hitarea */
+ delete_hitarea(getVarOrWord());
+ }
+ break;
+
+ case 109:{ /* clear hitarea bit 0x40 */
+ clear_hitarea_bit_0x40(getVarOrWord());
+ }
+ break;
+
+ case 110:{ /* set hitarea bit 0x40 */
+ set_hitarea_bit_0x40(getVarOrWord());
+ }
+ break;
+
+ case 111:{ /* set hitarea xy */
+ uint hitarea_id = getVarOrWord();
+ uint x = getVarOrWord();
+ uint y = getVarOrWord();
+ set_hitarea_x_y(hitarea_id, x, y);
+ }
+ break;
+
+ case 114:{
+ Item *item = getNextItemPtr();
+ uint fcs_index = getVarOrByte();
+ mouseOff();
+ drawIconArray(fcs_index, item, 0, 0);
+ mouseOn();
+ }
+ break;
+
+ case 115:{ /* item has flag */
+ Item *item = getNextItemPtr();
+ condition = (item->classFlags & (1 << getVarOrByte())) != 0;
+ }
+ break;
+
+ case 116:{ /* item set flag */
+ Item *item = getNextItemPtr();
+ item->classFlags |= (1 << getVarOrByte());
+ }
+ break;
+
+ case 117:{ /* item clear flag */
+ Item *item = getNextItemPtr();
+ item->classFlags &= ~(1 << getVarOrByte());
+ }
+ break;
+
+ case 119:{ /* wait vga */
+ uint var = getVarOrWord();
+ _scriptVar2 = (var == 200);
+
+ if (var != 200 || !_skipVgaWait)
+ o_waitForSync(var);
+ _skipVgaWait = false;
+ }
+ break;
+
+ case 120:{
+ o_sync(getVarOrWord());
+ }
+ break;
+
+ case 121:{ /* set vga item */
+ uint slot = getVarOrByte();
+ _vcItemArray[slot] = getNextItemPtr();
+ }
+ break;
+
+ case 122:{ /* oracle text down */
+ if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2)
+ goto invalid_opcode;
+
+ warning("STUB: script opcode 122");
+ }
+ break;
+
+ case 123:{ /* oracle text down */
+ if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2)
+ goto invalid_opcode;
+
+ warning("STUB: script opcode 123");
+ }
+ break;
+
+ case 124:{ /* if time */
+ if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2)
+ goto invalid_opcode;
+
+ uint time = getVarOrWord();
+ condition = 1;
+ warning("STUB: script opcode 124 (%d)", time);
+ }
+ break;
+
+ case 125:{ /* item is sibling with item 1 */
+ Item *item = getNextItemPtr();
+ condition = (getItem1Ptr()->parent == item->parent);
+ }
+ break;
+
+ case 126:{
+ Item *item = getNextItemPtr();
+ uint fcs_index = getVarOrByte();
+ uint a = 1 << getVarOrByte();
+ mouseOff();
+ drawIconArray(fcs_index, item, 1, a);
+ mouseOn();
+ }
+ break;
+
+ case 127:{ /* deals with music */
+ o_playMusic();
+ }
+ break;
+
+ case 128:{ /* dummy instruction */
+ getVarOrWord();
+ }
+ break;
+
+ case 129:{ /* dummy instruction */
+ getVarOrWord();
+ condition = true;
+ }
+ break;
+
+ case 130:{ /* set adj noun */
+ uint var = getVarOrByte();
+ if (var == 1) {
+ _scriptAdj1 = getNextWord();
+ _scriptNoun1 = getNextWord();
+ } else {
+ _scriptAdj2 = getNextWord();
+ _scriptNoun2 = getNextWord();
+ }
+ }
+ break;
+
+ case 132:{ /* save game */
+ _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+ o_saveGame();
+ _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+ }
+ break;
+
+ 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;
+
+ case 134:{ /* dummy opcode? */
+ if (getGameType() == GType_FF) {
+ warning("STUB: script opcode 134");
+ } else {
+ midi.stop();
+ _lastMusicPlayed = -1;
+ }
+ }
+ break;
+
+ 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;
+
+ case 136:{ /* set var to item unk3 */
+ Item *item = getNextItemPtr();
+ writeNextVarContents(item->state);
+ }
+ break;
+
+ case 137:{
+ o_restoreIconArray(getVarOrByte());
+ }
+ break;
+
+ case 138:{ /* vga pointer op 4 */
+ o_freezeBottom();
+ }
+ break;
+
+ case 139:{ /* set parent special */
+ Item *item = getNextItemPtr();
+ _noParentNotify = true;
+ setItemParent(item, getNextItemPtr());
+ _noParentNotify = false;
+ }
+ break;
+
+ case 140:{ /* del te and add one */
+ killAllTimers();
+ addTimeEvent(3, 0xA0);
+ }
+ break;
+
+ case 141:{ /* set m1 or m3 */
+ uint which = getVarOrByte();
+ Item *item = getNextItemPtr();
+ if (which == 1) {
+ _subjectItem = item;
+ } else {
+ _objectItem = item;
+ }
+ }
+ break;
+
+ case 142:{ /* is hitarea 0x40 clear */
+ condition = is_hitarea_0x40_clear(getVarOrWord());
+ }
+ break;
+
+ case 143:{ /* start item sub */
+ Child1 *child = (Child1 *)findChildOfType(getNextItemPtr(), 1);
+ if (child != NULL) {
+ Subroutine *sub = getSubroutineByID(child->subroutine_id);
+ if (sub)
+ startSubroutine(sub);
+ }
+ }
+ break;
+
+ case 151:{ /* set array6 to item */
+ uint var = getVarOrByte();
+ Item *item = getNextItemPtr();
+ _itemArray6[var] = item;
+ }
+ break;
+
+ case 152:{ /* set m1 or m3 to array6 */
+ Item *item = _itemArray6[getVarOrByte()];
+ uint var = getVarOrByte();
+ if (var == 1) {
+ _subjectItem = item;
+ } else {
+ _objectItem = item;
+ }
+ }
+ break;
+
+ case 153:{ /* set bit */
+ uint bit = getVarOrByte();
+ _bitArray[bit / 16] |= 1 << (bit & 15);
+ break;
+ }
+
+ case 154:{ /* clear bit */
+ uint bit = getVarOrByte();
+ _bitArray[bit / 16] &= ~(1 << (bit & 15));
+ break;
+ }
+
+ case 155:{ /* is bit clear */
+ uint bit = getVarOrByte();
+ condition = (_bitArray[bit / 16] & (1 << (bit & 15))) == 0;
+ }
+ break;
+
+ case 156:{ /* is bit set */
+ uint bit = getVarOrByte();
+ if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) {
+ bit = 50;
+ }
+ condition = (_bitArray[bit / 16] & (1 << (bit & 15))) != 0;
+ }
+ break;
+
+ case 157:{ /* get item int prop */
+ Item *item = getNextItemPtr();
+ Child2 *child = (Child2 *)findChildOfType(item, 2);
+ uint prop = getVarOrByte();
+
+ if (child != NULL && child->avail_props & (1 << prop) && prop < 16) {
+ uint offs = getOffsetOfChild2Param(child, 1 << prop);
+ writeNextVarContents(child->array[offs]);
+ } else {
+ writeNextVarContents(0);
+ }
+ }
+ break;
+
+ case 158:{ /* set item prop */
+ Item *item = getNextItemPtr();
+ Child2 *child = (Child2 *)findChildOfType(item, 2);
+ uint prop = getVarOrByte();
+ int value = getVarOrWord();
+
+ if (child != NULL && child->avail_props & (1 << prop) && prop < 16) {
+ uint offs = getOffsetOfChild2Param(child, 1 << prop);
+ child->array[offs] = value;
+ }
+ }
+ break;
+
+ case 160:{
+ o_unk_160(getVarOrByte());
+ }
+ break;
+
+ case 161:{ /* setup text */
+ TextLocation *tl = getTextLocation(getVarOrByte());
+
+ tl->x = getVarOrWord();
+ tl->y = getVarOrByte();
+ tl->width = getVarOrWord();
+ }
+ break;
+
+ case 162:{ /* print string */
+ o_printStr();
+ }
+ break;
+
+ case 163:{ /* play sound */
+ o_playSFX(getVarOrWord());
+ }
+ break;
+
+ case 164:{
+ _showPreposition = true;
+ o_setup_cond_c();
+ _showPreposition = false;
+ }
+ break;
+
+ case 165:{ /* item unk1 unk2 is */
+ Item *item = getNextItemPtr();
+ int16 a = getNextWord(), b = getNextWord();
+ condition = (item->adjective == a && item->noun == b);
+ } break;
+
+ case 166:{ /* set bit2 */
+ uint bit = getVarOrByte();
+ _bitArray[(bit / 16) + 16] |= 1 << (bit & 15);
+ }
+ break;
+
+ case 167:{ /* clear bit2 */
+ uint bit = getVarOrByte();
+ _bitArray[(bit / 16) + 16] &= ~(1 << (bit & 15));
+ }
+ break;
+
+ case 168:{ /* is bit2 clear */
+ uint bit = getVarOrByte();
+ condition = (_bitArray[(bit / 16) + 16] & (1 << (bit & 15))) == 0;
+ }
+ break;
+
+ case 169:{ /* is bit2 set */
+ uint bit = getVarOrByte();
+ condition = (_bitArray[(bit / 16) + 16] & (1 << (bit & 15))) != 0;
+ }
+ break;
+
+ case 175:{ /* vga pointer op 1 */
+ o_lockZone();
+ }
+ break;
+
+ case 176:{ /* vga pointer op 2 */
+ o_unlockZone();
+ }
+ break;
+
+ case 177:{ /* inventory descriptions */
+ o_inventory_descriptions();
+ }
+ break;
+
+ case 178:{ /* path find */
+ uint a = getVarOrWord();
+ uint b = getVarOrWord();
+ uint c = getVarOrByte();
+ uint d = getVarOrByte();
+ o_pathfind(a, b, c, d);
+ }
+ break;
+
+ case 179:{ /* conversation responses */
+ uint vgaSpriteId = getVarOrByte(); /* and room descriptions */
+ uint color = getVarOrByte();
+ uint string_id = getVarOrByte();
+ uint speechId = 0;
+
+ const char *string_ptr = (const char *)getStringPtrByID(_stringIdArray3[string_id]);
+ TextLocation *tl = getTextLocation(vgaSpriteId);
+ if (getFeatures() & GF_TALKIE)
+ speechId = _speechIdArray4[string_id];
+
+ if (_speech && speechId != 0)
+ playSpeech(speechId, vgaSpriteId);
+ if (string_ptr != NULL && _subtitles)
+ printText(vgaSpriteId, color, string_ptr, tl->x, tl->y, tl->width);
+ }
+ break;
+
+ case 180:{ /* force mouseOn */
+ o_mouseOn();
+ }
+ break;
+
+ case 181:{ /* force mouseOff */
+ o_mouseOff();
+ if (getGameType() == GType_SIMON2) {
+ changeWindow(1);
+ showMessageFormat("\xC");
+ }
+ }
+ break;
+
+ 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;
+
+ 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;
+
+ case 184:{ /* clear vgapointer entry */
+ o_unloadZone(getVarOrWord());
+ }
+ break;
+
+ 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);
+ }
+
+ }
+ break;
+
+ case 186:{ /* vga pointer op 3 */
+ o_unfreezeBottom();
+ }
+ break;
+
+ case 187:{ /* fade to black */
+ if (getGameType() == GType_SIMON2)
+ goto invalid_opcode;
+ o_fadeToBlack();
+ }
+ break;
+
+ case 188: /* string2 is */
+ if (getGameType() == GType_SIMON1)
+ goto invalid_opcode;
+ {
+ uint i = getVarOrByte();
+ uint str = getNextStringID();
+ condition = (str < 20 && _stringIdArray2[i] == str);
+ }
+ break;
+
+ case 189:{ /* clear_op189_flag */
+ if (getGameType() == GType_SIMON1)
+ goto invalid_opcode;
+ _marks = 0;
+ }
+ break;
+
+ case 190:{
+ uint i;
+ if (getGameType() == GType_SIMON1)
+ goto invalid_opcode;
+ i = getVarOrByte();
+ if (!(_marks & (1 << i)))
+ o_waitForMark(i);
+ }
+ break;
+
+ // Feeble opcodes
+ case 191:
+ if (_bitArray[5] & 0x0008) {
+ _PVCount1 = 0;
+ _GPVCount1 = 0;
+ } else {
+ _PVCount = 0;
+ _GPVCount = 0;
+ }
+ break;
+
+ case 192:{
+ uint8 a = getVarOrByte();
+ uint8 b = getVarOrByte();
+ uint8 c = getVarOrByte();
+ uint8 d = getVarOrByte();
+ if (_bitArray[5] & 0x0008) {
+ _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;
+
+ case 193:
+ // pause clock
+ warning("STUB: script opcode 193");
+ break;
+
+ case 194:
+ // resume clock
+ warning("STUB: script opcode 194");
+ break;
+
+ 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;
+
+ case 196:{ /* set bit3 */
+ uint bit = getVarOrByte();
+ _bitArray[(bit / 16) + 32] |= 1 << (bit & 15);
+ }
+ break;
+
+ case 197:{ /* clear bit3 */
+ uint bit = getVarOrByte();
+ _bitArray[(bit / 16) + 32] &= ~(1 << (bit & 15));
+ }
+ break;
+
+ case 198:{ /* is bit3 clear */
+ uint bit = getVarOrByte();
+ condition = (_bitArray[(bit / 16) + 32] & (1 << (bit & 15))) == 0;
+ }
+ break;
+
+ case 199:{ /* is bit3 set */
+ uint bit = getVarOrByte();
+ condition = (_bitArray[(bit / 16) + 32] & (1 << (bit & 15))) != 0;
+ }
+ break;
+
+ default:
+ invalid_opcode:;
+ error("Invalid opcode '%d'", opcode);
+ }
+
+ } while (condition != flag);
+
+ return 0;
+}
+
+int SimonEngine::startSubroutine(Subroutine *sub) {
+ int result = -1;
+ SubroutineLine *sl;
+ const byte *old_code_ptr;
+
+ if (_startMainScript)
+ dumpSubroutine(sub);
+
+ old_code_ptr = _codePtr;
+
+ if (++_recursionDepth > 40)
+ error("Recursion error");
+
+ sl = (SubroutineLine *)((byte *)sub + sub->first);
+
+ while ((byte *)sl != (byte *)sub) {
+ if (checkIfToRunSubroutineLine(sl, sub)) {
+ result = 0;
+ _codePtr = (byte *)sl;
+ if (sub->id)
+ _codePtr += 2;
+ else
+ _codePtr += 8;
+
+ if (_continousMainScript)
+ fprintf(_dumpFile, "; %d\n", sub->id);
+ result = runScript();
+ if (result != 0) {
+ /* result -10 means restart subroutine */
+ if (result == -10) {
+ delay(0); /* maybe leave control to the VGA */
+ sl = (SubroutineLine *)((byte *)sub + sub->first);
+ continue;
+ }
+ break;
+ }
+ }
+ sl = (SubroutineLine *)((byte *)sub + sl->next);
+ }
+
+ _codePtr = old_code_ptr;
+
+ _recursionDepth--;
+ return result;
+}
+
+int SimonEngine::startSubroutineEx(Subroutine *sub) {
+ return startSubroutine(sub);
+}
+
+bool SimonEngine::checkIfToRunSubroutineLine(SubroutineLine *sl, Subroutine *sub) {
+ if (sub->id)
+ return true;
+
+ if (sl->verb != -1 && sl->verb != _scriptVerb &&
+ (sl->verb != -2 || _scriptVerb != -1))
+ return false;
+
+ if (sl->noun1 != -1 && sl->noun1 != _scriptNoun1 &&
+ (sl->noun1 != -2 || _scriptNoun1 != -1))
+ return false;
+
+ if (sl->noun2 != -1 && sl->noun2 != _scriptNoun2 &&
+ (sl->noun2 != -2 || _scriptNoun2 != -1))
+ return false;
+
+ return true;
+}
+
+void SimonEngine::o_83_helper() {
+ if (_exitCutscene) {
+ if (vcGetBit(9)) {
+ endCutscene();
+ }
+ } else {
+ processSpecialKeys();
+ }
+}
+
+void SimonEngine::o_waitForMark(uint i) {
+ _exitCutscene = false;
+ while (!(_marks & (1 << i))) {
+ if (_exitCutscene) {
+ if (vcGetBit(9)) {
+ endCutscene();
+ break;
+ }
+ } else {
+ processSpecialKeys();
+ }
+
+ delay(10);
+ }
+}
+
+
+bool SimonEngine::o_chance(uint a) {
+ if (a == 0)
+ return 0;
+
+ if (a == 100)
+ return 1;
+
+ a += _scriptUnk1;
+ if (a <= 0) {
+ _scriptUnk1 = 0;
+ return 0;
+ }
+
+ if ((uint)_rnd.getRandomNumber(99) < a) {
+ if (_scriptUnk1 <= 0)
+ _scriptUnk1 -= 5;
+ else
+ _scriptUnk1 = 0;
+ return 1;
+ }
+
+ if (_scriptUnk1 >= 0)
+ _scriptUnk1 += 5;
+ else
+ _scriptUnk1 = 0;
+
+ return 0;
+}
+
+void SimonEngine::o_inventory_descriptions() {
+ uint vgaSpriteId = getVarOrByte();
+ uint color = getVarOrByte();
+ const char *string_ptr = NULL;
+ TextLocation *tl = NULL;
+ char buf[256];
+
+ Child2 *child = (Child2 *)findChildOfType(getNextItemPtr(), 2);
+ if (child != NULL && child->avail_props & 1) {
+ string_ptr = (const char *)getStringPtrByID(child->array[0]);
+ tl = getTextLocation(vgaSpriteId);
+ }
+
+ if ((getGameType() == GType_SIMON2) && (getFeatures() & GF_TALKIE)) {
+ if (child != NULL && child->avail_props & 0x200) {
+ uint speechId = child->array[getOffsetOfChild2Param(child, 0x200)];
+
+ if (child->avail_props & 0x100) {
+ uint speechIdOffs = child->array[getOffsetOfChild2Param(child, 0x100)];
+
+ if (speechId == 116)
+ speechId = speechIdOffs + 115;
+ if (speechId == 92)
+ speechId = speechIdOffs + 98;
+ if (speechId == 99)
+ speechId = 9;
+ if (speechId == 97) {
+ switch (speechIdOffs) {
+ case 12:
+ speechId = 109;
+ break;
+ case 14:
+ speechId = 108;
+ break;
+ case 18:
+ speechId = 107;
+ break;
+ case 20:
+ speechId = 106;
+ break;
+ case 22:
+ speechId = 105;
+ break;
+ case 28:
+ speechId = 104;
+ break;
+ case 90:
+ speechId = 103;
+ break;
+ case 92:
+ speechId = 102;
+ break;
+ case 100:
+ speechId = 51;
+ break;
+ default:
+ error("o_177: invalid case %d", speechIdOffs);
+ }
+ }
+ }
+
+ if (_speech)
+ playSpeech(speechId, vgaSpriteId);
+ }
+
+ } else if (getFeatures() & GF_TALKIE) {
+ if (child != NULL && child->avail_props & 0x200) {
+ uint offs = getOffsetOfChild2Param(child, 0x200);
+ playSpeech(child->array[offs], vgaSpriteId);
+ } else if (child != NULL && child->avail_props & 0x100) {
+ uint offs = getOffsetOfChild2Param(child, 0x100);
+ playSpeech(child->array[offs] + 3550, vgaSpriteId);
+ }
+ }
+
+ if (child != NULL && (child->avail_props & 1) && _subtitles) {
+ if (child->avail_props & 0x100) {
+ sprintf(buf, "%d%s", child->array[getOffsetOfChild2Param(child, 0x100)], string_ptr);
+ string_ptr = buf;
+ }
+ if (string_ptr != NULL)
+ printText(vgaSpriteId, color, string_ptr, tl->x, tl->y, tl->width);
+ }
+}
+
+void SimonEngine::o_confirmQuit() {
+ // If all else fails, use English as fallback.
+ byte keyYes = 'y';
+ byte keyNo = 'n';
+
+ switch (_language) {
+ case Common::RU_RUS:
+ break;
+ case Common::PL_POL:
+ keyYes = 't';
+ break;
+ case Common::HB_ISR:
+ keyYes = 'f';
+ break;
+ case Common::ES_ESP:
+ keyYes = 's';
+ break;
+ case Common::IT_ITA:
+ keyYes = 's';
+ break;
+ case Common::FR_FRA:
+ keyYes = 'o';
+ break;
+ case Common::DE_DEU:
+ keyYes = 'j';
+ break;
+ default:
+ break;
+ }
+
+ for (;;) {
+ delay(1);
+#ifdef _WIN32_WCE
+ if (isSmartphone()) {
+ if (_keyPressed) {
+ if (_keyPressed == 13)
+ shutdown();
+ else
+ break;
+ }
+ }
+#endif
+ if (_keyPressed == keyYes)
+ shutdown();
+ else if (_keyPressed == keyNo)
+ break;
+ }
+}
+
+void SimonEngine::o_restoreIconArray(uint fcs_index) {
+ FillOrCopyStruct *fcs;
+
+ fcs = _windowArray[fcs_index & 7];
+ if (fcs->fcs_data == NULL)
+ return;
+ drawIconArray(fcs_index, fcs->fcs_data->item_ptr, fcs->fcs_data->unk1, fcs->fcs_data->unk2);
+}
+
+void SimonEngine::o_freezeBottom() {
+ _vgaBufStart = _vgaBufFreeStart;
+ _vgaFileBufOrg = _vgaBufFreeStart;
+}
+
+void SimonEngine::o_unfreezeBottom() {
+ _vgaBufFreeStart = _vgaFileBufOrg2;
+ _vgaBufStart = _vgaFileBufOrg2;
+ _vgaFileBufOrg = _vgaFileBufOrg2;
+}
+
+void SimonEngine::o_lockZone() {
+ _vgaBufStart = _vgaBufFreeStart;
+}
+
+void SimonEngine::o_unlockZone() {
+ _vgaBufFreeStart = _vgaFileBufOrg;
+ _vgaBufStart = _vgaFileBufOrg;
+}
+
+int SimonEngine::o_unk_132_helper(bool *b, char *buf) {
+ HitArea *ha;
+ *b = true;
+
+ if (!_saveLoadFlag) {
+ strange_jump:;
+ _saveLoadFlag = false;
+ saveGameDialog(buf);
+ }
+
+start_over:;
+ _keyPressed = 0;
+
+start_over_2:;
+ _lastHitArea = _lastHitArea3 = 0;
+
+ do {
+ if (_keyPressed != 0) {
+ if (_saveLoadFlag) {
+ *b = false;
+ return _keyPressed;
+ }
+ goto start_over;
+ }
+ delay(100);
+ } while (_lastHitArea3 == 0);
+
+ ha = _lastHitArea;
+
+ if (ha == NULL || ha->id < 205)
+ goto start_over_2;
+
+ if (ha->id == 205)
+ return ha->id;
+
+ if (ha->id == 206) {
+ if (_saveLoadRowCurPos == 1)
+ goto start_over_2;
+ if (_saveLoadRowCurPos < 7)
+ _saveLoadRowCurPos = 1;
+ else
+ _saveLoadRowCurPos -= 6;
+
+ goto strange_jump;
+ }
+
+ if (ha->id == 207) {
+ if (!_saveDialogFlag)
+ goto start_over_2;
+ _saveLoadRowCurPos += 6;
+ if (_saveLoadRowCurPos >= _numSaveGameRows)
+ _saveLoadRowCurPos = _numSaveGameRows;
+ goto strange_jump;
+ }
+
+ if (ha->id >= 214)
+ goto start_over_2;
+ return ha->id - 208;
+}
+
+void SimonEngine::o_unk_132_helper_3() {
+ for (int i = 208; i != 208 + 6; i++)
+ set_hitarea_bit_0x40(i);
+}
+
+void SimonEngine::o_clearCharacter(FillOrCopyStruct *fcs, int x, byte b) {
+ byte old_text;
+
+ video_putchar(fcs, x, b);
+ old_text = fcs->text_color;
+ fcs->text_color = fcs->fill_color;
+
+ if (_language == Common::HB_ISR) { //Hebrew
+ x = 128;
+ } else {
+ x += 120;
+ if (x != 128)
+ x = 129;
+
+ }
+
+ video_putchar(fcs, x);
+
+ fcs->text_color = old_text;
+ video_putchar(fcs, 8);
+}
+
+void SimonEngine::o_playMusic() {
+ int music = getVarOrWord();
+ int track = getVarOrWord();
+
+ // Jamieson630:
+ // This appears to be a "load or play music" command.
+ // The music resource is specified, and optionally
+ // a track as well. Normally we see two calls being
+ // made, one to load the resource and another to
+ // actually start a track (so the resource is
+ // effectively preloaded so there's no latency when
+ // starting playback).
+ if (getGameType() == GType_SIMON2) {
+ int loop = getVarOrByte();
+
+ midi.setLoop (loop != 0);
+ if (_lastMusicPlayed != music)
+ _nextMusicToPlay = music;
+ else
+ midi.startTrack (track);
+ } else {
+ if (music != _lastMusicPlayed) {
+ _lastMusicPlayed = music;
+ loadMusic (music);
+ midi.startTrack (track);
+ }
+ }
+}
+
+void SimonEngine::o_sync(uint a) {
+ uint16 id = to16Wrapper(a);
+ _lockWord |= 0x8000;
+ _vcPtr = (byte *)&id;
+ vc15_wakeup_id();
+ _lockWord &= ~0x8000;
+}
+
+void SimonEngine::o_playSFX(uint sound_id) {
+ if (getGameId() == GID_SIMON1DOS)
+ playSting(sound_id);
+ else
+ _sound->playEffects(sound_id);
+}
+
+void SimonEngine::o_unk_160(uint a) {
+ fcs_setTextColor(_windowArray[_curWindow], a);
+}
+
+void SimonEngine::o_unk_103() {
+ mouseOff();
+ removeIconArray(_curWindow);
+ if (getGameType() == GType_FF)
+ showMessageFormat("\x0E");
+ else
+ showMessageFormat("\x0C");
+ mouseOn();
+}
+
+void SimonEngine::o_kill_sprite_simon1(uint a) {
+ uint16 b = to16Wrapper(a);
+ _lockWord |= 0x8000;
+ _vcPtr = (byte *)&b;
+ vc60_killSprite();
+ _lockWord &= ~0x8000;
+}
+
+void SimonEngine::o_kill_sprite_simon2(uint a, uint b) {
+ uint16 items[2];
+
+ items[0] = to16Wrapper(a);
+ items[1] = to16Wrapper(b);
+
+ _lockWord |= 0x8000;
+ _vcPtr = (byte *)&items;
+ vc60_killSprite();
+ _lockWord &= ~0x8000;
+}
+
+/* OK */
+void SimonEngine::o_defineWindow(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h) {
+ a &= 7;
+
+ if (_windowArray[a])
+ closeWindow(a);
+
+ _windowArray[a] = openWindow(b, c, d, e, f, g, h);
+
+ if (a == _curWindow) {
+ _textWindow = _windowArray[a];
+ showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength);
+ }
+}
+
+} // End of namespace Simon