/* 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 { // 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"); } } // ----------------------------------------------------------------------- // Simon 1 Opcodes // ----------------------------------------------------------------------- void SimonEngine::o1_at(bool &cond, int &ret) { // 1: ptrA parent is cond = (getItem1Ptr()->parent == getNextItemID()); } void SimonEngine::o1_notAt(bool &cond, int &ret) { // 2: ptrA parent is not cond = (getItem1Ptr()->parent != getNextItemID()); } void SimonEngine::o1_carried(bool &cond, int &ret) { // 5: parent is 1 cond = (getNextItemPtr()->parent == getItem1ID()); } void SimonEngine::o1_notCarried(bool &cond, int &ret) { // 6: parent isnot 1 cond = (getNextItemPtr()->parent != getItem1ID()); } void SimonEngine::o1_isAt(bool &cond, int &ret) { // 7: parent is Item *item = getNextItemPtr(); cond = (item->parent == getNextItemID()); } void SimonEngine::o1_zero(bool &cond, int &ret) { // 11: is zero cond = (getNextVarContents() == 0); } void SimonEngine::o1_notZero(bool &cond, int &ret) { // 12: isnot zero cond = (getNextVarContents() != 0); } void SimonEngine::o1_eq(bool &cond, int &ret) { // 13: equal uint tmp = getNextVarContents(); cond = (tmp == getVarOrWord()); } void SimonEngine::o1_notEq(bool &cond, int &ret) { // 14: not equal uint tmp = getNextVarContents(); cond = (tmp != getVarOrWord()); } void SimonEngine::o1_gt(bool &cond, int &ret) { // 15: is greater uint tmp = getNextVarContents(); cond = (tmp > getVarOrWord()); } void SimonEngine::o1_lt(bool &cond, int &ret) { // 16: is less uint tmp = getNextVarContents(); cond = (tmp < getVarOrWord()); } void SimonEngine::o1_eqf(bool &cond, int &ret) { // 17: is eq f uint tmp = getNextVarContents(); cond = (tmp == getNextVarContents()); } void SimonEngine::o1_notEqf(bool &cond, int &ret) { // 18: is not equal f uint tmp = getNextVarContents(); cond = (tmp != getNextVarContents()); } void SimonEngine::o1_ltf(bool &cond, int &ret) { // 19: is greater f uint tmp = getNextVarContents(); cond = (tmp < getNextVarContents()); } void SimonEngine::o1_gtf(bool &cond, int &ret) { // 20: is less f uint tmp = getNextVarContents(); cond = (tmp > getNextVarContents()); } void SimonEngine::o1_chance(bool &cond, int &ret) { // 23 cond = o_chance(getVarOrWord()); } void SimonEngine::o1_isRoom(bool &cond, int &ret) { // 25: is room cond = isRoom(getNextItemPtr()); } void SimonEngine::o1_isObject(bool &cond, int &ret) { // 26: is object cond = isObject(getNextItemPtr()); } void SimonEngine::o1_state(bool &cond, int &ret) { // 27: item state is Item *item = getNextItemPtr(); cond = ((uint) item->state == getVarOrWord()); } 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; } void SimonEngine::o1_destroy(bool &cond, int &ret) { // 31: set no parent setItemParent(getNextItemPtr(), NULL); } void SimonEngine::o1_place(bool &cond, int &ret) { // 33: set item parent Item *item = getNextItemPtr(); setItemParent(item, getNextItemPtr()); } void SimonEngine::o1_copyff(bool &cond, int &ret) { // 36: copy var uint value = getNextVarContents(); writeNextVarContents(value); } void SimonEngine::o1_clear(bool &cond, int &ret) { // 41: zero var writeNextVarContents(0); } void SimonEngine::o1_let(bool &cond, int &ret) { // 42: set var uint var = getVarOrByte(); writeVariable(var, getVarOrWord()); } void SimonEngine::o1_add(bool &cond, int &ret) { // 43: add uint var = getVarOrByte(); writeVariable(var, readVariable(var) + getVarOrWord()); } void SimonEngine::o1_sub(bool &cond, int &ret) { // 44: sub uint var = getVarOrByte(); writeVariable(var, readVariable(var) - getVarOrWord()); } void SimonEngine::o1_addf(bool &cond, int &ret) { // 45: add f uint var = getVarOrByte(); writeVariable(var, readVariable(var) + getNextVarContents()); } void SimonEngine::o1_subf(bool &cond, int &ret) { // 46: sub f uint var = getVarOrByte(); writeVariable(var, readVariable(var) - getNextVarContents()); } void SimonEngine::o1_mul(bool &cond, int &ret) { // 47: mul uint var = getVarOrByte(); writeVariable(var, readVariable(var) * getVarOrWord()); } 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); } void SimonEngine::o1_mulf(bool &cond, int &ret) { // 49: mul f uint var = getVarOrByte(); writeVariable(var, readVariable(var) * getNextVarContents()); } 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); } 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); } 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); } void SimonEngine::o1_random(bool &cond, int &ret) { // 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)); } void SimonEngine::o1_goto(bool &cond, int &ret) { // 55: set itemA parent setItemParent(getItem1Ptr(), getNextItemPtr()); } 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; } 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); } void SimonEngine::o1_putBy(bool &cond, int &ret) { // 58: make siblings Item *item = getNextItemPtr(); setItemParent(item, derefItem(getNextItemPtr()->parent)); } void SimonEngine::o1_inc(bool &cond, int &ret) { // 59: item inc state Item *item = getNextItemPtr(); if (item->state <= 30000) setItemState(item, item->state + 1); } void SimonEngine::o1_dec(bool &cond, int &ret) { // 60: item dec state Item *item = getNextItemPtr(); if (item->state >= 0) setItemState(item, item->state - 1); } 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); } void SimonEngine::o1_print(bool &cond, int &ret) { // 62: show int showMessageFormat("%d", getNextVarContents()); } void SimonEngine::o1_message(bool &cond, int &ret) { // 63: show string nl showMessageFormat("%s\n", getStringPtrByID(getNextStringID())); } void SimonEngine::o1_msg(bool &cond, int &ret) { // 64: show string showMessageFormat("%s", getStringPtrByID(getNextStringID())); } 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); } void SimonEngine::o1_setShortText(bool &cond, int &ret) { // 66: set item name uint var = getVarOrByte(); uint stringId = getNextStringID(); if (var < 20) _stringIdArray2[var] = stringId; } 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; } } } void SimonEngine::o1_end(bool &cond, int &ret) { // 68: exit interpreter shutdown(); } void SimonEngine::o1_done(bool &cond, int &ret) { // 69: return 1 ret = 1; } 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); } void SimonEngine::o1_process(bool &cond, int &ret) { // 71: start subroutine Subroutine *sub = getSubroutineByID(getVarOrWord()); if (sub != NULL) startSubroutine(sub); } void SimonEngine::o1_when(bool &cond, int &ret) { // 76: add timeout uint timeout = getVarOrWord(); addTimeEvent(timeout, getVarOrWord()); } void SimonEngine::o1_if1(bool &cond, int &ret) { // 77: has item minus 1 cond = _subjectItem != NULL; } void SimonEngine::o1_if2(bool &cond, int &ret) { // 78: has item minus 3 cond = _objectItem != NULL; } 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; } void SimonEngine::o1_is(bool &cond, int &ret) { // 80: item equal cond = getNextItemPtr() == getNextItemPtr(); } void SimonEngine::o1_debug(bool &cond, int &ret) { // 82: debug opcode getVarOrByte(); } void SimonEngine::o1_rescan(bool &cond, int &ret) { // 83: restart subroutine ret = -10; } void SimonEngine::o1_comment(bool &cond, int &ret) { // 87: comment getNextStringID(); } void SimonEngine::o1_haltAnimation(bool &cond, int &ret) { // 88: stop animation _lockWord |= 0x10; } void SimonEngine::o1_restartAnimation(bool &cond, int &ret) { // 89: restart animation _lockWord &= ~0x10; } 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"); } } 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"); } } 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"); } } void SimonEngine::o1_picture(bool &cond, int &ret) { // 96 uint val = getVarOrWord(); o_set_video_mode(getVarOrByte(), val); } void SimonEngine::o1_loadZone(bool &cond, int &ret) { // 97: load vga o_loadZone(getVarOrWord()); } 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); } void SimonEngine::o1_stopAnimate(bool &cond, int &ret) { // 99: kill sprite o_kill_sprite_simon1(getVarOrWord()); } void SimonEngine::o1_killAnimate(bool &cond, int &ret) { // 100: vga reset o_vga_reset(); } 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); } void SimonEngine::o1_window(bool &cond, int &ret) { // 102 changeWindow(getVarOrByte() & 7); } void SimonEngine::o1_cls(bool &cond, int &ret) { // 103 o_unk_103(); } void SimonEngine::o1_closeWindow(bool &cond, int &ret) { // 104 closeWindow(getVarOrByte() & 7); } 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); } void SimonEngine::o1_delBox(bool &cond, int &ret) { // 108: delete hitarea delete_hitarea(getVarOrWord()); } void SimonEngine::o1_enableBox(bool &cond, int &ret) { // 109: clear hitarea bit 0x40 clear_hitarea_bit_0x40(getVarOrWord()); } void SimonEngine::o1_disableBox(bool &cond, int &ret) { // 110: set hitarea bit 0x40 set_hitarea_bit_0x40(getVarOrWord()); } 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); } void SimonEngine::o1_doIcons(bool &cond, int &ret) { // 114 Item *item = getNextItemPtr(); uint num = getVarOrByte(); mouseOff(); drawIconArray(num, item, 0, 0); mouseOn(); } void SimonEngine::o1_isClass(bool &cond, int &ret) { // 115: item has flag Item *item = getNextItemPtr(); cond = (item->classFlags & (1 << getVarOrByte())) != 0; } void SimonEngine::o1_setClass(bool &cond, int &ret) { // 116: item set flag Item *item = getNextItemPtr(); item->classFlags |= (1 << getVarOrByte()); } void SimonEngine::o1_unsetClass(bool &cond, int &ret) { // 117: item clear flag Item *item = getNextItemPtr(); item->classFlags &= ~(1 << getVarOrByte()); } void SimonEngine::o1_waitSync(bool &cond, int &ret) { // 119: wait vga uint var = getVarOrWord(); _scriptVar2 = (var == 200); if (var != 200 || !_skipVgaWait) o_waitForSync(var); _skipVgaWait = false; } void SimonEngine::o1_sync(bool &cond, int &ret) { // 120: sync o_sync(getVarOrWord()); } void SimonEngine::o1_defObj(bool &cond, int &ret) { // 121: set vga item uint slot = getVarOrByte(); _vcItemArray[slot] = getNextItemPtr(); } void SimonEngine::o1_here(bool &cond, int &ret) { // 125: item is sibling with item 1 Item *item = getNextItemPtr(); cond = (getItem1Ptr()->parent == item->parent); } 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(); } void SimonEngine::o1_playTune(bool &cond, int &ret) { // 127: deals with music o_playMusic(); } void SimonEngine::o1_waitEndTune(bool &cond, int &ret) { // 128: dummy instruction getVarOrWord(); } void SimonEngine::o1_ifEndTune(bool &cond, int &ret) { // 129: dummy instruction getVarOrWord(); cond = true; } 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(); } } void SimonEngine::o1_saveUserGame(bool &cond, int &ret) { // 132: save game _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); o_saveGame(); _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } void SimonEngine::o1_loadUserGame(bool &cond, int &ret) { // 133: load game _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); o_loadGame(); _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } void SimonEngine::o1_stopTune(bool &cond, int &ret) { // 134: dummy opcode? midi.stop(); _lastMusicPlayed = -1; } 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); } void SimonEngine::o1_copysf(bool &cond, int &ret) { // 136: set var to item unk3 Item *item = getNextItemPtr(); writeNextVarContents(item->state); } void SimonEngine::o1_restoreIcons(bool &cond, int &ret) { // 137 o_restoreIconArray(getVarOrByte()); } void SimonEngine::o1_freezeZones(bool &cond, int &ret) { // 138: vga pointer op 4 o_freezeBottom(); } void SimonEngine::o1_placeNoIcons(bool &cond, int &ret) { // 139: set parent special Item *item = getNextItemPtr(); _noParentNotify = true; setItemParent(item, getNextItemPtr()); _noParentNotify = false; } void SimonEngine::o1_clearTimers(bool &cond, int &ret) { // 140: del te and add one killAllTimers(); addTimeEvent(3, 0xA0); } 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; } } void SimonEngine::o1_isBox(bool &cond, int &ret) { // 142: is hitarea 0x40 clear cond = is_hitarea_0x40_clear(getVarOrWord()); } 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); } } void SimonEngine::o1_storeItem(bool &cond, int &ret) { // 151: set array6 to item uint var = getVarOrByte(); Item *item = getNextItemPtr(); _itemArray6[var] = item; } 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; } } void SimonEngine::o1_bSet(bool &cond, int &ret) { // 153: set bit setBitFlag(getVarOrByte(), true); } void SimonEngine::o1_bClear(bool &cond, int &ret) { // 154: clear bit setBitFlag(getVarOrByte(), false); } void SimonEngine::o1_bZero(bool &cond, int &ret) { // 155: is bit clear cond = !getBitFlag(getVarOrByte()); } void SimonEngine::o1_bNotZero(bool &cond, int &ret) { // 156: is bit set uint bit = getVarOrByte(); // WORKAROUND: Fix for glitch in some versions if (getGameType() == GType_SIMON1 && _subroutine == 2962 && bit == 63) { bit = 50; } cond = getBitFlag(bit); } 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(); if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { uint offs = getOffsetOfChild2Param(subObject, 1 << prop); writeNextVarContents(subObject->objectFlagValue[offs]); } else { writeNextVarContents(0); } } 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(); if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { uint offs = getOffsetOfChild2Param(subObject, 1 << prop); subObject->objectFlagValue[offs] = value; } } void SimonEngine::o1_ink(bool &cond, int &ret) { // 160 o_setTextColor(getVarOrByte()); } void SimonEngine::o1_screenTextBox(bool &cond, int &ret) { // 161: setup text TextLocation *tl = getTextLocation(getVarOrByte()); tl->x = getVarOrWord(); tl->y = getVarOrByte(); tl->width = getVarOrWord(); } void SimonEngine::o1_screenTextMsg(bool &cond, int &ret) { // 162: print string o_printStr(); } void SimonEngine::o1_playEffect(bool &cond, int &ret) { // 163: play sound o_playSFX(getVarOrWord()); } void SimonEngine::o1_getDollar2(bool &cond, int &ret) { // 164 _showPreposition = true; o_setup_cond_c(); _showPreposition = false; } 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); } void SimonEngine::o1_b2Set(bool &cond, int &ret) { // 166: set bit2 setBitFlag(256 + getVarOrByte(), true); } void SimonEngine::o1_b2Clear(bool &cond, int &ret) { // 167: clear bit2 setBitFlag(256 + getVarOrByte(), false); } void SimonEngine::o1_b2Zero(bool &cond, int &ret) { // 168: is bit2 clear cond = !getBitFlag(256 + getVarOrByte()); } void SimonEngine::o1_b2NotZero(bool &cond, int &ret) { // 169: is bit2 set cond = getBitFlag(256 + getVarOrByte()); } void SimonEngine::o1_lockZones(bool &cond, int &ret) { // 175: vga pointer op 1 o_lockZone(); } void SimonEngine::o1_unlockZones(bool &cond, int &ret) { // 176: vga pointer op 2 o_unlockZone(); } void SimonEngine::o1_screenTextPObj(bool &cond, int &ret) { // 177: inventory descriptions o_inventory_descriptions(); } 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); } 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); } void SimonEngine::o1_mouseOn(bool &cond, int &ret) { // 180: force mouseOn o_mouseOn(); } void SimonEngine::o1_mouseOff(bool &cond, int &ret) { // 181: force mouseOff o_mouseOff(); } void SimonEngine::o1_loadBeard(bool &cond, int &ret) { // 182: load beard o_loadBeard(); } void SimonEngine::o1_unloadBeard(bool &cond, int &ret) { // 183: unload beard o_unloadBeard(); } void SimonEngine::o1_unloadZone(bool &cond, int &ret) { // 184: clear vgapointer entry o_unloadZone(getVarOrWord()); } 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); } } void SimonEngine::o1_unfreezeZones(bool &cond, int &ret) { // 186: vga pointer op 3 o_unfreezeBottom(); } void SimonEngine::o1_specialFade(bool &cond, int &ret) { // 187: fade to black o_fadeToBlack(); } // ----------------------------------------------------------------------- // Simon 2 Opcodes // ----------------------------------------------------------------------- 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); } void SimonEngine::o2_rescan(bool &cond, int &ret) { // 83: restart subroutine o_83_helper(); ret = -10; } 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); } void SimonEngine::o2_stopAnimate(bool &cond, int &ret) { // 99: kill sprite uint a = getVarOrWord(); uint b = getVarOrWord(); o_kill_sprite_simon2(a, b); } void SimonEngine::o2_mouseOff(bool &cond, int &ret) { // 181: force mouseOff o_mouseOff(); changeWindow(1); showMessageFormat("\xC"); } void SimonEngine::o2_isShortText(bool &cond, int &ret) { // 188: string2 is uint i = getVarOrByte(); uint str = getNextStringID(); cond = (str < 20 && _stringIdArray2[i] == str); } void SimonEngine::o2_clearMarks(bool &cond, int &ret) { // 189: clear_op189_flag _marks = 0; } void SimonEngine::o2_waitMark(bool &cond, int &ret) { // 190 uint i = getVarOrByte(); if (!(_marks & (1 << i))) o_waitForMark(i); } // ----------------------------------------------------------------------- // Feeble Files Opcodes // ----------------------------------------------------------------------- void SimonEngine::o3_jumpOut(bool &cond, int &ret) { // 37 getVarOrByte(); ret = 1; } 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); } void SimonEngine::o3_oracleTextDown(bool &cond, int &ret) { // 122: oracle text down oracleTextDown(); } void SimonEngine::o3_oracleTextUp(bool &cond, int &ret) { // 123: oracle text up oracleTextUp(); } void SimonEngine::o3_ifTime(bool &cond, int &ret) { // 124: if time uint time = getVarOrWord(); cond = true; warning("STUB: script opcode 124 (%d)", time); } void SimonEngine::o3_setTime(bool &cond, int &ret) { // 131 warning("STUB: script opcode 131"); } void SimonEngine::o3_loadUserGame(bool &cond, int &ret) { // 133: load game loadGame(readVariable(55)); } void SimonEngine::o3_listSaveGames(bool &cond, int &ret) { // 134: dummy opcode? listSaveGames(1); } void SimonEngine::o3_checkCD(bool &cond, int &ret) { // 135: switch CD debug(1, "Switch to CD number %d", readVariable(97)); } void SimonEngine::o3_screenTextBox(bool &cond, int &ret) { // 161: setup text TextLocation *tl = getTextLocation(getVarOrByte()); tl->x = getVarOrWord(); tl->y = getVarOrWord(); tl->width = getVarOrWord(); } void SimonEngine::o3_hyperLinkOn(bool &cond, int &ret) { // 171: oracle hyperlink on hyperLinkOn(getVarOrWord()); } void SimonEngine::o3_hyperLinkOff(bool &cond, int &ret) { // 172: oracle hyperlink off hyperLinkOff(); } void SimonEngine::o3_checkPaths(bool &cond, int &ret) { // 173 warning("STUB: script opcode 173"); } void SimonEngine::o3_loadSmack(bool &cond, int &ret) { // 182: load video file debug(1,"Load video file: %s", getStringPtrByID(getNextStringID())); } void SimonEngine::o3_playSmack(bool &cond, int &ret) { // 183: play video debug(1, "Play video"); } void SimonEngine::o3_centreScroll(bool &cond, int &ret) { // 187 warning("STUB: script opcode 187"); } void SimonEngine::o3_resetPVCount(bool &cond, int &ret) { // 191 if (getBitFlag(83)) { _PVCount1 = 0; _GPVCount1 = 0; } else { _PVCount = 0; _GPVCount = 0; } } 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; } } void SimonEngine::o3_stopClock(bool &cond, int &ret) { // 193: pause clock warning("STUB: script opcode 193"); } void SimonEngine::o3_restartClock(bool &cond, int &ret) { // 194: resume clock warning("STUB: script opcode 194"); } 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); } 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; } condition = true; 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) { 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 (getBitFlag(9)) { endCutscene(); } } else { processSpecialKeys(); } } void SimonEngine::o_waitForMark(uint i) { _exitCutscene = false; while (!(_marks & (1 << i))) { if (_exitCutscene) { if (getBitFlag(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]; SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); if (subObject != NULL && subObject->objectFlags & kOFText) { string_ptr = (const char *)getStringPtrByID(subObject->objectFlagValue[0]); tl = getTextLocation(vgaSpriteId); } if ((getGameType() == GType_SIMON2) && (getFeatures() & GF_TALKIE)) { if (subObject != NULL && subObject->objectFlags & kOFVoice) { uint speechId = subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFVoice)]; if (subObject->objectFlags & kOFNumber) { uint speechIdOffs = subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFNumber)]; 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 (subObject != NULL && subObject->objectFlags & kOFVoice) { uint offs = getOffsetOfChild2Param(subObject, kOFVoice); playSpeech(subObject->objectFlagValue[offs], vgaSpriteId); } else if (subObject != NULL && subObject->objectFlags & kOFNumber) { uint offs = getOffsetOfChild2Param(subObject, kOFNumber); playSpeech(subObject->objectFlagValue[offs] + 3550, vgaSpriteId); } } if (subObject != NULL && (subObject->objectFlags & kOFText) && _subtitles) { if (subObject->objectFlags & kOFNumber) { sprintf(buf, "%d%s", subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFNumber)], 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 num) { WindowBlock *window; window = _windowArray[num & 7]; if (window->iconPtr == NULL) return; drawIconArray(num, window->iconPtr->itemRef, window->iconPtr->line, window->iconPtr->classMask); } 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; } 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_setTextColor(uint color) { WindowBlock *window; window = _windowArray[_curWindow]; window->text_color = color; } 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 num, uint x, uint y, uint w, uint h, uint flags, uint fill_color, uint text_color) { num &= 7; if (_windowArray[num]) closeWindow(num); _windowArray[num] = openWindow(x, y, w, h, flags, fill_color, text_color); if (num == _curWindow) { _textWindow = _windowArray[num]; if (getGameType() == GType_FF) showmessage_helper_3(_textWindow->textColumn, _textWindow->width); else showmessage_helper_3(_textWindow->textLength, _textWindow->textMaxLength); } } } // End of namespace Simon