aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
Diffstat (limited to 'scumm')
-rw-r--r--scumm/intern.h430
-rw-r--r--scumm/module.mk1
-rw-r--r--scumm/resource.cpp73
-rw-r--r--scumm/resource_v2.cpp5
-rw-r--r--scumm/resource_v3.cpp9
-rw-r--r--scumm/resource_v4.cpp5
-rw-r--r--scumm/saveload.cpp3
-rw-r--r--scumm/script_v5.cpp3
-rw-r--r--scumm/script_v6.cpp5
-rw-r--r--scumm/script_v8.cpp1040
-rw-r--r--scumm/scumm.h352
-rw-r--r--scumm/scummvm.cpp3
-rw-r--r--scumm/vars.cpp1
13 files changed, 1550 insertions, 380 deletions
diff --git a/scumm/intern.h b/scumm/intern.h
new file mode 100644
index 0000000000..f59d7ac8bf
--- /dev/null
+++ b/scumm/intern.h
@@ -0,0 +1,430 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef INTERN_H
+#define INTERN_H
+
+#include "scumm.h"
+
+
+class Scumm_v5 : public Scumm
+{
+protected:
+ typedef void (Scumm_v5::*OpcodeProcV5)();
+ struct OpcodeEntryV5 {
+ OpcodeProcV5 proc;
+ const char *desc;
+ };
+
+ const OpcodeEntryV5 *_opcodesV5;
+
+public:
+ Scumm_v5(GameDetector *detector, OSystem *syst) : Scumm(detector, syst) {}
+
+protected:
+ virtual void setupOpcodes();
+ virtual void executeOpcode(int i);
+ virtual const char *getOpcodeDesc(int i);
+
+ void decodeParseString();
+ int getWordVararg(int16 *ptr);
+ int getVarOrDirectWord(byte mask);
+ int getVarOrDirectByte(byte mask);
+
+ /* Version 5 script opcodes */
+ void o5_actorFollowCamera();
+ void o5_actorFromPos();
+ void o5_actorSet();
+ void o5_add();
+ void o5_and();
+ void o5_animateActor();
+ void o5_badOpcode();
+ void o5_breakHere();
+ void o5_chainScript();
+ void o5_cursorCommand();
+ void o5_cutscene();
+ void o5_debug();
+ void o5_decrement();
+ void o5_delay();
+ void o5_delayVariable();
+ void o5_divide();
+ void o5_doSentence();
+ void o5_drawBox();
+ void o5_drawObject();
+ void o5_dummy();
+ void o5_endCutscene();
+ void o5_equalZero();
+ void o5_expression();
+ void o5_faceActor();
+ void o5_findInventory();
+ void o5_findObject();
+ void o5_freezeScripts();
+ void o5_getActorCostume();
+ void o5_getActorElevation();
+ void o5_getActorFacing();
+ void o5_getActorMoving();
+ void o5_getActorRoom();
+ void o5_getActorScale();
+ void o5_getActorWalkBox();
+ void o5_getActorWidth();
+ void o5_getActorX();
+ void o5_getActorY();
+ void o5_getAnimCounter();
+ void o5_getClosestObjActor();
+ void o5_getDist();
+ void o5_getInventoryCount();
+ void o5_getObjectOwner();
+ void o5_getObjectState();
+ void o5_getRandomNr();
+ void o5_isScriptRunning();
+ void o5_getVerbEntrypoint();
+ void o5_ifClassOfIs();
+ void o5_increment();
+ void o5_isActorInBox();
+ void o5_isEqual();
+ void o5_isGreater();
+ void o5_isGreaterEqual();
+ void o5_isLess();
+ void o5_isNotEqual();
+ void o5_ifState();
+ void o5_ifNotState();
+ void o5_isSoundRunning();
+ void o5_jumpRelative();
+ void o5_lessOrEqual();
+ void o5_lights();
+ void o5_loadRoom();
+ void o5_loadRoomWithEgo();
+ void o5_matrixOps();
+ void o5_move();
+ void o5_multiply();
+ void o5_notEqualZero();
+ void o5_or();
+ void o5_overRide();
+ void o5_panCameraTo();
+ void o5_pickupObject();
+ void o5_print();
+ void o5_printEgo();
+ void o5_pseudoRoom();
+ void o5_putActor();
+ void o5_putActorAtObject();
+ void o5_putActorInRoom();
+ void o5_quitPauseRestart();
+ void o5_resourceRoutines();
+ void o5_roomOps();
+ void o5_saveRestoreVerbs();
+ void o5_setCameraAt();
+ void o5_setClass();
+ void o5_setObjectName();
+ void o5_setOwnerOf();
+ void o5_setState();
+ void o5_setVarRange();
+ void o5_soundKludge();
+ void o5_startMusic();
+ void o5_startObject();
+ void o5_startScript();
+ void o5_startSound();
+ void o5_stopMusic();
+ void o5_stopObjectCode();
+ void o5_stopObjectScript();
+ void o5_stopScript();
+ void o5_stopSound();
+ void o5_stringOps();
+ void o5_subtract();
+ void o5_verbOps();
+ void o5_wait();
+ void o5_walkActorTo();
+ void o5_walkActorToActor();
+ void o5_walkActorToObject();
+ void o5_oldRoomEffect();
+ void o5_pickupObjectOld();
+};
+
+// FIXME - subclassing V2 from Scumm_v5 is a hack: V2 should have its own opcode table
+class Scumm_v2 : public Scumm_v5
+{
+public:
+ Scumm_v2(GameDetector *detector, OSystem *syst) : Scumm_v5(detector, syst) {}
+
+ virtual void readIndexFile();
+};
+
+// FIXME - maybe we should move the opcodes from v5 to v3, and change the inheritance
+// accordingly - that would be more logical I guess. However, if you do so, take care
+// of preserving the right readIndexFile / loadCharset !!!
+class Scumm_v3 : public Scumm_v5
+{
+public:
+ Scumm_v3(GameDetector *detector, OSystem *syst) : Scumm_v5(detector, syst) {}
+
+ void readIndexFile();
+ virtual void loadCharset(int no);
+};
+
+class Scumm_v4 : public Scumm_v3
+{
+public:
+ Scumm_v4(GameDetector *detector, OSystem *syst) : Scumm_v3(detector, syst) {}
+
+ void loadCharset(int no);
+};
+
+class Scumm_v6 : public Scumm
+{
+protected:
+ typedef void (Scumm_v6::*OpcodeProcV6)();
+ struct OpcodeEntryV6 {
+ OpcodeProcV6 proc;
+ const char *desc;
+ };
+
+ const OpcodeEntryV6 *_opcodesV6;
+
+public:
+ Scumm_v6(GameDetector *detector, OSystem *syst) : Scumm(detector, syst) {}
+
+protected:
+ virtual void setupOpcodes();
+
+ virtual void executeOpcode(int i);
+ virtual const char *getOpcodeDesc(int i);
+
+ int popRoomAndObj(int *room);
+
+ void decodeParseString2(int a, int b);
+ int getStackList(int16 *args, uint maxnum);
+
+ /* Version 6 script opcodes */
+ void o6_setBlastObjectWindow();
+ void o6_pushByte();
+ void o6_pushWord();
+ void o6_pushByteVar();
+ void o6_pushWordVar();
+ void o6_invalid();
+ void o6_byteArrayRead();
+ void o6_wordArrayRead();
+ void o6_byteArrayIndexedRead();
+ void o6_wordArrayIndexedRead();
+ void o6_dup();
+ void o6_not();
+ void o6_eq();
+ void o6_neq();
+ void o6_gt();
+ void o6_lt();
+ void o6_le();
+ void o6_ge();
+ void o6_add();
+ void o6_sub();
+ void o6_mul();
+ void o6_div();
+ void o6_land();
+ void o6_lor();
+ void o6_kill();
+ void o6_writeByteVar();
+ void o6_writeWordVar();
+ void o6_byteArrayWrite();
+ void o6_wordArrayWrite();
+ void o6_byteArrayIndexedWrite();
+ void o6_wordArrayIndexedWrite();
+ void o6_byteVarInc();
+ void o6_wordVarInc();
+ void o6_byteArrayInc();
+ void o6_wordArrayInc();
+ void o6_byteVarDec();
+ void o6_wordVarDec();
+ void o6_byteArrayDec();
+ void o6_wordArrayDec();
+ void o6_jumpTrue();
+ void o6_jumpFalse();
+ void o6_jump();
+ void o6_startScriptEx();
+ void o6_startScript();
+ void o6_startObject();
+ void o6_setObjectState();
+ void o6_setObjectXY();
+ void o6_stopObjectCode();
+ void o6_endCutscene();
+ void o6_cutScene();
+ void o6_stopMusic();
+ void o6_freezeUnfreeze();
+ void o6_cursorCommand();
+ void o6_breakHere();
+ void o6_ifClassOfIs();
+ void o6_setClass();
+ void o6_getState();
+ void o6_setState();
+ void o6_setOwner();
+ void o6_getOwner();
+ void o6_startSound();
+ void o6_stopSound();
+ void o6_startMusic();
+ void o6_stopObjectScript();
+ void o6_panCameraTo();
+ void o6_actorFollowCamera();
+ void o6_setCameraAt();
+ void o6_loadRoom();
+ void o6_stopScript();
+ void o6_walkActorToObj();
+ void o6_walkActorTo();
+ void o6_putActorInRoom();
+ void o6_putActorAtObject();
+ void o6_faceActor();
+ void o6_animateActor();
+ void o6_doSentence();
+ void o6_pickupObject();
+ void o6_loadRoomWithEgo();
+ void o6_getRandomNumber();
+ void o6_getRandomNumberRange();
+ void o6_getActorMoving();
+ void o6_isScriptRunning();
+ void o6_getActorRoom();
+ void o6_getObjectX();
+ void o6_getObjectY();
+ void o6_getObjectOldDir();
+ void o6_getObjectNewDir();
+ void o6_getActorWalkBox();
+ void o6_getActorCostume();
+ void o6_findInventory();
+ void o6_getInventoryCount();
+ void o6_getVerbFromXY();
+ void o6_beginOverride();
+ void o6_endOverride();
+ void o6_setObjectName();
+ void o6_isSoundRunning();
+ void o6_setBoxFlags();
+ void o6_createBoxMatrix();
+ void o6_resourceRoutines();
+ void o6_roomOps();
+ void o6_actorSet();
+ void o6_verbOps();
+ void o6_getActorFromXY();
+ void o6_findObject();
+ void o6_pseudoRoom();
+ void o6_getActorElevation();
+ void o6_getVerbEntrypoint();
+ void o6_arrayOps();
+ void o6_saveRestoreVerbs();
+ void o6_drawBox();
+ void o6_getActorWidth();
+ void o6_wait();
+ void o6_getActorScaleX();
+ void o6_getActorAnimCounter1();
+ void o6_soundKludge();
+ void o6_isAnyOf();
+ void o6_quitPauseRestart();
+ void o6_isActorInBox();
+ void o6_delay();
+ void o6_delayLonger();
+ void o6_delayVeryLong();
+ void o6_stopSentence();
+ void o6_print_0();
+ void o6_print_1();
+ void o6_print_2();
+ void o6_print_3();
+ void o6_printActor();
+ void o6_printEgo();
+ void o6_talkActor();
+ void o6_talkEgo();
+ void o6_dim();
+ void o6_dummy();
+ void o6_runVerbCodeQuick();
+ void o6_runScriptQuick();
+ void o6_dim2();
+ void o6_abs();
+ void o6_distObjectObject();
+ void o6_distObjectPt();
+ void o6_distPtPt();
+ void o6_miscOps();
+ void o6_delayFrames();
+ void o6_pickOneOf();
+ void o6_pickOneOfDefault();
+ void o6_jumpToScript();
+ void o6_isRoomScriptRunning();
+ void o6_kernelFunction();
+ void o6_getAnimateVariable();
+ void o6_drawBlastObject();
+ void o6_getActorPriority();
+ void o6_unknownCD();
+ void o6_bor();
+ void o6_band();
+};
+
+class Scumm_v7 : public Scumm_v6
+{
+public:
+ Scumm_v7(GameDetector *detector, OSystem *syst) : Scumm_v6(detector, syst) {}
+
+protected:
+ virtual void setupScummVars();
+};
+
+class Scumm_v8 : public Scumm
+{
+protected:
+ typedef void (Scumm_v8::*OpcodeProcV8)();
+ struct OpcodeEntryV8 {
+ OpcodeProcV8 proc;
+ const char *desc;
+ };
+
+ const OpcodeEntryV8 *_opcodesV8;
+
+public:
+ Scumm_v8(GameDetector *detector, OSystem *syst) : Scumm(detector, syst) {}
+
+protected:
+ virtual void setupOpcodes();
+
+ virtual void executeOpcode(int i);
+ virtual const char *getOpcodeDesc(int i);
+
+ /* Version 8 script opcodes */
+ void o8_unknown();
+ void o8_invalid();
+
+ void o8_pushNumber();
+ void o8_pushVariable();
+ void o8_dup();
+ void o8_pop();
+ void o8_not();
+ void o8_eq();
+ void o8_neq();
+ void o8_gt();
+ void o8_lt();
+ void o8_le();
+ void o8_ge();
+ void o8_add();
+ void o8_sub();
+ void o8_mul();
+ void o8_div();
+ void o8_land();
+ void o8_lor();
+ void o8_band();
+ void o8_bor();
+ void o8_mod();
+ void o8_jump();
+ void o8_breakHere();
+ void o8_startScript();
+ void o8_startObject();
+};
+
+
+#endif
diff --git a/scumm/module.mk b/scumm/module.mk
index e1771b49f6..5f4a3b6410 100644
--- a/scumm/module.mk
+++ b/scumm/module.mk
@@ -20,6 +20,7 @@ SCUMM_OBJS = \
scumm/script.o \
scumm/script_v5.o \
scumm/script_v6.o \
+ scumm/script_v8.o \
scumm/scummvm.o \
scumm/sound.o \
scumm/string.o \
diff --git a/scumm/resource.cpp b/scumm/resource.cpp
index 5551d00f0f..e37b9a94d7 100644
--- a/scumm/resource.cpp
+++ b/scumm/resource.cpp
@@ -31,7 +31,6 @@
uint16 newTag2Old(uint32 oldTag);
-
/* Open a room */
void Scumm::openRoom(int room)
{
@@ -39,6 +38,7 @@ void Scumm::openRoom(int room)
char buf[256];
debug(9, "openRoom(%d)", room);
+ assert(room >= 0);
/* Don't load the same room again */
if (_lastLoadedRoom == room)
@@ -125,7 +125,17 @@ void Scumm::openRoom(int room)
} while (1);
deleteRoomOffsets();
- _fileOffset = 0; /* start of file */
+ _fileOffset = 0; // start of file
+}
+
+void Scumm::closeRoom()
+{
+ if (_lastLoadedRoom != -1) {
+ _lastLoadedRoom = -1;
+ _encbyte = 0;
+ deleteRoomOffsets();
+ _fileHandle.close();
+ }
}
/* Delete the currently loaded room offsets */
@@ -202,7 +212,7 @@ void Scumm::readIndexFile()
debug(9, "readIndexFile()");
- openRoom(-1);
+ closeRoom();
openRoom(0);
if (!(_features & GF_AFTER_V6)) {
@@ -330,12 +340,17 @@ void Scumm::readIndexFile()
break;
case MKID('AARY'):
+ debug(3, "Going to call readArrayFromIndexFile (pos = 0x%08x)", _fileHandle.pos());
readArrayFromIndexFile();
+ debug(3, "After readArrayFromIndexFile (pos = 0x%08x)", _fileHandle.pos());
break;
default:
- error("Bad ID %c%c%c%c found in directory!", blocktype & 0xFF,
- blocktype >> 8, blocktype >> 16, blocktype >> 24);
+ error("Bad ID %c%c%c%c found in directory!",
+ (byte)blocktype,
+ (byte)(blocktype >> 8),
+ (byte)(blocktype >> 16),
+ (byte)(blocktype >> 24));
return;
}
}
@@ -343,22 +358,42 @@ void Scumm::readIndexFile()
// if (numblock!=9)
// error("Not enough blocks read from directory");
- openRoom(-1);
+ closeRoom();
}
void Scumm::readArrayFromIndexFile()
{
int num;
- int a, b, c;
-
- while ((num = _fileHandle.readUint16LE()) != 0) {
- a = _fileHandle.readUint16LE();
- b = _fileHandle.readUint16LE();
- c = _fileHandle.readUint16LE();
- if (c == 1)
- defineArray(num, 1, a, b);
- else
- defineArray(num, 5, a, b);
+ int a, b, c, d;
+
+ if (_features & GF_AFTER_V8) {
+ // FIXME - I am not quite sure how to interpret the AARY format of COMI.
+ // Each entry seems to be 12 bytes, while in V7 games it is only 8 bytes.
+ // 2 of the additional bytes seem to be used for num. But what about the
+ // other 2?. Either one of the three fields grew, too (but which). Or there
+ // is a new field, but then what does it mean? Endy or ludde probably know more :-)
+ while ((num = _fileHandle.readUint32LE()) != 0) {
+ a = _fileHandle.readUint16LE();
+ b = _fileHandle.readUint16LE();
+ c = _fileHandle.readUint16LE();
+ d = _fileHandle.readUint16LE();
+
+ printf("Reading array (0x%08x,%d,%d,%d,%d) - (pos = 0x%08x)\n", num, a, b, c, d, _fileHandle.pos());
+ if (c == 1)
+ defineArray(num, 1, a, b);
+ else
+ defineArray(num, 5, a, b);
+ }
+ } else {
+ while ((num = _fileHandle.readUint16LE()) != 0) {
+ a = _fileHandle.readUint16LE();
+ b = _fileHandle.readUint16LE();
+ c = _fileHandle.readUint16LE();
+ if (c == 1)
+ defineArray(num, 1, a, b);
+ else
+ defineArray(num, 5, a, b);
+ }
}
}
@@ -388,7 +423,7 @@ void Scumm::readResTypeList(int id, uint32 tag, const char *name)
}
if (_features & GF_OLD_BUNDLE) {
- if (id == rtRoom){
+ if (id == rtRoom) {
for (i = 0; i < num; i++)
res.roomno[id][i] = i;
_fileHandle.seek(num, SEEK_CUR);
@@ -1514,6 +1549,10 @@ void Scumm::readMAXS()
_fileHandle.readUint32LE();
_numArray = _fileHandle.readUint32LE();
+ // FIXME - uhm... COMI seems to have an ARRY with 143 entries, but
+ // indeed _numArray gets set to 50 ?!?
+ _numArray = 150;
+
_objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
_numGlobalScripts = 2000;
diff --git a/scumm/resource_v2.cpp b/scumm/resource_v2.cpp
index c78921f923..b992b3d7ea 100644
--- a/scumm/resource_v2.cpp
+++ b/scumm/resource_v2.cpp
@@ -21,6 +21,7 @@
#include "stdafx.h"
#include "scumm.h"
+#include "intern.h"
#include "resource.h"
@@ -29,7 +30,7 @@ void Scumm_v2::readIndexFile()
int magic = 0;
debug(9, "readIndexFile()");
- openRoom(-1);
+ closeRoom();
openRoom(0);
magic = _fileHandle.readUint16LE();
@@ -81,5 +82,5 @@ void Scumm_v2::readIndexFile()
readResTypeList(rtScript, MKID('SCRP'), "script");
readResTypeList(rtSound, MKID('SOUN'), "sound");
- openRoom(-1);
+ closeRoom();
}
diff --git a/scumm/resource_v3.cpp b/scumm/resource_v3.cpp
index 45b31bf6e5..e9b0a25d31 100644
--- a/scumm/resource_v3.cpp
+++ b/scumm/resource_v3.cpp
@@ -22,6 +22,7 @@
#include "stdafx.h"
#include "scumm.h"
+#include "intern.h"
#include "resource.h"
@@ -34,7 +35,7 @@ void Scumm_v3::readIndexFile()
debug(9, "readIndexFile()");
- openRoom(-1);
+ closeRoom();
openRoom(0);
while (!_fileHandle.eof()) {
@@ -147,7 +148,7 @@ void Scumm_v3::readIndexFile()
}
}
- openRoom(-1);
+ closeRoom();
}
void Scumm_v3::loadCharset(int no)
@@ -156,12 +157,12 @@ void Scumm_v3::loadCharset(int no)
memset(_charsetData, 0, sizeof(_charsetData));
checkRange(4, 0, no, "Loading illegal charset %d");
- openRoom(-1);
+ closeRoom();
openRoom(98 + no);
size = _fileHandle.readUint16LE();
_fileHandle.read(createResource(6, no, size), size);
- openRoom(-1);
+ closeRoom();
}
diff --git a/scumm/resource_v4.cpp b/scumm/resource_v4.cpp
index fc8ea5fb9b..e8731bae18 100644
--- a/scumm/resource_v4.cpp
+++ b/scumm/resource_v4.cpp
@@ -22,6 +22,7 @@
#include "stdafx.h"
#include "scumm.h"
+#include "intern.h"
void Scumm_v4::loadCharset(int no)
{
@@ -29,12 +30,12 @@ void Scumm_v4::loadCharset(int no)
memset(_charsetData, 0, sizeof(_charsetData));
checkRange(4, 0, no, "Loading illegal charset %d");
- openRoom(-1);
+ closeRoom();
openRoom(900 + no);
size = _fileHandle.readUint32LE() + 11;
_fileHandle.read(createResource(6, no, size), size);
- openRoom(-1);
+ closeRoom();
}
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 78be8b140b..817a833c2c 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -111,7 +111,8 @@ bool Scumm::loadState(int slot, bool compat, SaveFileManager *mgr)
_sound->stopCD();
_sound->pauseSounds(true);
- CHECK_HEAP openRoom(-1);
+ CHECK_HEAP
+ closeRoom();
memset(_inventory, 0, sizeof(_inventory[0]) * _numInventory);
/* Nuke all resources */
diff --git a/scumm/script_v5.cpp b/scumm/script_v5.cpp
index 9d9bfa0776..d385bab2dc 100644
--- a/scumm/script_v5.cpp
+++ b/scumm/script_v5.cpp
@@ -23,8 +23,9 @@
#include "stdafx.h"
#include "scumm.h"
#include "actor.h"
+#include "intern.h"
+#include "sound.h"
#include "verbs.h"
-#include "scumm/sound.h"
#define OPCODE(x) { &Scumm_v5::x, #x }
diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp
index d6708374a8..3a375f7f7d 100644
--- a/scumm/script_v6.cpp
+++ b/scumm/script_v6.cpp
@@ -24,13 +24,14 @@
#include "stdafx.h"
#include "scumm.h"
#include "actor.h"
+#include "imuse.h"
+#include "intern.h"
+#include "sound.h"
#include "verbs.h"
#include "smush/player.h"
#include "smush/scumm_renderer.h"
#include "sound/mididrv.h"
-#include "scumm/sound.h"
-#include "scumm/imuse.h"
#include "dialogs.h" // FIXME: This is just for the FT-INSANE warning.
// Remove when INSANE is implemented
diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp
new file mode 100644
index 0000000000..49209c7957
--- /dev/null
+++ b/scumm/script_v8.cpp
@@ -0,0 +1,1040 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "scumm.h"
+#include "intern.h"
+
+/*
+ * NO, we do NOT support CMI yet :-) This file is mostly a placeholder and a place
+ * to grow real support in. For now, only a few opcodes are implemented, and they
+ * might even be wrong... so don't hold your breath.
+ */
+
+#define OPCODE(x) { &Scumm_v8::x, #x }
+
+void Scumm_v8::setupOpcodes()
+{
+ static const OpcodeEntryV8 opcodes[256] = {
+ /* 00 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_pushNumber),
+ OPCODE(o8_pushVariable),
+ OPCODE(o8_unknown),
+ /* 04 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_dup),
+ OPCODE(o8_pop),
+ OPCODE(o8_not),
+ /* 08 */
+ OPCODE(o8_eq),
+ OPCODE(o8_neq),
+ OPCODE(o8_gt),
+ OPCODE(o8_lt),
+ /* 0C */
+ OPCODE(o8_le),
+ OPCODE(o8_ge),
+ OPCODE(o8_add),
+ OPCODE(o8_sub),
+ /* 10 */
+ OPCODE(o8_mul),
+ OPCODE(o8_div),
+ OPCODE(o8_land),
+ OPCODE(o8_lor),
+ /* 14 */
+ OPCODE(o8_band),
+ OPCODE(o8_bor),
+ OPCODE(o8_mod),
+ OPCODE(o8_unknown),
+ /* 18 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 1C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 20 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 24 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 28 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 2C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 30 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 34 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 38 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 3C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 40 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 44 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 48 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 4C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 50 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 54 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 58 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 5C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 60 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 64 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_jump),
+ OPCODE(o8_breakHere),
+ /* 68 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 6C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 70 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 74 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 78 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 7C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 80 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 84 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 88 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 8C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 90 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 94 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 98 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* 9C */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* A0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* A4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* A8 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* AC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* B0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* B4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* B8 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* BC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* C0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* C4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* C8 */
+ OPCODE(o8_startScript),
+ OPCODE(o8_startObject),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* CC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* D0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* D4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* D8 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* DC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* E0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* E4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* E8 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* EC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* F0 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* F4 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* F8 */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ /* FC */
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ OPCODE(o8_unknown),
+ };
+
+ _opcodesV8 = opcodes;
+}
+
+void Scumm_v8::executeOpcode(int i)
+{
+ OpcodeProcV8 op = _opcodesV8[i].proc;
+ (this->*op) ();
+}
+
+const char *Scumm_v8::getOpcodeDesc(int i)
+{
+ return _opcodesV8[i].desc;
+}
+
+void Scumm_v8::o8_unknown()
+{
+ warning("Unknown opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer);
+}
+
+void Scumm_v8::o8_invalid()
+{
+ error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer);
+}
+
+void Scumm_v8::o8_dup()
+{
+ int a = pop();
+ push(a);
+ push(a);
+}
+
+void Scumm_v8::o8_pop()
+{
+ pop();
+}
+
+void Scumm_v8::o8_not()
+{
+ push(pop() == 0);
+}
+
+void Scumm_v8::o8_eq()
+{
+ push(pop() == pop());
+}
+
+void Scumm_v8::o8_neq()
+{
+ push(pop() != pop());
+}
+
+void Scumm_v8::o8_gt()
+{
+ int a = pop();
+ push(pop() > a);
+}
+
+void Scumm_v8::o8_lt()
+{
+ int a = pop();
+ push(pop() < a);
+}
+
+void Scumm_v8::o8_le()
+{
+ int a = pop();
+ push(pop() <= a);
+}
+
+void Scumm_v8::o8_ge()
+{
+ int a = pop();
+ push(pop() >= a);
+}
+
+void Scumm_v8::o8_add()
+{
+ int a = pop();
+ push(pop() + a);
+}
+
+void Scumm_v8::o8_sub()
+{
+ int a = pop();
+ push(pop() - a);
+}
+
+void Scumm_v8::o8_mul()
+{
+ int a = pop();
+ push(pop() * a);
+}
+
+void Scumm_v8::o8_div()
+{
+ int a = pop();
+ if (a == 0)
+ error("division by zero");
+ push(pop() / a);
+}
+
+void Scumm_v8::o8_land() // Logical And
+{
+ int a = pop();
+ push(pop() && a);
+}
+
+void Scumm_v8::o8_lor() // Logical Or
+{
+ int a = pop();
+ push(pop() || a);
+}
+
+void Scumm_v8::o8_bor() // Bitwise Or
+{
+ int a = pop();
+ push(pop() | a);
+}
+
+void Scumm_v8::o8_band() // Bitwise And
+{
+ int a = pop();
+ push(pop() | a);
+}
+
+void Scumm_v8::o8_mod()
+{
+ int a = pop();
+ push(pop() % a);
+}
+
+void Scumm_v8::o8_breakHere()
+{
+ // TODO
+}
+
+void Scumm_v8::o8_pushNumber()
+{
+ // TODO
+}
+
+void Scumm_v8::o8_startObject()
+{
+ // TODO
+}
+
+void Scumm_v8::o8_startScript()
+{
+ // TODO
+}
+
+void Scumm_v8::o8_pushVariable()
+{
+ // TODO
+}
+
+void Scumm_v8::o8_jump()
+{
+ // TODO
+}
+
+/*
+
+From http://scummrev.mixnmojo.com/specs/CMIOpcodes.shtml
+
+000 O_0
+001 O_PUSH_NUMBER Push number onto stack.
+002 O_PUSH_VARIABLE Push variable value onto stack.
+003 O_PUSH_ARRAY_VALUE Push array value onto stack.
+004 O_PUSH_ARRAY2_VALUE ?
+005 O_DUP Duplicate stack value
+006 O_POP Pop value from stack.
+007 O_NOT NOT (!)
+008 O_EQ Equals (==)
+009 O_NEQ Does not equal (!=)
+00A O_GT Greater than (>)
+00B O_LT Less than (<)
+00C O_LEQ Less than or equal (<=)
+00D O_GEQ Greater than or equal (>=)
+00E O_ADD Add (+)
+00F O_SUB Subtract (-)
+010 O_MUL Multiply (*)
+011 O_DIV Divide (/)
+012 O_LAND Logical AND
+013 O_LOR Logical OR
+014 O_BAND Binary AND
+015 O_BOR Binary OR
+016 O_MOD Modulus (%)
+017 O_23
+018 O_24
+019 O_25
+01A O_26
+01B O_27
+01C O_28
+01D O_29
+01E O_30
+01F O_31
+020 O_32
+021 O_33
+022 O_34
+023 O_35
+024 O_36
+025 O_37
+026 O_38
+027 O_39
+028 O_40
+029 O_41
+02A O_42
+02B O_43
+02C O_44
+02D O_45
+02E O_46
+02F O_47
+030 O_48
+031 O_49
+032 O_50
+033 O_51
+034 O_52
+035 O_53
+036 O_54
+037 O_55
+038 O_56
+039 O_57
+03A O_58
+03B O_59
+03C O_60
+03D O_61
+03E O_62
+03F O_63
+040 O_64
+041 O_65
+042 O_66
+043 O_67
+044 O_68
+045 O_69
+046 O_70
+047 O_71
+048 O_72
+049 O_73
+04A O_74
+04B O_75
+04C O_76
+04D O_77
+04E O_78
+04F O_79
+050 O_80
+051 O_81
+052 O_82
+053 O_83
+054 O_84
+055 O_85
+056 O_86
+057 O_87
+058 O_88
+059 O_89
+05A O_90
+05B O_91
+05C O_92
+05D O_93
+05E O_94
+05F O_95
+060 O_96
+061 O_97
+062 O_98
+063 O_99
+064 O_IF if ()
+065 O_IF_NOT if not ()
+066 O_JUMP jump/goto
+067 O_BREAK_HERE Break out of script
+068 O_BREAK_HERE_VAR
+069 O_WAIT_FOR_STUFF Wait Sub opcodes
+06A O_SLEEP_JIFFIES Sleep for jiffies (10ths of a second)
+06B O_SLEEP_SECONDS Sleep for seconds
+06C O_SLEEP_MINUTES Sleep for minutes
+06D O_STORE_VARIABLE Assign value to variable
+06E O_INC_VARIABLE Increase variable value (++)
+06F O_DEC_VARIABLE Decrease variable value (--)
+070 O_ARRAY_DIM Set dimension of array
+071 O_STORE_ARRAY Assign value to array
+072 O_INC_ARRAY Increase array value
+073 O_DEC_ARRAY Decrease array value
+074 O_ARRAY_DIM2 Set dimensions of 2 dimensional array
+075 O_STORE_ARRAY2 Assign value to 2 dimensional array
+076 O_ASSIGN_ARRAY ?
+077 O_ARRAY_SHUFFLE Shuffle array
+078 O_ARRAY_LOCALIZE ?
+079 O_START_SCRIPT Start script
+07A O_START_SCRIPT_QUICK ?
+07B O_END_SCRIPT End script
+07C O_STOP_SCRIPT Stop script from running
+07D O_CHAIN_SCRIPT ?
+07E O_RETURN Return
+07F O_START_OBJECT ?
+080 O_STOP_OBJECT ?
+081 O_CUT_SCENE Start of cutscene (interface off)
+082 O_END_CUT_SCENE End of cutscene (interface on)
+083 O_FREEZE_SCRIPTS ?
+084 O_OVERRIDE ?
+085 O_OVERRIDE_OFF ?
+086 O_STOP_SENTENCE ?
+087 O_DEBUG Set debug mode
+088 O_DEBUG_WINDEX Set debug mode with output to external window
+089 O_CLASS_OF Set class of script
+08A O_STATE_OF ?
+08B O_OWNER_OF Set owner of object
+08C O_CAMERA_PAN_TO Pan camera to (X,Y)
+08D O_CAMERA_FOLLOW Make camera follow character/object
+08E O_CAMERA_AT Place camera at specific (X,Y)
+08F O_SAY_LINE Talk
+090 O_SAY_LINE_DEFAULT Talk using default actor
+091 O_SAY_LINE_SIMPLE Talk with less arguments
+092 O_SAY_LINE_SIMPLE_DEFAULT Talk with less arguments using default actor
+093 O_PRINT_LINE Print a line on screen
+094 O_PRINT_CURSOR
+095 O_PRINT_DEBUG
+096 O_PRINT_SYSTEM
+097 O_BLAST_TEXT Text to output to screen
+098 O_DRAW_OBJECT Draw object
+099 O_153
+09A O_BLAST_OBJECT
+09B O_155
+09C O_USERFACE ?
+09D O_CURRENT_ROOM Set current room
+09E O_COME_OUT_DOOR
+09F O_WALK_ACTOR_TO_OBJECT Walk to object
+0A0 O_WALK_ACTOR_TO_XY Walk to coordinate
+0A1 O_PUT_ACTOR_AT_XY Put at coordinate
+0A2 O_PUT_ACTOR_AT_OBJECT Put at object
+0A3 O_FACE_TOWARDS Change facing
+0A4 O_DO_ANIMATION Animate
+0A5 O_DO_SENTENCE
+0A6 O_PICK_UP_OBJECT Pick up object
+0A7 O_SET_BOX
+0A8 O_SET_BOX_PATH
+0A9 O_SET_BOX_SET
+0AA O_HEAP_STUFF Heap sub opcodes
+0AB O_ROOM_STUFF Room sub opcodes
+0AC O_ACTOR_STUFF Actor sub opcodes
+0AD O_CAMERA_STUFF Camera sub opcodes
+0AE O_VERB_STUFF Verb sub opcodes
+0AF O_START_SFX Start sound effect
+0B0 O_START_MUSIC Start music
+0B1 O_STOP_SOUND Stop sound (effect or music)
+0B2 O_SOUND_KLUDGE ?
+0B3 O_SYSTEM System sub opcodes
+0B4 O_VERB_SETS
+0B5 O_NEW_NAME_OF Set new name of object
+0B6 O_GET_TIME_DATE Get time and/or date
+0B7 O_DRAW_BOX
+0B8 O_ACTOBJ_STAMP
+0B9 O_START_VIDEO Start cutscene video
+0BA O_KLUDGE
+0BB O_187
+0BC O_188
+0BD O_189
+0BE O_190
+0BF O_191
+0C0 O_192
+0C1 O_193
+0C2 O_194
+0C3 O_195
+0C4 O_196
+0C5 O_197
+0C6 O_198
+0C7 O_199
+0C8 F_START_SCRIPT Start script
+0C9 F_START_OBJECT Start object script
+0CA F_PICK
+0CB F_PICK_DEFAULT
+0CC F_PICK_RANDOM
+0CD F_IN_SET
+0CE F_RANDOM Get random number
+0CF F_RANDOM_BETWEEN Get random number between two values
+0D0 F_CLASS_OF Get class of script
+0D1 F_STATE_OF
+0D2 F_OWNER_OF Get owner of object
+0D3 F_SCRIPT_RUNNING Test if script is running
+0D4 F_OBJECT_RUNNING Test if object is running
+0D5 F_SOUND_RUNNING Test if sound is running
+0D6 F_ABS Get absolute value
+0D7 F_PIXEL
+0D8 F_KLUDGE
+0D9 F_IN_BOX Test if object is in box
+0DA F_VALID_VERB
+0DB F_FIND_ACTOR
+0DC F_FIND_OBJECT
+0DD F_FIND_VERB
+0DE F_FIND_ALL_OBJECTS
+0DF F_ACTOR_INVENTORY
+0E0 F_ACTOR_INVENTORY_COUNT Get number of items in inventory
+0E1 F_ACTOR_VARIABLE Get actor variable (property)
+0E2 F_ACTOR_ROOM Get current room for actor
+0E3 F_ACTOR_BOX Get current box for actor
+0E4 F_ACTOR_MOVING Test if actor is moving
+0E5 F_ACTOR_COSTUME Get current costume for actor
+0E6 F_ACTOR_SCALE Get current scale of actor
+0E7 F_ACTOR_DEPTH Get current Z position of actor
+0E8 F_ACTOR_ELEVATION Get current actor elevation
+0E9 F_ACTOR_WIDTH Get current actor width
+0EA F_ACTOBJ_FACING Get current actor/object facing
+0EB F_ACTOBJ_X Get X position of actor/object
+0EC F_ACTOBJ_Y Get Y position of actor/object
+0ED F_ACTOR_CHORE
+0EE F_PROXIMITY_2ACTOBJS Get distance between 2 actors/objects
+0EF F_PROXIMITY_2POINTS Get distance between 2 points
+0F0 F_OBJECT_IMAGE_X Get X position of object image
+0F1 F_OBJECT_IMAGE_Y Get Y position of object image
+0F2 F_OBJECT_IMAGE_WIDTH Get width of object image
+0F3 F_OBJECT_IMAGE_HEIGHT Get height of object image
+0F4 F_VERB_X Get X position of verb
+0F5 F_VERB_Y Get Y position of verb
+0F6 F_STRING_WIDTH
+0F7 F_ACTOR_ZPLANE
+0F8 O_248
+0F9 O_249
+0FA O_250
+0FB O_251
+0FC O_252
+0FD O_253
+0FE O_254
+0FF O_255
+
+The following are subopcodes - just strip the leading 1
+
+100 SO_256
+101 SO_257
+102 SO_258
+103 SO_259
+104 SO_260
+105 SO_261
+106 SO_262
+107 SO_263
+108 SO_264
+109 SO_265
+10A SO_ARRAY_SCUMMVAR
+10B SO_ARRAY_STRING
+10C SO_ARRAY_UNDIM
+10D SO_269
+10E SO_270
+10F SO_271
+110 SO_272
+111 SO_273
+112 SO_274
+113 SO_275
+114 SO_ASSIGN_STRING
+115 SO_ASSIGN_SCUMMVAR_LIST
+116 SO_ASSIGN_2DIM_LIST
+117 SO_279
+118 SO_280
+119 SO_281
+11A SO_282
+11B SO_283
+11C SO_284
+11D SO_285
+11E SO_WAIT_FOR_ACTOR Wait for actor (to finish current action?)
+11F SO_WAIT_FOR_MESSAGE Wait for message
+120 SO_WAIT_FOR_CAMERA Wait for camera (to finish current action?)
+121 SO_WAIT_FOR_SENTENCE
+122 SO_WAIT_FOR_ANIMATION
+123 SO_WAIT_FOR_TURN
+124 SO_292
+125 SO_293
+126 SO_294
+127 SO_295
+128 SO_SYSTEM_RESTART Restart game
+129 SO_SYSTEM_QUIT Quit game
+12A SO_298
+12B SO_299
+12C SO_300
+12D SO_301
+12E SO_302
+12F SO_303
+130 SO_304
+131 SO_305
+132 SO_CAMERA_PAUSE
+133 SO_CAMERA_RESUME
+134 SO_308
+135 SO_309
+136 SO_310
+137 SO_311
+138 SO_312
+139 SO_313
+13A SO_314
+13B SO_315
+13C SO_HEAP_LOAD_CHARSET Load character set to heap
+13D SO_HEAP_LOAD_COSTUME Load costume to heap
+13E SO_HEAP_LOAD_OBJECT Load object to heap
+13F SO_HEAP_LOAD_ROOM Load room to heap
+140 SO_HEAP_LOAD_SCRIPT Load script to heap
+141 SO_HEAP_LOAD_SOUND Load sound to heap
+142 SO_HEAP_LOCK_COSTUME Lock costume in heap
+143 SO_HEAP_LOCK_ROOM Lock room in heap
+144 SO_HEAP_LOCK_SCRIPT Lock script in heap
+145 SO_HEAP_LOCK_SOUND Lock sound in heap
+146 SO_HEAP_UNLOCK_COSTUME Unlock costume
+147 SO_HEAP_UNLOCK_ROOM Unlock room
+148 SO_HEAP_UNLOCK_SCRIPT Unlock script
+149 SO_HEAP_UNLOCK_SOUND Unlock sound
+14A SO_HEAP_NUKE_COSTUME Remove costume from heap
+14B SO_HEAP_NUKE_ROOM Remove room from heap
+14C SO_HEAP_NUKE_SCRIPT Remove script from heap
+14D SO_HEAP_NUKE_SOUND Remove sound from heap
+14E SO_334
+14F SO_335
+150 SO_336
+151 SO_337
+152 SO_ROOM_PALETTE Set room palette
+153 SO_339
+154 SO_340
+155 SO_ROOM_INTENSITY Set room intensity
+156 SO_342
+157 SO_ROOM_FADE Fade room
+158 SO_ROOM_RGB_INTENSITY Set room color intensity
+159 SO_ROOM_TRANSFORM Transform room
+15A SO_ROOM_CYCLE_SPEED Set palette cycling speed
+15B SO_ROOM_COPY_PALETTE Copy palette
+15C SO_ROOM_NEW_PALETTE Create new palette
+15D SO_ROOM_SAVE_GAME Save game
+15E SO_ROOM_LOAD_GAME Load game
+15F SO_ROOM_SATURATION Set saturation of room colors
+160 SO_352
+161 SO_353
+162 SO_354
+163 SO_355
+164 SO_ACTOR_COSTUME Set actor costume
+165 SO_ACTOR_STEP_DIST Set actor width of steps
+166 SO_358
+167 SO_ACTOR_ANIMATION_DEFAULT Set actor animation to default
+168 SO_ACTOR_ANIMATION_INIT Initialize animation
+169 SO_ACTOR_ANIMATION_TALK Set actor animation to talk animation
+16A SO_ACTOR_ANIMATION_WALK Set actor animation to walk animation
+16B SO_ACTOR_ANIMATION_STAND Set actor animation to standing animation
+16C SO_ACTOR_ANIMATION_SPEED Set speed of animation
+16D SO_ACTOR_DEFAULT
+16E SO_ACTOR_ELEVATION
+16F SO_ACTOR_PALETTE Set actor palette
+170 SO_ACTOR_TALK_COLOR Set actor talk color
+171 SO_ACTOR_NAME Set name of actor
+172 SO_ACTOR_WIDTH Set width of actor
+173 SO_ACTOR_SCALE Set scaling of actor
+174 SO_ACTOR_NEVER_ZCLIP ?
+175 SO_ACTOR_ALWAYS_ZCLIP ?
+176 SO_ACTOR_IGNORE_BOXES Make actor ignore boxes
+177 SO_ACTOR_FOLLOW_BOXES Make actor follow boxes
+178 SO_ACTOR_SPECIAL_DRAW
+179 SO_ACTOR_TEXT_OFFSET Set text offset relative to actor
+17A SO_ACTOR_INIT Initialize actor
+17B SO_ACTOR_VARIABLE Set actor variable
+17C SO_ACTOR_IGNORE_TURNS_ON Make actor ignore turns
+17D SO_ACTOR_IGNORE_TURNS_OFF Make actor follow turns
+17E SO_ACTOR_NEW New actor
+17F SO_ACTOR_DEPTH Set actor Z position
+180 SO_ACTOR_STOP
+181 SO_ACTOR_FACE Make actor face angle
+182 SO_ACTOR_TURN Turn actor
+183 SO_ACTOR_WALK_SCRIPT Set walk script for actor?
+184 SO_ACTOR_TALK_SCRIPT Set talk script for actor?
+185 SO_ACTOR_WALK_PAUSE
+186 SO_ACTOR_WALK_RESUME
+187 SO_ACTOR_VOLUME Set volume of actor speech
+188 SO_ACTOR_FREQUENCY Set frequency of actor speech
+189 SO_ACTOR_PAN
+18A SO_394
+18B SO_395
+18C SO_396
+18D SO_397
+18E SO_398
+18F SO_399
+190 SO_400
+191 SO_401
+192 SO_402
+193 SO_403
+194 SO_404
+195 SO_405
+196 SO_VERB_INIT Choose verb number for editing
+197 SO_VERB_NEW New verb
+198 SO_VERB_DELETE Delete verb
+199 SO_VERB_NAME Set verb name
+19A SO_VERB_AT Set verb (X,Y) placement
+19B SO_VERB_ON Turn verb on
+19C SO_VERB_OFF Turn verb off
+19D SO_VERB_COLOR Set verb color
+19E SO_VERB_HICOLOR Set verb highlighted color
+19F SO_415
+1A0 SO_VERB_DIMCOLOR Set verb dimmed (disabled) color
+1A1 SO_VERB_DIM
+1A2 SO_VERB_KEY Set keypress to associate with verb
+1A3 SO_VERB_IMAGE Set verb image
+1A4 SO_VERB_NAME_STR Set verb name
+1A5 SO_VERB_CENTER Center verb
+1A6 SO_VERB_CHARSET Choose charset for verb
+1A7 SO_VERB_LINE_SPACING Choose linespacing for verb
+1A8 SO_424
+1A9 SO_425
+1AA SO_426
+1AB SO_427
+1AC SO_428
+1AD SO_429
+1AE SO_430
+1AF SO_431
+1B0 SO_432
+1B1 SO_433
+1B2 SO_434
+1B3 SO_435
+1B4 SO_VERBS_SAVE
+1B5 SO_VERBS_RESTORE
+1B6 SO_VERBS_DELETE
+1B7 SO_439
+1B8 SO_440
+1B9 SO_441
+1BA SO_442
+1BB SO_443
+1BC SO_444
+1BD SO_445
+1BE SO_446
+1BF SO_447
+1C0 SO_448
+1C1 SO_449
+1C2 SO_450
+1C3 SO_451
+1C4 SO_452
+1C5 SO_453
+1C6 SO_454
+1C7 SO_455
+1C8 SO_PRINT_BASEOP
+1C9 SO_PRINT_END
+1CA SO_PRINT_AT Print at coordinates (x,y)
+1CB SO_PRINT_COLOR Print color
+1CC SO_PRINT_CENTER Center output
+1CD SO_PRINT_CHARSET Set print character set
+1CE SO_PRINT_LEFT Left justify output
+1CF SO_PRINT_OVERHEAD
+1D0 SO_PRINT_MUMBLE
+1D1 SO_PRINT_STRING Set string to print
+1D2 SO_PRINT_WRAP Set print wordwrap
+1D3 SO_467
+1D4 SO_468
+1D5 SO_469
+1D6 SO_470
+1D7 SO_471
+1D8 SO_472
+1D9 SO_473
+1DA SO_474
+1DB SO_475
+1DC SO_CURSOR_ON Turn cursor on
+1DD SO_CURSOR_OFF Turn cursor off
+1DE SO_CURSOR_SOFT_ON Turn soft cursor on
+1DF SO_CURSOR_SOFT_OFF Turn soft cursor off
+1E0 SO_USERPUT_ON
+1E1 SO_USERPUT_OFF
+1E2 SO_USERPUT_SOFT_ON
+1E3 SO_USERPUT_SOFT_OFF
+1E4 SO_CURSOR_IMAGE Set cursor image
+1E5 SO_CURSOR_HOTSPOT Set cursor hotspot
+1E6 SO_CURSOR_TRANSPARENT Set cursor transparent color
+1E7 SO_CHARSET_SET
+1E8 SO_CHARSET_COLOR
+1E9 SO_CURSOR_PUT
+1EA SO_490
+1EB SO_491
+1EC SO_492
+1ED SO_493
+1EE SO_494
+1EF SO_495
+1F0 SO_496
+1F1 SO_497
+1F2 SO_498
+1F3 SO_499
+1F4 SO_500
+1F5 SO_501
+1F6 SO_502
+1F7 SO_503
+1F8 SO_504
+1F9 SO_505
+1FA SO_506
+1FB SO_507
+1FC SO_508
+1FD SO_509
+1FE SO_510
+1FF SO_511
+
+*/ \ No newline at end of file
diff --git a/scumm/scumm.h b/scumm/scumm.h
index fa2a1a1036..d9e8f93136 100644
--- a/scumm/scumm.h
+++ b/scumm/scumm.h
@@ -48,7 +48,6 @@ extern Scumm *g_scumm;
/* System Wide Constants */
enum {
- NUM_MIXER = 4,
NUM_SCRIPT_SLOT = 40,
NUM_LOCALSCRIPT = 60,
NUM_SHADOW_PALETTE = 8,
@@ -528,6 +527,7 @@ public:
void allocateArrays();
void openRoom(int room);
+ void closeRoom();
void deleteRoomOffsets();
void readRoomsOffsets();
void askForDisk(const char *filename);
@@ -1063,356 +1063,6 @@ public:
void updatePalette();
};
-class Scumm_v5 : public Scumm
-{
-protected:
- typedef void (Scumm_v5::*OpcodeProcV5)();
- struct OpcodeEntryV5 {
- OpcodeProcV5 proc;
- const char *desc;
- };
-
- const OpcodeEntryV5 *_opcodesV5;
-
-public:
- Scumm_v5(GameDetector *detector, OSystem *syst) : Scumm(detector, syst) {}
-
-protected:
- virtual void setupOpcodes();
- virtual void executeOpcode(int i);
- virtual const char *getOpcodeDesc(int i);
-
- void decodeParseString();
- int getWordVararg(int16 *ptr);
- int getVarOrDirectWord(byte mask);
- int getVarOrDirectByte(byte mask);
-
- /* Version 5 script opcodes */
- void o5_actorFollowCamera();
- void o5_actorFromPos();
- void o5_actorSet();
- void o5_add();
- void o5_and();
- void o5_animateActor();
- void o5_badOpcode();
- void o5_breakHere();
- void o5_chainScript();
- void o5_cursorCommand();
- void o5_cutscene();
- void o5_debug();
- void o5_decrement();
- void o5_delay();
- void o5_delayVariable();
- void o5_divide();
- void o5_doSentence();
- void o5_drawBox();
- void o5_drawObject();
- void o5_dummy();
- void o5_endCutscene();
- void o5_equalZero();
- void o5_expression();
- void o5_faceActor();
- void o5_findInventory();
- void o5_findObject();
- void o5_freezeScripts();
- void o5_getActorCostume();
- void o5_getActorElevation();
- void o5_getActorFacing();
- void o5_getActorMoving();
- void o5_getActorRoom();
- void o5_getActorScale();
- void o5_getActorWalkBox();
- void o5_getActorWidth();
- void o5_getActorX();
- void o5_getActorY();
- void o5_getAnimCounter();
- void o5_getClosestObjActor();
- void o5_getDist();
- void o5_getInventoryCount();
- void o5_getObjectOwner();
- void o5_getObjectState();
- void o5_getRandomNr();
- void o5_isScriptRunning();
- void o5_getVerbEntrypoint();
- void o5_ifClassOfIs();
- void o5_increment();
- void o5_isActorInBox();
- void o5_isEqual();
- void o5_isGreater();
- void o5_isGreaterEqual();
- void o5_isLess();
- void o5_isNotEqual();
- void o5_ifState();
- void o5_ifNotState();
- void o5_isSoundRunning();
- void o5_jumpRelative();
- void o5_lessOrEqual();
- void o5_lights();
- void o5_loadRoom();
- void o5_loadRoomWithEgo();
- void o5_matrixOps();
- void o5_move();
- void o5_multiply();
- void o5_notEqualZero();
- void o5_or();
- void o5_overRide();
- void o5_panCameraTo();
- void o5_pickupObject();
- void o5_print();
- void o5_printEgo();
- void o5_pseudoRoom();
- void o5_putActor();
- void o5_putActorAtObject();
- void o5_putActorInRoom();
- void o5_quitPauseRestart();
- void o5_resourceRoutines();
- void o5_roomOps();
- void o5_saveRestoreVerbs();
- void o5_setCameraAt();
- void o5_setClass();
- void o5_setObjectName();
- void o5_setOwnerOf();
- void o5_setState();
- void o5_setVarRange();
- void o5_soundKludge();
- void o5_startMusic();
- void o5_startObject();
- void o5_startScript();
- void o5_startSound();
- void o5_stopMusic();
- void o5_stopObjectCode();
- void o5_stopObjectScript();
- void o5_stopScript();
- void o5_stopSound();
- void o5_stringOps();
- void o5_subtract();
- void o5_verbOps();
- void o5_wait();
- void o5_walkActorTo();
- void o5_walkActorToActor();
- void o5_walkActorToObject();
- void o5_oldRoomEffect();
- void o5_pickupObjectOld();
-};
-
-// FIXME - subclassing V2 from Scumm_v5 is a hack: V2 should have its own opcode table
-class Scumm_v2 : public Scumm_v5
-{
-public:
- Scumm_v2(GameDetector *detector, OSystem *syst) : Scumm_v5(detector, syst) {}
-
- virtual void readIndexFile();
-};
-
-// FIXME - maybe we should move the opcodes from v5 to v3, and change the inheritance
-// accordingly - that would be more logical I guess. However, if you do so, take care
-// of preserving the right readIndexFile / loadCharset !!!
-class Scumm_v3 : public Scumm_v5
-{
-public:
- Scumm_v3(GameDetector *detector, OSystem *syst) : Scumm_v5(detector, syst) {}
-
- void readIndexFile();
- virtual void loadCharset(int no);
-};
-
-class Scumm_v4 : public Scumm_v3
-{
-public:
- Scumm_v4(GameDetector *detector, OSystem *syst) : Scumm_v3(detector, syst) {}
-
- void loadCharset(int no);
-};
-
-class Scumm_v6 : public Scumm
-{
-protected:
- typedef void (Scumm_v6::*OpcodeProcV6)();
- struct OpcodeEntryV6 {
- OpcodeProcV6 proc;
- const char *desc;
- };
-
- const OpcodeEntryV6 *_opcodesV6;
-
-public:
- Scumm_v6(GameDetector *detector, OSystem *syst) : Scumm(detector, syst) {}
-
-protected:
- virtual void setupOpcodes();
-
- virtual void executeOpcode(int i);
- virtual const char *getOpcodeDesc(int i);
-
- int popRoomAndObj(int *room);
-
- void decodeParseString2(int a, int b);
- int getStackList(int16 *args, uint maxnum);
-
- /* Version 6 script opcodes */
- void o6_setBlastObjectWindow();
- void o6_pushByte();
- void o6_pushWord();
- void o6_pushByteVar();
- void o6_pushWordVar();
- void o6_invalid();
- void o6_byteArrayRead();
- void o6_wordArrayRead();
- void o6_byteArrayIndexedRead();
- void o6_wordArrayIndexedRead();
- void o6_dup();
- void o6_not();
- void o6_eq();
- void o6_neq();
- void o6_gt();
- void o6_lt();
- void o6_le();
- void o6_ge();
- void o6_add();
- void o6_sub();
- void o6_mul();
- void o6_div();
- void o6_land();
- void o6_lor();
- void o6_kill();
- void o6_writeByteVar();
- void o6_writeWordVar();
- void o6_byteArrayWrite();
- void o6_wordArrayWrite();
- void o6_byteArrayIndexedWrite();
- void o6_wordArrayIndexedWrite();
- void o6_byteVarInc();
- void o6_wordVarInc();
- void o6_byteArrayInc();
- void o6_wordArrayInc();
- void o6_byteVarDec();
- void o6_wordVarDec();
- void o6_byteArrayDec();
- void o6_wordArrayDec();
- void o6_jumpTrue();
- void o6_jumpFalse();
- void o6_jump();
- void o6_startScriptEx();
- void o6_startScript();
- void o6_startObject();
- void o6_setObjectState();
- void o6_setObjectXY();
- void o6_stopObjectCode();
- void o6_endCutscene();
- void o6_cutScene();
- void o6_stopMusic();
- void o6_freezeUnfreeze();
- void o6_cursorCommand();
- void o6_breakHere();
- void o6_ifClassOfIs();
- void o6_setClass();
- void o6_getState();
- void o6_setState();
- void o6_setOwner();
- void o6_getOwner();
- void o6_startSound();
- void o6_stopSound();
- void o6_startMusic();
- void o6_stopObjectScript();
- void o6_panCameraTo();
- void o6_actorFollowCamera();
- void o6_setCameraAt();
- void o6_loadRoom();
- void o6_stopScript();
- void o6_walkActorToObj();
- void o6_walkActorTo();
- void o6_putActorInRoom();
- void o6_putActorAtObject();
- void o6_faceActor();
- void o6_animateActor();
- void o6_doSentence();
- void o6_pickupObject();
- void o6_loadRoomWithEgo();
- void o6_getRandomNumber();
- void o6_getRandomNumberRange();
- void o6_getActorMoving();
- void o6_isScriptRunning();
- void o6_getActorRoom();
- void o6_getObjectX();
- void o6_getObjectY();
- void o6_getObjectOldDir();
- void o6_getObjectNewDir();
- void o6_getActorWalkBox();
- void o6_getActorCostume();
- void o6_findInventory();
- void o6_getInventoryCount();
- void o6_getVerbFromXY();
- void o6_beginOverride();
- void o6_endOverride();
- void o6_setObjectName();
- void o6_isSoundRunning();
- void o6_setBoxFlags();
- void o6_createBoxMatrix();
- void o6_resourceRoutines();
- void o6_roomOps();
- void o6_actorSet();
- void o6_verbOps();
- void o6_getActorFromXY();
- void o6_findObject();
- void o6_pseudoRoom();
- void o6_getActorElevation();
- void o6_getVerbEntrypoint();
- void o6_arrayOps();
- void o6_saveRestoreVerbs();
- void o6_drawBox();
- void o6_getActorWidth();
- void o6_wait();
- void o6_getActorScaleX();
- void o6_getActorAnimCounter1();
- void o6_soundKludge();
- void o6_isAnyOf();
- void o6_quitPauseRestart();
- void o6_isActorInBox();
- void o6_delay();
- void o6_delayLonger();
- void o6_delayVeryLong();
- void o6_stopSentence();
- void o6_print_0();
- void o6_print_1();
- void o6_print_2();
- void o6_print_3();
- void o6_printActor();
- void o6_printEgo();
- void o6_talkActor();
- void o6_talkEgo();
- void o6_dim();
- void o6_dummy();
- void o6_runVerbCodeQuick();
- void o6_runScriptQuick();
- void o6_dim2();
- void o6_abs();
- void o6_distObjectObject();
- void o6_distObjectPt();
- void o6_distPtPt();
- void o6_miscOps();
- void o6_delayFrames();
- void o6_pickOneOf();
- void o6_pickOneOfDefault();
- void o6_jumpToScript();
- void o6_isRoomScriptRunning();
- void o6_kernelFunction();
- void o6_getAnimateVariable();
- void o6_drawBlastObject();
- void o6_getActorPriority();
- void o6_unknownCD();
- void o6_bor();
- void o6_band();
-};
-
-class Scumm_v7 : public Scumm_v6
-{
-public:
- Scumm_v7(GameDetector *detector, OSystem *syst) : Scumm_v6(detector, syst) {}
-
-protected:
- virtual void setupScummVars();
-};
-
// This is a constant lookup table of reverse bit masks
extern const byte revBitMask[8];
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index 6bfab40d85..79a9b34640 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -27,6 +27,7 @@
#include "debugger.h"
#include "dialogs.h"
#include "imuse.h"
+#include "intern.h"
#include "object.h"
#include "resource.h"
#include "sound.h"
@@ -61,6 +62,8 @@ Engine *Engine_SCUMM_create(GameDetector *detector, OSystem *syst)
engine = new Scumm_v3(detector, syst);
else if (detector->_features & GF_SMALL_HEADER) // this forces loomCD as v4
engine = new Scumm_v4(detector, syst);
+ else if (detector->_features & GF_AFTER_V8)
+ engine = new Scumm_v8(detector, syst);
else if (detector->_features & GF_AFTER_V7)
engine = new Scumm_v7(detector, syst);
else if (detector->_features & GF_AFTER_V6) // this forces SamnmaxCD as v6
diff --git a/scumm/vars.cpp b/scumm/vars.cpp
index 2393ad68dd..481b896fce 100644
--- a/scumm/vars.cpp
+++ b/scumm/vars.cpp
@@ -23,6 +23,7 @@
#include "stdafx.h"
#include "scumm.h"
+#include "intern.h"
void Scumm::setupScummVars()
{