aboutsummaryrefslogtreecommitdiff
path: root/script_v2.cpp
diff options
context:
space:
mode:
authorLudvig Strigeus2001-10-16 10:01:48 +0000
committerLudvig Strigeus2001-10-16 10:01:48 +0000
commit794163c1a334e9f99f7cdd70ab2c70fd7bd04737 (patch)
treeb40304976533e40b7f557018d95c844a15612c63 /script_v2.cpp
parent862192dbebd24f32e24f051b5a88f1bb6d801be8 (diff)
downloadscummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.tar.gz
scummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.tar.bz2
scummvm-rg350-794163c1a334e9f99f7cdd70ab2c70fd7bd04737.zip
preliminary DOTT support
svn-id: r3433
Diffstat (limited to 'script_v2.cpp')
-rw-r--r--script_v2.cpp2124
1 files changed, 2124 insertions, 0 deletions
diff --git a/script_v2.cpp b/script_v2.cpp
new file mode 100644
index 0000000000..d27bfd2507
--- /dev/null
+++ b/script_v2.cpp
@@ -0,0 +1,2124 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Change Log:
+ * $Log$
+ * Revision 1.1 2001/10/16 10:01:47 strigeus
+ * preliminary DOTT support
+ *
+ */
+
+
+#include "stdafx.h"
+#include "scumm.h"
+
+#if defined(DOTT)
+
+void Scumm::setupOpcodes2() {
+ static const OpcodeProc opcode_list[256] = {
+ /* 00 */
+ &Scumm::o2_pushByte,
+ &Scumm::o2_pushWord,
+ &Scumm::o2_pushByteVar,
+ &Scumm::o2_pushWordVar,
+ /* 04 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayRead,
+ &Scumm::o2_wordArrayRead,
+ /* 08 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayIndexedRead,
+ &Scumm::o2_wordArrayIndexedRead,
+ /* 0C */
+ &Scumm::o2_dup,
+ &Scumm::o2_zero,
+ &Scumm::o2_eq,
+ &Scumm::o2_neq,
+ /* 10 */
+ &Scumm::o2_gt,
+ &Scumm::o2_lt,
+ &Scumm::o2_le,
+ &Scumm::o2_ge,
+ /* 14 */
+ &Scumm::o2_add,
+ &Scumm::o2_sub,
+ &Scumm::o2_mul,
+ &Scumm::o2_div,
+ /* 18 */
+ &Scumm::o2_land,
+ &Scumm::o2_lor,
+ &Scumm::o2_kill,
+ &Scumm::o2_invalid,
+ /* 1C */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 20 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 24 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 28 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 2C */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 30 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 34 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 38 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 3C */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* 40 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_writeByteVar,
+ &Scumm::o2_writeWordVar,
+ /* 44 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayWrite,
+ &Scumm::o2_wordArrayWrite,
+ /* 48 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayIndexedWrite,
+ &Scumm::o2_wordArrayIndexedWrite,
+ /* 4C */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteVarInc,
+ &Scumm::o2_wordVarInc,
+ /* 50 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayInc,
+ &Scumm::o2_wordArrayInc,
+ /* 54 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteVarDec,
+ &Scumm::o2_wordVarDec,
+ /* 58 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_byteArrayDec,
+ &Scumm::o2_wordArrayDec,
+ /* 5C */
+ &Scumm::o2_jumpTrue,
+ &Scumm::o2_jumpFalse,
+ &Scumm::o2_startScriptEx,
+ &Scumm::o2_startScript,
+ /* 60 */
+ &Scumm::o2_startObject,
+ &Scumm::o2_setObjectState,
+ &Scumm::o2_setObjectXY,
+ &Scumm::o2_invalid,
+ /* 64 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_stopObjectCode,
+ &Scumm::o2_stopObjectCode,
+ &Scumm::o2_endCutscene,
+ /* 68 */
+ &Scumm::o2_cutScene,
+ &Scumm::o2_stopMusic,
+ &Scumm::o2_freezeUnfreeze,
+ &Scumm::o2_cursorCommand,
+ /* 6C */
+ &Scumm::o2_breakHere,
+ &Scumm::o2_ifClassOfIs,
+ &Scumm::o2_setClass,
+ &Scumm::o2_getState,
+ /* 70 */
+ &Scumm::o2_setState,
+ &Scumm::o2_setOwner,
+ &Scumm::o2_getOwner,
+ &Scumm::o2_jump,
+ /* 74 */
+ &Scumm::o2_startSound,
+ &Scumm::o2_stopSound,
+ &Scumm::o2_startMusic,
+ &Scumm::o2_stopObjectScript,
+ /* 78 */
+ &Scumm::o2_panCameraTo,
+ &Scumm::o2_actorFollowCamera,
+ &Scumm::o2_setCameraAt,
+ &Scumm::o2_loadRoom,
+ /* 7C */
+ &Scumm::o2_stopScript,
+ &Scumm::o2_walkActorToObj,
+ &Scumm::o2_walkActorTo,
+ &Scumm::o2_putActorInRoom,
+ /* 80 */
+ &Scumm::o2_putActorAtObject,
+ &Scumm::o2_faceActor,
+ &Scumm::o2_animateActor,
+ &Scumm::o2_doSentence,
+ /* 84 */
+ &Scumm::o2_pickupObject,
+ &Scumm::o2_loadRoomWithEgo,
+ &Scumm::o2_invalid,
+ &Scumm::o2_getRandomNumber,
+ /* 88 */
+ &Scumm::o2_getRandomNumberRange,
+ &Scumm::o2_invalid,
+ &Scumm::o2_getActorMoving,
+ &Scumm::o2_getScriptRunning,
+ /* 8C */
+ &Scumm::o2_getActorRoom,
+ &Scumm::o2_getObjectX,
+ &Scumm::o2_getObjectY,
+ &Scumm::o2_getObjectDir,
+ /* 90 */
+ &Scumm::o2_getActorWalkBox,
+ &Scumm::o2_getActorCostume,
+ &Scumm::o2_findInventory,
+ &Scumm::o2_getInventoryCount,
+ /* 94 */
+ &Scumm::o2_getVerbFromXY,
+ &Scumm::o2_beginOverride,
+ &Scumm::o2_endOverride,
+ &Scumm::o2_setObjectName,
+ /* 98 */
+ &Scumm::o2_isSoundRunning,
+ &Scumm::o2_setBoxFlags,
+ &Scumm::o2_createBoxMatrix,
+ &Scumm::o2_resourceRoutines,
+ /* 9C */
+ &Scumm::o2_roomOps,
+ &Scumm::o2_actorSet,
+ &Scumm::o2_verbOps,
+ &Scumm::o2_getActorFromXY,
+ /* A0 */
+ &Scumm::o2_findObject,
+ &Scumm::o2_pseudoRoom,
+ &Scumm::o2_getActorElevation,
+ &Scumm::o2_getVerbEntrypoint,
+ /* A4 */
+ &Scumm::o2_arrayOps,
+ &Scumm::o2_saveRestoreVerbs,
+ &Scumm::o2_drawBox,
+ &Scumm::o2_invalid,
+ /* A8 */
+ &Scumm::o2_getActorWidth,
+ &Scumm::o2_wait,
+ &Scumm::o2_getActorScaleX,
+ &Scumm::o2_getActorAnimCounter1,
+ /* AC */
+ &Scumm::o2_soundKludge,
+ &Scumm::o2_isAnyOf,
+ &Scumm::o2_quitPauseRestart,
+ &Scumm::o2_isActorInBox,
+ /* B0 */
+ &Scumm::o2_delay,
+ &Scumm::o2_delayLonger,
+ &Scumm::o2_delayVeryLong,
+ &Scumm::o2_stopSentence,
+ /* B4 */
+ &Scumm::o2_print_0,
+ &Scumm::o2_print_1,
+ &Scumm::o2_print_2,
+ &Scumm::o2_print_3,
+ /* B8 */
+ &Scumm::o2_printActor,
+ &Scumm::o2_printEgo,
+ &Scumm::o2_talkActor,
+ &Scumm::o2_talkEgo,
+ /* BC */
+ &Scumm::o2_dim,
+ &Scumm::o2_invalid,
+ &Scumm::o2_runVerbCodeQuick,
+ &Scumm::o2_runScriptQuick,
+ /* C0 */
+ &Scumm::o2_dim2,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* C4 */
+ &Scumm::o2_abs,
+ &Scumm::o2_distObjectObject,
+ &Scumm::o2_distObjectPt,
+ &Scumm::o2_distPtPt,
+ /* C8 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_miscOps,
+ &Scumm::o2_breakMaybe,
+ &Scumm::o2_pickOneOf,
+ /* CC */
+ &Scumm::o2_pickOneOfDefault,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* D0 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* D4 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* D8 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* DC */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* E0 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* E4 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* E8 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* EC */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* F0 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* F4 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* F8 */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ /* FC */
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ &Scumm::o2_invalid,
+ };
+
+ _opcodes = opcode_list;
+}
+
+int Scumm::readArray(int array, int index, int base) {
+ ArrayHeader *ah = (ArrayHeader*)getResourceAddress(7, readVar(array));
+
+ assert(ah);
+
+ base += index*ah->dim1_size;
+
+ assert(base>=0 && base < ah->dim1_size*ah->dim2_size);
+
+ if (ah->type==4) {
+ return ah->data[base];
+ } else {
+ return (int16)READ_LE_UINT16(ah->data + base*2);
+ }
+}
+
+void Scumm::writeArray(int array, int index, int base, int value) {
+ ArrayHeader *ah = (ArrayHeader*)getResourceAddress(7, readVar(array));
+ assert(ah);
+ base += index*ah->dim1_size;
+
+ assert(base>=0 && base < ah->dim1_size*ah->dim2_size);
+
+ if (ah->type==4) {
+ ah->data[base] = value;
+ } else {
+ ((uint16*)ah->data)[base] = TO_LE_16(value);
+ }
+}
+
+int Scumm::getStackList(int16 *args, uint maxnum) {
+ uint num, i;
+
+ for (i=0; i<maxnum; i++)
+ args[i] = 0;
+
+ num = pop();
+
+ if (num > maxnum)
+ error("Too many items %d in stack list, max %d", num, maxnum);
+
+ i = num;
+ while (((int)--i)>=0) {
+ args[i] = pop();
+ }
+
+ return num;
+}
+
+void Scumm::o2_pushByte() {
+ push(fetchScriptByte());
+}
+
+void Scumm::o2_pushWord() {
+ push((int16)fetchScriptWord());
+}
+
+void Scumm::o2_pushByteVar() {
+ push(readVar(fetchScriptByte()));
+}
+
+void Scumm::o2_pushWordVar() {
+ push(readVar(fetchScriptWord()));
+}
+
+void Scumm::o2_invalid() {
+ error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer);
+}
+
+void Scumm::o2_byteArrayRead() {
+ int base = pop();
+ push(readArray(fetchScriptByte(), 0, base));
+}
+
+void Scumm::o2_wordArrayRead() {
+ int base = pop();
+ push(readArray(fetchScriptWord(), 0, base));
+}
+
+void Scumm::o2_byteArrayIndexedRead() {
+ int base = pop();
+ int index = pop();
+ push(readArray(fetchScriptByte(), index, base));
+}
+
+void Scumm::o2_wordArrayIndexedRead() {
+ int base = pop();
+ int index = pop();
+ push(readArray(fetchScriptWord(), index, base));
+}
+
+void Scumm::o2_dup() {
+ int a = pop();
+ push(a);
+ push(a);
+}
+
+void Scumm::o2_zero() {
+ push( pop() == 0 );
+}
+
+void Scumm::o2_eq() {
+ push( pop() == pop() );
+}
+
+void Scumm::o2_neq() {
+ push( pop() != pop() );
+}
+
+void Scumm::o2_gt() {
+ int a = pop();
+ push( pop() > a );
+}
+
+void Scumm::o2_lt() {
+ int a = pop();
+ push( pop() < a );
+}
+
+void Scumm::o2_le() {
+ int a = pop();
+ push( pop() <= a );
+}
+
+void Scumm::o2_ge() {
+ int a = pop();
+ push( pop() >= a );
+}
+
+void Scumm::o2_add() {
+ int a = pop();
+ push( pop() + a );
+}
+
+void Scumm::o2_sub() {
+ int a = pop();
+ push( pop() - a );
+}
+
+void Scumm::o2_mul() {
+ int a = pop();
+ push( pop() * a );
+}
+
+void Scumm::o2_div() {
+ int a = pop();
+ if (a==0) error("division by zero");
+ push( pop() / a );
+}
+
+void Scumm::o2_land() {
+ int a = pop();
+ push( pop() && a );
+}
+
+void Scumm::o2_lor() {
+ int a = pop();
+ push( pop() || a );
+}
+
+void Scumm::o2_kill() {
+ pop();
+}
+
+void Scumm::o2_writeByteVar() {
+ writeVar(fetchScriptByte(), pop());
+}
+
+void Scumm::o2_writeWordVar() {
+ writeVar(fetchScriptWord(), pop());
+}
+
+void Scumm::o2_byteArrayWrite() {
+ int a = pop();
+ writeArray(fetchScriptByte(), 0, pop(), a);
+}
+
+void Scumm::o2_wordArrayWrite() {
+ int a = pop();
+ writeArray(fetchScriptWord(), 0, pop(), a);
+}
+
+void Scumm::o2_byteArrayIndexedWrite() {
+ int val = pop();
+ int base = pop();
+ writeArray(fetchScriptByte(), pop(), base, val);
+}
+
+void Scumm::o2_wordArrayIndexedWrite() {
+ int val = pop();
+ int base = pop();
+ writeArray(fetchScriptWord(), pop(), base, val);
+}
+
+void Scumm::o2_byteVarInc() {
+ int var = fetchScriptByte();
+ writeVar(var,readVar(var)+1);
+}
+
+void Scumm::o2_wordVarInc() {
+ int var = fetchScriptWord();
+ writeVar(var,readVar(var)+1);
+}
+
+void Scumm::o2_byteArrayInc() {
+ int var = fetchScriptByte();
+ int base = pop();
+ writeArray(var, 0, base, readArray(var, 0, base) + 1);
+}
+
+void Scumm::o2_wordArrayInc() {
+ int var = fetchScriptWord();
+ int base = pop();
+ writeArray(var, 0, base, readArray(var, 0, base) + 1);
+}
+
+
+void Scumm::o2_byteVarDec() {
+ int var = fetchScriptByte();
+ writeVar(var,readVar(var)-1);
+}
+
+void Scumm::o2_wordVarDec() {
+ int var = fetchScriptWord();
+ writeVar(var,readVar(var)-1);
+}
+
+void Scumm::o2_byteArrayDec() {
+ int var = fetchScriptByte();
+ int base = pop();
+ writeArray(var, 0, base, readArray(var, 0, base) - 1);
+}
+
+void Scumm::o2_wordArrayDec() {
+ int var = fetchScriptWord();
+ int base = pop();
+ writeArray(var, 0, base, readArray(var, 0, base) - 1);
+}
+
+void Scumm::o2_jumpTrue() {
+ if (pop())
+ o2_jump();
+ else
+ fetchScriptWord();
+}
+
+void Scumm::o2_jumpFalse() {
+ if (!pop())
+ o2_jump();
+ else
+ fetchScriptWord();
+}
+
+void Scumm::o2_jump() {
+ _scriptPointer += (int16)fetchScriptWord();
+}
+
+void Scumm::o2_startScriptEx() {
+ int16 args[16];
+ int script,flags;
+
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ script = pop();
+ flags = pop();
+ runScript(script, flags&1, flags&2, args);
+}
+
+void Scumm::o2_startScript() {
+ int16 args[16];
+ int script;
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ script = pop();
+ runScript(script, 0, 0, args);
+}
+
+void Scumm::o2_startObject() {
+ int16 args[16];
+ int script,entryp;
+ int flags;
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ entryp = pop();
+ script = pop();
+ flags = pop();
+ runVerbCode(script, entryp, flags&1, flags&2, args);
+}
+
+void Scumm::o2_setObjectState() {
+ int a = pop();
+ if (a==0) a=1;
+ setObjectState(pop(), a, -1, -1);
+}
+
+void Scumm::o2_setObjectXY() {
+ int y = pop();
+ int x = pop();
+ setObjectState(pop(), 1, x, y);
+}
+
+void Scumm::o2_stopObjectCode() {
+ stopObjectCode();
+}
+
+void Scumm::o2_endCutscene() {
+ endCutscene();
+}
+
+void Scumm::o2_cutScene() {
+ int16 args[16];
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ cutscene(args);
+}
+
+void Scumm::o2_stopMusic() {
+ warning("o2_stopMusic: not implemented");
+}
+
+void Scumm::o2_freezeUnfreeze() {
+ int a = pop();
+ if (a)
+ freezeScripts(a);
+ else
+ unfreezeScripts();
+}
+
+void Scumm::o2_cursorCommand() {
+ int a,num,i;
+ int16 args[16];
+
+ switch(fetchScriptByte()) {
+ case 0x90:
+ _cursorState = 1;
+ verbMouseOver(0);
+ break;
+ case 0x91:
+ _cursorState = 0;
+ verbMouseOver(0);
+ break;
+ case 0x92:
+ _userPut = 1;
+ break;
+ case 0x93:
+ _userPut = 0;
+ break;
+ case 0x94:
+ _cursorState++;
+ if (_cursorState > 1)
+ error("Cursor state greater than 1 in script");
+ verbMouseOver(0);
+ break;
+ case 0x95:
+ _cursorState--;
+ verbMouseOver(0);
+ break;
+ case 0x96:
+ _userPut++;
+ break;
+ case 0x97:
+ _userPut--;
+ break;
+ case 0x99:
+ a = pop();
+ setCursorImg(a, pop());
+ break;
+ case 0x9A:
+ a = pop();
+ setCursorHotspot2(pop(),a);
+ break;
+ case 0x9C: /* init charset */
+ initCharset(pop());
+ break;
+ case 0x9D: /* set charset colors */
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ for (i=0; i<16; i++)
+ charset._colorMap[i] = _charsetData[string[1].t_charset][i] = args[i];
+ break;
+ case 0xD6:
+ new_unk_1(pop());
+ break;
+ }
+
+ _vars[VAR_CURSORSTATE] = _cursorState;
+ _vars[VAR_USERPUT] = _userPut;
+}
+
+void Scumm::o2_breakHere() {
+ updateScriptPtr();
+ _currentScript = 0xFF;
+}
+
+void Scumm::o2_ifClassOfIs() {
+ int16 args[16];
+ int num,obj,cls;
+ bool b;
+ int cond = 1;
+
+ num = getStackList(args,sizeof(args)/sizeof(args[0]));
+ obj = pop();
+
+ while (--num>=0) {
+ cls = args[num];
+ b = getClass(obj, cls);
+ if (cls&0x80 && !b || !(cls&0x80) && b)
+ cond = 0;
+ }
+ push(cond);
+}
+
+void Scumm::o2_setClass() {
+ int16 args[16];
+ int num,obj,cls;
+
+ num = getStackList(args,sizeof(args)/sizeof(args[0]));
+ obj = pop();
+
+ while (--num>=0) {
+ cls = args[num];
+ if (cls==0)
+ _classData[num] = 0;
+ else if (cls&0x80)
+ putClass(obj, cls, 1);
+ else
+ putClass(obj, cls, 0);
+ }
+}
+
+void Scumm::o2_getState() {
+ push(getState(pop()));
+}
+
+void Scumm::o2_setState() {
+ int state = pop();
+ int obj = pop();
+
+ putState(obj, state);
+ removeObjectFromRoom(obj);
+ if (_BgNeedsRedraw)
+ clearDrawObjectQueue();
+}
+
+void Scumm::o2_setOwner() {
+ int owner = pop();
+ int obj = pop();
+
+ setOwnerOf(obj, owner);
+}
+
+void Scumm::o2_getOwner() {
+ push(getOwner(pop()));
+}
+
+void Scumm::o2_startSound() {
+ addSoundToQueue(pop());
+}
+
+void Scumm::o2_stopSound() {
+ unkSoundProc1(pop());
+}
+
+void Scumm::o2_startMusic() {
+ addSoundToQueue(pop());
+}
+
+void Scumm::o2_stopObjectScript() {
+ stopObjectScript(pop());
+}
+
+void Scumm::o2_panCameraTo() {
+ panCameraTo(pop());
+}
+
+void Scumm::o2_actorFollowCamera() {
+ actorFollowCamera(pop());
+}
+
+void Scumm::o2_setCameraAt() {
+ setCameraAtEx(pop());
+}
+
+void Scumm::o2_loadRoom() {
+ int room = pop();
+ debug(1,"Loading room %d", room);
+ startScene(room, 0, 0);
+ _fullRedraw = 1;
+}
+
+void Scumm::o2_stopScript() {
+ int script = pop();
+ if (script==0)
+ stopObjectCode();
+ else
+ stopScriptNr(script);
+}
+
+void Scumm::o2_walkActorToObj() {
+ int obj,dist;
+ Actor *a, *a2;
+ int x;
+
+ dist = pop();
+ obj = pop();
+ a = derefActorSafe(pop(), "o2_walkActorToObj");
+
+ if (obj >= 17) {
+ if (whereIsObject(obj)==-1)
+ return;
+ getObjectXYPos(obj);
+ startWalkActor(a, _xPos, _yPos, _dir);
+ } else {
+ a2 = derefActorSafe(obj, "o2_walkActorToObj(2)");
+ if (a2->room != _currentRoom ||
+ a->room != _currentRoom)
+ return;
+ if (dist==0) {
+ dist = a2->scalex * a2->width / 0xFF;
+ dist += dist>>1;
+ }
+ x = a2->x;
+ if (x < a->x)
+ x += dist;
+ else
+ x -= dist;
+ startWalkActor(a, x, a2->y, 0xFF);
+ }
+}
+
+void Scumm::o2_walkActorTo() {
+ int x,y;
+ y = pop();
+ x = pop();
+ startWalkActor(derefActorSafe(pop(), "o2_walkActorTo"), x, y, 0xFF);
+}
+
+void Scumm::o2_putActorInRoom() {
+ int room, x, y;
+ Actor *a;
+
+ room = pop();
+ y = pop();
+ x = pop();
+ a = derefActorSafe(pop(), "o2_putActorInRoom");
+ if (room==0xFF) {
+ room = a->room;
+ } else {
+ if (a->visible && _currentRoom != room && _vars[VAR_TALK_ACTOR]==a->number) {
+ clearMsgQueue();
+ }
+ if (room != 0)
+ a->room = room;
+ }
+ putActor(a, x, y, room);
+}
+
+void Scumm::o2_putActorAtObject() {
+ int room,obj,x,y;
+ Actor *a;
+
+ room = pop();
+ obj = pop();
+
+ a = derefActorSafe(pop(), "o2_putActorAtObject");
+ if (whereIsObject(obj)!=-1) {
+ getObjectXYPos(obj);
+ x = _xPos;
+ y = _yPos;
+ } else {
+ x = 160;
+ y = 120;
+ }
+ if (room == 0xFF)
+ room = a->room;
+ putActor(a, x, y, room);
+}
+
+void Scumm::o2_faceActor() {
+ int act,obj;
+ obj = pop();
+ act = pop();
+ faceActorToObj(act, obj);
+}
+
+void Scumm::o2_animateActor() {
+ int anim = pop();
+ int act = pop();
+ animateActor(act, anim);
+}
+
+void Scumm::o2_doSentence() {
+ int a,b,c;
+ SentenceTab *st;
+
+ a = pop();
+ pop(); //dummy pop
+ b = pop();
+ c = pop();
+
+ st = &sentence[++_sentenceIndex];
+
+ st->unk5 = c;
+ st->unk4 = b;
+ st->unk3 = a;
+
+ if (!(st->unk3&0xFF00))
+ st->unk2 = 0;
+ else
+ st->unk2 = 1;
+
+ st->unk = 0;
+}
+
+void Scumm::o2_pickupObject() {
+ int obj, room;
+
+ room = pop();
+ obj = pop();
+
+ if (room==0)
+ room = _roomResource;
+ addObjectToInventory(obj, room);
+ putOwner(obj, _vars[VAR_UNK_ACTOR]);
+ putClass(obj, 32, 1);
+ putState(obj, 1);
+ removeObjectFromRoom(obj);
+ clearDrawObjectQueue();
+ runHook(obj); /* Difference */
+}
+
+void Scumm::o2_loadRoomWithEgo() {
+ Actor *a;
+ int room,obj,x,y;
+
+ y = pop();
+ x = pop();
+ room = pop();
+ obj = pop();
+
+ a = derefActorSafe(_vars[VAR_UNK_ACTOR], "o_loadRoomWithEgo");
+
+ putActor(a, 0, 0, room);
+ dseg_3A76 = 0;
+ _vars[VAR_WALKTO_OBJ] = obj;
+ startScene(a->room, a, obj);
+ _vars[VAR_WALKTO_OBJ] = 0;
+
+ /* startScene maybe modifies VAR_UNK_ACTOR, i hope not */
+ camera._destPos = camera._curPos = a->x;
+ setCameraFollows(a);
+ _fullRedraw=1;
+ if (x != -1) {
+ startWalkActor(a, x, y, 0xFF);
+ }
+}
+
+void Scumm::o2_getRandomNumber() {
+ int rnd;
+ rnd = getRandomNumber(pop()+1);
+ _vars[VAR_RANDOM_NR] = rnd;
+ push(rnd);
+}
+
+void Scumm::o2_getRandomNumberRange() {
+ int max = pop();
+ int min = pop();
+ int rnd = getRandomNumber(max-min+1) + min;
+ _vars[VAR_RANDOM_NR] = rnd;
+ push(rnd);
+}
+
+void Scumm::o2_getActorMoving() {
+ push(derefActorSafe(pop(),"o2_getActorMoving")->moving);
+}
+
+void Scumm::o2_getScriptRunning() {
+ push(getScriptRunning(pop()));
+}
+
+void Scumm::o2_getActorRoom() {
+ push(derefActorSafe(pop(),"o2_getActorRoom")->room);
+}
+
+void Scumm::o2_getObjectX() {
+ push(getObjX(pop()));
+}
+
+void Scumm::o2_getObjectY() {
+ push(getObjY(pop()));
+}
+
+void Scumm::o2_getObjectDir() {
+ push(getObjDir(pop()));
+}
+
+void Scumm::o2_getActorWalkBox() {
+ push(derefActorSafe(pop(),"o2_getActorWalkBox")->walkbox);
+}
+
+void Scumm::o2_getActorCostume() {
+ push(derefActorSafe(pop(),"o2_getActorCostume")->costume);
+}
+
+void Scumm::o2_findInventory() {
+ int index = pop();
+ int owner = pop();
+ push(findInventory(owner,index));
+}
+
+void Scumm::o2_getInventoryCount() {
+ push(getInventoryCount(pop()));
+}
+
+void Scumm::o2_getVerbFromXY() {
+ int y = pop();
+ int x = pop();
+ int over = checkMouseOver(x,y);
+ if (over)
+ over = _verbs[over].verbid;
+ push(over);
+}
+
+void Scumm::o2_beginOverride() {
+ beginOverride();
+}
+
+void Scumm::o2_endOverride() {
+ endOverride();
+}
+
+void Scumm::o2_setObjectName() {
+ int obj = pop();
+ int i;
+
+ if (obj <= _vars[VAR_NUM_ACTOR])
+ error("Can't set actor %d name with new-name-of", obj);
+
+ if (!getObjectAddress(obj))
+ error("Can't set name of object %d", obj);
+
+ for (i=1; i<50; i++) {
+ if (_newNames[i] == obj) {
+ nukeResource(16, i);
+ _newNames[i] = 0;
+ break;
+ }
+ }
+
+ for (i=1; i<50; i++) {
+ if (_newNames[i] == 0) {
+ loadPtrToResource(16, i, NULL);
+ _newNames[i] = obj;
+ runHook(0);
+ return;
+ }
+ }
+
+ error("New name of %d overflows name table (max = %d)", obj, 50);
+}
+
+void Scumm::o2_isSoundRunning() {
+ int snd = pop();
+ if (snd)
+ snd = unkSoundProc23(snd);
+ push(snd);
+}
+
+void Scumm::o2_setBoxFlags() {
+ int16 table[65];
+ int num,value;
+
+ value = pop();
+ num = getStackList(table,sizeof(table)/sizeof(table[0]));
+
+ while (--num>=0) {
+ setBoxFlags(table[num], value);
+ }
+}
+
+void Scumm::o2_createBoxMatrix() {
+ createBoxMatrix();
+}
+
+void Scumm::o2_resourceRoutines() {
+ int res;
+
+ switch(fetchScriptByte()) {
+ case 100: /* load script */
+ res = pop();
+ ensureResourceLoaded(2, res);
+ break;
+ case 101: /* load sound */
+ res = pop();
+ ensureResourceLoaded(4, res);
+ break;
+ case 102: /* load costume */
+ res = pop();
+ ensureResourceLoaded(3, res);
+ break;
+ case 103: /* load room */
+ res = pop();
+ ensureResourceLoaded(1, res);
+ break;
+ case 104: /* nuke script */
+ res = pop();
+ setResourceFlags(2, res, 0x7F);
+ break;
+ case 105: /* nuke sound */
+ res = pop();
+ setResourceFlags(4, res, 0x7F);
+ break;
+ case 106: /* nuke costume */
+ res = pop();
+ setResourceFlags(3, res, 0x7F);
+ break;
+ case 107: /* nuke room */
+ res = pop();
+ setResourceFlags(1, res, 0x7F);
+ break;
+ case 108: /* lock script */
+ res = pop();
+ if (res >= _numGlobalScripts)
+ break;
+ lock(2,res);
+ break;
+ case 109:/* lock sound */
+ res = pop();
+ lock(4,res);
+ break;
+ case 110:/* lock costume */
+ res = pop();
+ lock(3,res);
+ break;
+ case 111:/* lock room */
+ res = pop();
+ if (res > 0x7F)
+ res = _resourceMapper[res&0x7F];
+ lock(1,res);
+ break;
+ case 112:/* unlock script */
+ res = pop();
+ if (res >= _numGlobalScripts)
+ break;
+ unlock(2,res);
+ break;
+ case 113:/* unlock sound */
+ res = pop();
+ unlock(4,res);
+ break;
+ case 114:/* unlock costume */
+ res = pop();
+ unlock(3,res);
+ break;
+ case 115:/* unlock room */
+ res = pop();
+ if (res > 0x7F)
+ res = _resourceMapper[res&0x7F];
+ unlock(1,res);
+ break;
+ case 116:/* clear heap */
+ /* this is actually a scumm message */
+ error("clear heap not working yet");
+ break;
+ case 117:/* load charset */
+ res = pop();
+ loadCharset(res);
+ break;
+ case 118:/* nuke charset */
+ warning("popping extra argument in nukeCharset");
+ res = pop();
+ nukeCharset(res);
+ break;
+ case 119:/* ? */
+ res = pop();
+ unkResProc(pop(), res);
+ break;
+ default:
+ error("o2_resourceRoutines: default case");
+ }
+}
+
+void Scumm::o2_roomOps() {
+ int a,b,c,d,e;
+
+ switch(fetchScriptByte()) {
+ case 172: /* room scroll */
+ b = pop();
+ a = pop();
+ if (a < 160) a=160;
+ if (a > ((_scrWidthIn8Unit-20)<<3)) a=((_scrWidthIn8Unit-20)<<3);
+ if (b < 160) b=160;
+ if (b > ((_scrWidthIn8Unit-20)<<3)) b=((_scrWidthIn8Unit-20)<<3);
+ _vars[VAR_CAMERA_MIN] = a;
+ _vars[VAR_CAMERA_MAX] = b;
+ break;
+
+ case 174: /* set screen */
+ b = pop();
+ a = pop();
+ initScreens(0,a,320,b);
+ break;
+
+ case 175: /* set palette color */
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ setPalColor(d, a, b, c);
+ break;
+
+ case 176: /* shake on */
+ setShake(1);
+ break;
+
+ case 177: /* shake off */
+ setShake(0);
+ break;
+
+ case 179:
+ c = pop();
+ b = pop();
+ a = pop();
+ unkRoomFunc2(b,c,a,a,a);
+ break;
+
+ case 180:
+ _saveLoadData = pop();
+ _saveLoadFlag = pop();
+ warning("o2_roomops:180: partially unimplemented");
+ break;
+
+ case 181:
+ a = pop();
+ if (a) {
+ _switchRoomEffect = (byte)(a);
+ _switchRoomEffect2 = (byte)(a>>8);
+ } else {
+ screenEffect(_newEffect);
+ }
+ break;
+
+ case 182:
+ e = pop();
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ unkRoomFunc2(d, e, a, b, c);
+ break;
+
+ case 183:
+ e = pop();
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ unkRoomFunc3(d, e, a, b, c);
+ break;
+
+ case 184:
+ error("save string not implemented");
+ break;
+
+ case 185:
+ error("load string not implemented");
+ break;
+
+ case 186: /* palmanip? */
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ unkRoomFunc4(a, b, c, d, 1);
+ break;
+
+ case 187: /* color cycle delay */
+ b = pop();
+ a = pop();
+ if (b!=0)
+ _colorCycleDelays[a] = 0x4000 / (b*0x4C);
+ else
+ _colorCycleDelays[a] = 0;
+ break;
+
+ case 213: /* set palette */
+ setPalette(pop());
+ break;
+
+ default:
+ error("o2_roomOps: default case");
+ }
+}
+
+void Scumm::o2_actorSet() {
+ Actor *a;
+ int i,j,k;
+ int16 args[8];
+ byte b;
+
+ b = fetchScriptByte();
+ if (b==197) {
+ _curActor = pop();
+ return;
+ }
+
+ a = derefActorSafe(_curActor, "o2_actorSet");
+
+ switch(b) {
+ case 76: /* actor-costume */
+ setActorCostume(a, pop());
+ break;
+ case 77: /* actor-speed */
+ j = pop();
+ i = pop();
+ setActorWalkSpeed(a, i, j);
+ break;
+ case 78: /* actor-sound */
+ k = getStackList(args, sizeof(args)/sizeof(args[0]));
+ for (i=0; i<k; i++)
+ a->sound[i] = args[i];
+ break;
+ case 79: /* actor-walkframe */
+ a->walkFrame = pop();
+ break;
+ case 80: /* actor-talkframe */
+ a->talkFrame2 = pop();
+ a->talkFrame1 = pop();
+ break;
+ case 81: /* actor-standframe */
+ a->standFrame = pop();
+ break;
+ case 82:
+ pop();
+ pop();
+ pop();
+ break;
+ case 83:
+ initActor(a, 0);
+ break;
+ case 84: /* actor-elevation */
+ a->elevation = pop();
+ a->needRedraw = true;
+ a->needBgReset = true;
+ break;
+ case 85: /* actor-defaultanims */
+ a->initFrame = 1;
+ a->walkFrame = 2;
+ a->standFrame = 3;
+ a->talkFrame1 = 4;
+ a->talkFrame2 = 5;
+ break;
+ case 86: /* actor-palette */
+ j = pop();
+ i = pop();
+ checkRange(31, 0, i, "Illegal palet slot %d");
+ a->palette[i] = j;
+ a->needRedraw = true;
+ break;
+ case 87: /* actor-talkcolor */
+ a->talkColor = pop();
+ break;
+ case 88: /* actor-name */
+ loadPtrToResource(9, a->number, NULL);
+ break;
+ case 89: /* actor-initframe */
+ a->initFrame = pop();
+ break;
+ case 91:
+ a->width = pop();
+ break;
+ case 92:
+ a->scalex = a->scaley = pop();
+ a->needRedraw = true;
+ a->needBgReset = true;
+ break;
+ case 93:
+ a->neverZClip = 0;
+ break;
+ case 94:
+ a->neverZClip = pop();
+ break;
+ case 95:
+ a->ignoreBoxes = 1;
+ a->neverZClip = 0;
+FixRooms:;
+ if (a->room==_currentRoom)
+ putActor(a, a->x, a->y, a->room);
+ break;
+ case 96:
+ a->ignoreBoxes = 0;
+ a->neverZClip = 0;
+ goto FixRooms;
+ case 97:
+ a->animSpeed = pop();
+ a->animProgress = 0;
+ break;
+ case 98:
+ a->data8 = pop();
+ break;
+ case 99:
+ a->new_1 = pop();
+ a->new_2 = pop();
+ break;
+ case 215:
+ a->new_3 = 1;
+ break;
+ case 216:
+ a->new_3 = 0;
+ break;
+ case 217:
+ initActor(a, 2);
+ break;
+ default:
+ error("o2_actorset: default case");
+ }
+}
+
+void Scumm::o2_verbOps() {
+ int slot,a,b;
+ VerbSlot *vs;
+ byte *ptr, op;
+
+ op = fetchScriptByte();
+ if(op==196) {
+ _curVerb = pop();
+ _curVerbSlot = getVerbSlot(_curVerb, 0);
+ checkRange(_maxVerbs-1,0,_curVerbSlot,"Illegal new verb slot %d");
+ return;
+ }
+ vs = &_verbs[_curVerbSlot];
+ slot = _curVerbSlot;
+ switch(op) {
+ case 124: /* load img */
+ a = pop();
+ if (_curVerbSlot) {
+ setVerbObject(_roomResource,a,slot);
+ vs->type=1;
+ }
+ break;
+ case 125:
+ loadPtrToResource(8, slot, NULL);
+ vs->type = 0;
+ vs->imgindex = 0;
+ break;
+ case 126:
+ vs->color = pop();
+ break;
+ case 127:
+ vs->hicolor = pop();
+ break;
+ case 128:
+ vs->y = pop();
+ vs->x = pop();
+ break;
+ case 129:
+ vs->curmode = 1;
+ break;
+ case 130:
+ vs->curmode = 0;
+ break;
+ case 131:
+ killVerb(slot);
+ break;
+ case 132:
+ slot = getVerbSlot(_curVerb, 0);
+ if (slot==0) {
+ for (slot=1; slot<_maxVerbs; slot++) {
+ if(_verbs[slot].verbid==0)
+ break;
+ }
+ if (slot==_maxVerbs)
+ error("Too many verbs");
+ _curVerbSlot = slot;
+ }
+ vs = &_verbs[slot];
+ vs->verbid = _curVerb;
+ vs->color = 2;
+ vs->hicolor = 0;
+ vs->dimcolor = 8;
+ vs->type = 0;
+ vs->charset_nr = string[0].t_charset;
+ vs->curmode = 0;
+ vs->saveid = 0;
+ vs->key = 0;
+ vs->center = 0;
+ vs->imgindex = 0;
+ break;
+ case 133:
+ vs->dimcolor = pop();
+ break;
+ case 134:
+ vs->curmode = 2;
+ break;
+ case 135:
+ vs->key = pop();
+ break;
+ case 136:
+ vs->center = 1;
+ break;
+ case 137:
+ a = pop();
+ if (a==0) {
+ ptr = (byte*)"";
+ } else {
+ ptr = getResourceAddress(7, a);
+ }
+ loadPtrToResource(8, slot, ptr);
+ vs->type = 0;
+ vs->imgindex = 0;
+ break;
+ case 139:
+ b = pop();
+ a = pop();
+ if (slot && a != vs->imgindex) {
+ setVerbObject(b, a, slot);
+ vs->type = 1;
+ vs->imgindex = a;
+ }
+ break;
+ case 140:
+ vs->bkcolor = pop();
+ break;
+ case 255:
+ drawVerb(slot, 0);
+ verbMouseOver(0);
+ break;
+ default:
+ error("o2_verbops: default case");
+ }
+}
+
+void Scumm::o2_getActorFromXY() {
+ int y = pop();
+ int x = pop();
+ push(getActorFromPos(x,y));
+}
+
+void Scumm::o2_findObject() {
+ int y = pop();
+ int x = pop();
+ int r = findObject(x,y);
+ push(r);
+}
+
+void Scumm::o2_pseudoRoom() {
+ int16 list[100];
+ int num,a,value;
+
+ num = getStackList(list,sizeof(list)/sizeof(list[0]));
+ value = pop();
+
+ while (--num>=0) {
+ a = list[num];
+ if (a > 0x7F)
+ _resourceMapper[a&0x7F] = value;
+ }
+}
+
+void Scumm::o2_getActorElevation() {
+ push(derefActorSafe(pop(),"o2_getActorElevation")->elevation);
+}
+
+void Scumm::o2_getVerbEntrypoint() {
+ int e = pop();
+ int v = pop();
+ push(getVerbEntrypoint(v,e));
+}
+
+void Scumm::o2_arrayOps() {
+ int a,b,c,d,num;
+ int16 list[128];
+
+ switch(fetchScriptByte()) {
+ case 205:
+ a = fetchScriptWord();
+ pop();
+ arrayop_1(a, NULL);
+ break;
+ case 208:
+ a = fetchScriptWord();
+ b = pop();
+ c = pop();
+ d = readVar(a);
+ if (d==0) {
+ defineArray(a, 5, 0, b+c);
+ }
+ while (c--) {
+ writeArray(a, 0, b+c, pop());
+ }
+ break;
+ case 212:
+ a = fetchScriptWord();
+ b = pop();
+ num = getStackList(list,sizeof(list)/sizeof(list[0]));
+ d = readVar(a);
+ if (d==0)
+ error("Must DIM a two dimensional array before assigning");
+ c = pop();
+ while (--num>=0) {
+ writeArray(a, c, b+num, list[num]);
+ }
+ break;
+ default:
+ error("o2_arrayOps: default case");
+ }
+}
+
+void Scumm::o2_saveRestoreVerbs() {
+ int a,b,c;
+ int slot,slot2;
+
+ c = pop();
+ b = pop();
+ a = pop();
+
+ switch(fetchScriptByte()) {
+ case 141:
+ while (a<=b) {
+ slot = getVerbSlot(a,0);
+ if (slot && _verbs[slot].saveid==0) {
+ _verbs[slot].saveid = c;
+ drawVerb(slot, 0);
+ verbMouseOver(0);
+ }
+ a++;
+ }
+ break;
+ case 142:
+ while (a<=b) {
+ slot = getVerbSlot(a, c);
+ if (slot) {
+ slot2 = getVerbSlot(a,0);
+ if (slot2)
+ killVerb(slot2);
+ slot = getVerbSlot(a,c);
+ _verbs[slot].saveid = 0;
+ drawVerb(slot, 0);
+ verbMouseOver(0);
+ }
+ a++;
+ }
+ break;
+ case 143:
+ while (a<=b) {
+ slot = getVerbSlot(a,c);
+ if (slot)
+ killVerb(slot);
+ a++;
+ }
+ break;
+ default:
+ error("o2_saveRestoreVerbs: default case");
+ }
+}
+
+void Scumm::o2_drawBox() {
+ int x,y,x2,y2,color;
+ color = pop();
+ y2 = pop();
+ x2 = pop();
+ y = pop();
+ x = pop();
+ drawBox(x, y, x2, y2, color);
+}
+
+void Scumm::o2_getActorWidth() {
+ push(derefActorSafe(pop(),"o2_getActorWidth")->width);
+}
+
+void Scumm::o2_wait() {
+ byte oldaddr;
+
+ switch(fetchScriptByte()) {
+ case 168:
+ if (derefActorSafe(pop(), "o2_wait")->moving) {
+ _scriptPointer += (int16)fetchScriptWord();
+ o2_breakHere();
+ } else {
+ fetchScriptWord();
+ }
+ return;
+ case 169:
+ if (_vars[VAR_HAVE_MSG])
+ break;
+ return;
+ case 170:
+ if (camera._curPos>>3 != camera._destPos>>3)
+ break;
+ return;
+ case 171:
+ if (_sentenceIndex!=0xFF) {
+ if (sentence[_sentenceIndex].unk &&
+ !isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT]) )
+ return;
+ break;
+ }
+ if (!isScriptLoaded(_vars[VAR_SENTENCE_SCRIPT]))
+ return;
+ break;
+ default:
+ error("o2_wait: default case");
+ }
+
+ _scriptPointer -= 2;
+ o2_breakHere();
+}
+
+void Scumm::o2_getActorScaleX() {
+ push(derefActorSafe(pop(),"o2_getActorScale")->scalex);
+}
+
+void Scumm::o2_getActorAnimCounter1() {
+ push(derefActorSafe(pop(),"o2_getActorAnimCounter")->cost.animCounter1);
+}
+
+void Scumm::o2_soundKludge() {
+ int16 list[8];
+ getStackList(list,sizeof(list)/sizeof(list[0]));
+ soundKludge(list);
+}
+
+void Scumm::o2_isAnyOf() {
+ int16 list[100];
+ int num;
+ int16 val;
+
+ num = getStackList(list,sizeof(list)/sizeof(list[0]));
+ val = pop();
+
+ while (--num>=0) {
+ if (list[num] == val) {
+ push(1);
+ return;
+ }
+ }
+ push(0);
+ return;
+}
+
+void Scumm::o2_quitPauseRestart() {
+ switch(fetchScriptByte()) {
+ case 158:
+ pauseGame(0);
+ break;
+ case 160:
+ shutDown(0);
+ break;
+ default:
+ error("o2_quitPauseRestart: invalid case");
+ }
+}
+
+void Scumm::o2_isActorInBox() {
+ int box = pop();
+ Actor *a = derefActorSafe(pop(), "o2_isActorInBox");
+ push(checkXYInBoxBounds(box, a->x, a->y));
+}
+
+void Scumm::o2_delay() {
+ uint32 delay = (uint16)pop();
+ vm.slot[_currentScript].delay = delay;
+ vm.slot[_currentScript].status = 1;
+ o2_breakHere();
+}
+
+void Scumm::o2_delayLonger() {
+ uint32 delay = (uint16)pop() * 60;
+ vm.slot[_currentScript].delay = delay;
+ vm.slot[_currentScript].status = 1;
+ o2_breakHere();
+}
+
+void Scumm::o2_delayVeryLong() {
+ uint32 delay = (uint16)pop() * 3600;
+ vm.slot[_currentScript].delay = delay;
+ vm.slot[_currentScript].status = 1;
+ o2_breakHere();
+}
+
+void Scumm::o2_stopSentence() {
+ _sentenceIndex = 0xFF;
+ stopScriptNr(_vars[VAR_SENTENCE_SCRIPT]);
+ clearClickedStatus();
+}
+
+void Scumm::o2_print_0() {
+ _actorToPrintStrFor = 0xFF;
+ decodeParseString2(0,0);
+}
+
+void Scumm::o2_print_1() {
+ decodeParseString2(1,0);
+}
+
+void Scumm::o2_print_2() {
+ decodeParseString2(2,0);
+}
+
+void Scumm::o2_print_3() {
+ decodeParseString2(3,0);
+}
+
+void Scumm::o2_printActor() {
+ decodeParseString2(0,1);
+}
+
+void Scumm::o2_printEgo() {
+ push(_vars[VAR_UNK_ACTOR]);
+ decodeParseString2(0,1);
+}
+
+void Scumm::o2_talkActor() {
+ _actorToPrintStrFor = pop();
+ _messagePtr = _scriptPointer;
+ setStringVars(0);
+ actorTalk();
+ _scriptPointer = _messagePtr;
+}
+
+void Scumm::o2_talkEgo() {
+ _actorToPrintStrFor = _vars[VAR_UNK_ACTOR];
+ _messagePtr = _scriptPointer;
+ setStringVars(0);
+ actorTalk();
+ _scriptPointer = _messagePtr;
+}
+
+void Scumm::o2_dim() {
+ byte b;
+ int data;
+
+ switch(fetchScriptByte()) {
+ case 199:
+ data = 5;
+ break;
+ case 200:
+ data = 1;
+ break;
+ case 201:
+ data = 2;
+ break;
+ case 202:
+ data = 3;
+ break;
+ case 203:
+ data = 4;
+ break;
+ case 204:
+ nukeArray(fetchScriptWord());
+ return;
+ default:
+ error("o2_dim: default case");
+ }
+
+ defineArray(fetchScriptWord(), data, 0, pop());
+}
+
+void Scumm::o2_runVerbCodeQuick() {
+ int16 args[16];
+ int script,entryp;
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ entryp = pop();
+ script = pop();
+ runVerbCode(script, entryp, 0, 1, args);
+}
+
+void Scumm::o2_runScriptQuick() {
+ int16 args[16];
+ int script;
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ script = pop();
+ runScript(script, 0, 1, args);
+}
+
+void Scumm::o2_dim2() {
+ int a,b,data;
+ switch(fetchScriptByte()) {
+ case 199:
+ data = 5;
+ break;
+ case 200:
+ data = 1;
+ break;
+ case 201:
+ data = 2;
+ break;
+ case 202:
+ data = 3;
+ break;
+ case 203:
+ data = 4;
+ break;
+ default:
+ error("o2_dim2: default case");
+ }
+
+ b = pop();
+ a = pop();
+ defineArray(fetchScriptWord(), data, a, b);
+}
+
+void Scumm::o2_abs() {
+ push(abs(pop()));
+}
+
+
+void Scumm::o2_distObjectObject() {
+ int a,b;
+ b = pop();
+ a = pop();
+ push(getDistanceBetween(true, a, 0, true, b, 0));
+}
+
+void Scumm::o2_distObjectPt() {
+ int a,b,c;
+ c = pop();
+ b = pop();
+ a = pop();
+ push(getDistanceBetween(true, a, 0, false, b, c));
+}
+
+void Scumm::o2_distPtPt() {
+ int a,b,c,d;
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ push(getDistanceBetween(false, a, b, false, c, d));
+}
+
+void Scumm::o2_dummy_stacklist() {
+ error("opcode o2_dummy_stacklist invalid");
+}
+
+void Scumm::o2_miscOps() {
+ int16 args[30];
+ int i;
+
+ getStackList(args,sizeof(args)/sizeof(args[0]));
+ switch(args[0]) {
+ case 3:
+ warning("o2_miscOps: nothing in 3");
+ break;
+ case 4:
+ unkMiscOp4(args[1], args[2], args[3], args[4]);
+ break;
+ case 5:
+ unkVirtScreen4(args[1]);
+ break;
+ case 6:
+ _fullRedraw = 1;
+ redrawBGAreas();
+ for (i=0; i<13; i++)
+ derefActor(i)->needRedraw = true;
+ processActors();
+ screenEffect(args[1]);
+ break;
+ case 8:
+ startManiac();
+ break;
+ case 9:
+ unkMiscOp9();
+ break;
+ }
+}
+
+void Scumm::o2_breakMaybe() {
+ ScriptSlot *ss = &vm.slot[_currentScript];
+ if (ss->newfield == 0) {
+ ss->newfield = pop();
+ } else {
+ ss->newfield--;
+ }
+ if (ss->newfield) {
+ _scriptPointer--;
+ o2_breakHere();
+ }
+}
+
+void Scumm::o2_pickOneOf() {
+ int16 args[100];
+ int i,num;
+
+ num = getStackList(args,sizeof(args)/sizeof(args[0]));
+ i = pop();
+ if (i<0 || i>=num)
+ error("o2_pickOneOf: out of range");
+ push(args[i]);
+}
+
+void Scumm::o2_pickOneOfDefault() {
+ int16 args[100];
+ int i,num,def;
+
+ def = pop();
+ num = getStackList(args,sizeof(args)/sizeof(args[0]));
+ i = pop();
+ if (i<0 || i>=num)
+ i = def;
+ else
+ i = args[i];
+ push(i);
+}
+
+void Scumm::decodeParseString2(int m, int n) {
+ byte b;
+
+ b = fetchScriptByte();
+
+ switch(b) {
+ case 65:
+ string[m].ypos = pop();
+ string[m].xpos = pop();
+ string[m].overhead = 0;
+ break;
+ case 66:
+ string[m].color = pop();
+ break;
+ case 67:
+ string[m].right = pop();
+ break;
+ case 69:
+ string[m].center = 1;
+ string[m].overhead = 0;
+ break;
+ case 71:
+ string[m].center = 0;
+ string[m].overhead = 0;
+ break;
+ case 72:
+ string[m].overhead = 1;
+ string[m].new_3 = 0;
+ break;
+ case 73:
+ error("decodeParseString2: case 73");
+ break;
+ case 74:
+ string[m].new_3 = 1;
+ break;
+ case 75:
+ _messagePtr = _scriptPointer;
+ switch(m) {
+ case 0: actorTalk(); break;
+ case 1: drawString(1); break;
+ case 2: unkMessage1(); break;
+ case 3: unkMessage2(); break;
+ }
+ _scriptPointer = _messagePtr;
+ return;
+
+ case 0xFE:
+ setStringVars(m);
+ if (n)
+ _actorToPrintStrFor = pop();
+ return;
+ case 0xFF:
+ string[m].t_xpos = string[m].xpos;
+ string[m].t_ypos = string[m].ypos;
+ string[m].t_center = string[m].center;
+ string[m].t_overhead = string[m].overhead;
+ string[m].t_new3 = string[m].new_3;
+ string[m].t_right = string[m].right;
+ string[m].t_color = string[m].color;
+ string[m].t_charset = string[m].charset;
+ return;
+ default:
+ error("decodeParseString: default case");
+ }
+}
+
+#endif \ No newline at end of file