diff options
| -rw-r--r-- | scumm.dsp | 4 | ||||
| -rw-r--r-- | scumm/intern.h | 66 | ||||
| -rw-r--r-- | scumm/module.mk | 1 | ||||
| -rw-r--r-- | scumm/script_v2.cpp | 569 | 
4 files changed, 630 insertions, 10 deletions
@@ -367,6 +367,10 @@ SOURCE=.\scumm\script.cpp  # End Source File
  # Begin Source File
 +SOURCE=.\scumm\script_v2.cpp
 +# End Source File
 +# Begin Source File
 +
  SOURCE=.\scumm\script_v5.cpp
  # End Source File
  # Begin Source File
 diff --git a/scumm/intern.h b/scumm/intern.h index 6572844138..74cf658a20 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -157,16 +157,6 @@ protected:  	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) {} - -protected: -	void readIndexFile(); -	void readMAXS(); -}; -  // 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 !!! @@ -182,6 +172,62 @@ protected:  	void readGlobalObjects();  }; +class Scumm_v2 : public Scumm_v3 { +public: +	Scumm_v2(GameDetector *detector, OSystem *syst) : Scumm_v3(detector, syst) {} + +protected: +	void readIndexFile(); +	void readMAXS(); +	typedef void (Scumm_v2::*OpcodeProcV2)(); +	struct OpcodeEntryV2 { +		OpcodeProcV2 proc; +		const char *desc; +	}; + +	const OpcodeEntryV2 *_opcodesV2; + +	virtual void setupOpcodes(); +	virtual void executeOpcode(int i); +	virtual const char *getOpcodeDesc(int i); +	virtual void getResultPos(); +	virtual void getResultPosDirect(); +	virtual void ifStateGeneral(byte type); +	virtual void ifNotStateGeneral(byte type); + +	/* Version 2 script opcodes */ +	void o2_setState80(); +	void o2_clearState80(); +	void o2_setState40(); +	void o2_clearState40(); +	void o2_setState20(); +	void o2_clearState20(); +	void o2_setState10(); +	void o2_clearState10(); +	void o2_assignVarByteDirect(); +	void o2_assignVarWordDirect(); +	void o2_assignVarByte(); +	void o2_assignVarWord(); +	void o2_setObjY(); +	void o2_getObjY(); +	void o2_setBitVar(); +	void o2_getBitVar(); +	void o2_addDirect(); +	void o2_subDirect(); +	void o2_ifState80(); +	void o2_ifNotState80(); +	void o2_ifState40(); +	void o2_ifNotState40(); +	void o2_ifState20(); +	void o2_ifNotState20(); +	void o2_ifState10(); +	void o2_ifNotState10(); +	void o2_waitForActor(); +	void o2_waitForSentence(); +	void o2_restart(); + +}; +  class Scumm_v4 : public Scumm_v3 {  public:  	Scumm_v4(GameDetector *detector, OSystem *syst) : Scumm_v3(detector, syst) {} diff --git a/scumm/module.mk b/scumm/module.mk index ba79382644..1e4632e79c 100644 --- a/scumm/module.mk +++ b/scumm/module.mk @@ -21,6 +21,7 @@ SCUMM_OBJS = \  	scumm/resource_v4.o \  	scumm/saveload.o \  	scumm/script.o \ +	scumm/script_v2.o \  	scumm/script_v5.o \  	scumm/script_v6.o \  	scumm/script_v8.o \ diff --git a/scumm/script_v2.cpp b/scumm/script_v2.cpp new file mode 100644 index 0000000000..97c73d8e62 --- /dev/null +++ b/scumm/script_v2.cpp @@ -0,0 +1,569 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001  Ludvig Strigeus + * Copyright (C) 2001-2003 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 "actor.h" +#include "charset.h" +#include "intern.h" +#include "sound.h" +#include "verbs.h" + +#define OPCODE(x)	{ &Scumm_v2::x, #x } + +void Scumm_v2::setupOpcodes() { +	static const OpcodeEntryV2 opcodes[256] = { +		/* 00 */ +		OPCODE(o5_stopObjectCode), +		OPCODE(o5_putActor), +		OPCODE(o5_startMusic), +		OPCODE(o5_getActorRoom), +		/* 04 */ +		OPCODE(o5_isGreaterEqual), +		OPCODE(o5_drawObject), +		OPCODE(o5_getActorElevation), +		OPCODE(o2_setState80), +		/* 08 */ +		OPCODE(o5_isNotEqual), +		OPCODE(o5_faceActor), +		OPCODE(o2_assignVarWordDirect), +		OPCODE(o2_setObjY), +		/* 0C */ +		OPCODE(o5_resourceRoutines), +		OPCODE(o5_walkActorToActor), +		OPCODE(o5_putActorAtObject), +		OPCODE(o5_getObjectState), +		/* 10 */ +		OPCODE(o5_getObjectOwner), +		OPCODE(o5_animateActor), +		OPCODE(o5_panCameraTo), +		OPCODE(o5_actorSet), +		/* 14 */ +		OPCODE(o5_print), +		OPCODE(o5_actorFromPos), +		OPCODE(o5_getRandomNr), +		OPCODE(o2_setState40), +		/* 18 */ +		OPCODE(o5_jumpRelative), +		OPCODE(o5_doSentence), +		OPCODE(o5_move), +		OPCODE(o2_setBitVar), +		/* 1C */ +		OPCODE(o5_startSound), +		OPCODE(o5_ifClassOfIs), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifState20), +		/* 20 */ +		OPCODE(o5_stopMusic), +		OPCODE(o5_putActor), +		OPCODE(o5_getAnimCounter), +		OPCODE(o5_getActorY), +		/* 24 */ +		OPCODE(o5_loadRoomWithEgo), +		OPCODE(o5_pickupObject), +		OPCODE(o5_setVarRange), +		OPCODE(o2_ifNotState40), +		/* 28 */ +		OPCODE(o5_equalZero), +		OPCODE(o5_setOwnerOf), +		OPCODE(o2_addDirect), +		OPCODE(o5_delayVariable), +		/* 2C */ +		OPCODE(o2_ifNotState40), +		OPCODE(o5_putActorInRoom), +		OPCODE(o5_delay), +		OPCODE(o2_assignVarByte), +		/* 30 */ +		OPCODE(o5_matrixOps), +		OPCODE(o2_getBitVar), +		OPCODE(o5_setCameraAt), +		OPCODE(o5_roomOps), +		/* 34 */ +		OPCODE(o5_getDist), +		OPCODE(o5_findObject), +		OPCODE(o5_walkActorToObject), +		OPCODE(o2_setState10), +		/* 38 */ +		OPCODE(o5_lessOrEqual), +		OPCODE(o5_doSentence), +		OPCODE(o5_subtract), +		OPCODE(o2_waitForActor), +		/* 3C */ +		OPCODE(o5_stopSound), +		OPCODE(o5_getActorElevation), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifNotState10), +		/* 40 */ +		OPCODE(o5_cutscene), +		OPCODE(o5_putActor), +		OPCODE(o5_startScript), +		OPCODE(o5_getActorX), +		/* 44 */ +		OPCODE(o5_isLess), +		OPCODE(o5_drawObject), +		OPCODE(o5_increment), +		OPCODE(o2_setState80), +		/* 48 */ +		OPCODE(o5_isEqual), +		OPCODE(o5_faceActor), +		OPCODE(o5_chainScript), +		OPCODE(o2_setObjY), +		/* 4C */ +		OPCODE(o2_waitForSentence), +		OPCODE(o5_walkActorToActor), +		OPCODE(o5_putActorAtObject), +		OPCODE(o2_ifState80), +		/* 50 */ +		OPCODE(o5_pickupObjectOld), +		OPCODE(o5_animateActor), +		OPCODE(o5_actorFollowCamera), +		OPCODE(o5_actorSet), +		/* 54 */ +		OPCODE(o5_setObjectName), +		OPCODE(o5_actorFromPos), +		OPCODE(o5_getActorMoving), +		OPCODE(o2_setState20), +		/* 58 */ +		OPCODE(o5_overRide), +		OPCODE(o5_doSentence), +		OPCODE(o5_add), +		OPCODE(o2_setBitVar), +		/* 5C */ +		OPCODE(o5_oldRoomEffect), +		OPCODE(o5_ifClassOfIs), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifNotState20), +		/* 60 */ +		OPCODE(o5_cursorCommand), +		OPCODE(o5_putActor), +		OPCODE(o5_stopScript), +		OPCODE(o5_getActorFacing), +		/* 64 */ +		OPCODE(o5_loadRoomWithEgo), +		OPCODE(o5_pickupObject), +		OPCODE(o5_getClosestObjActor), +		OPCODE(o2_clearState40), +		/* 68 */ +		OPCODE(o5_isScriptRunning), +		OPCODE(o5_setOwnerOf), +		OPCODE(o2_subDirect), +		OPCODE(o5_dummy), +		/* 6C */ +		OPCODE(o2_getObjY), +		OPCODE(o5_putActorInRoom), +		OPCODE(o5_dummy), +		OPCODE(o2_ifState40), +		/* 70 */ +		OPCODE(o5_lights), +		OPCODE(o5_getActorCostume), +		OPCODE(o5_loadRoom), +		OPCODE(o5_roomOps), +		/* 74 */ +		OPCODE(o5_getDist), +		OPCODE(o5_findObject), +		OPCODE(o5_walkActorToObject), +		OPCODE(o2_clearState10), +		/* 78 */ +		OPCODE(o5_isGreater), +		OPCODE(o5_doSentence), +		OPCODE(o5_verbOps), +		OPCODE(o5_getActorWalkBox), +		/* 7C */ +		OPCODE(o5_isSoundRunning), +		OPCODE(o5_getActorElevation), +		OPCODE(o5_walkActorTo), +		OPCODE(o5_drawBox), +		/* 80 */ +		OPCODE(o5_breakHere), +		OPCODE(o5_putActor), +		OPCODE(o5_startMusic), +		OPCODE(o5_getActorRoom), +		/* 84 */ +		OPCODE(o5_isGreaterEqual), +		OPCODE(o5_drawObject), +		OPCODE(o5_getActorElevation), +		OPCODE(o2_setState80), +		/* 88 */ +		OPCODE(o5_isNotEqual), +		OPCODE(o5_faceActor), +		OPCODE(o2_assignVarWordDirect), +		OPCODE(o2_setObjY), +		/* 8C */ +		OPCODE(o5_resourceRoutines), +		OPCODE(o5_walkActorToActor), +		OPCODE(o5_putActorAtObject), +		OPCODE(o2_ifNotState80), +		/* 90 */ +		OPCODE(o5_getObjectOwner), +		OPCODE(o5_animateActor), +		OPCODE(o5_panCameraTo), +		OPCODE(o5_actorSet), +		/* 94 */ +		OPCODE(o5_print), +		OPCODE(o5_actorFromPos), +		OPCODE(o5_getRandomNr), +		OPCODE(o2_setState20), +		/* 98 */ +		OPCODE(o2_restart), +		OPCODE(o5_doSentence), +		OPCODE(o2_assignVarWord), +		OPCODE(o2_setBitVar), +		/* 9C */ +		OPCODE(o5_startSound), +		OPCODE(o5_ifClassOfIs), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifState20), +		/* A0 */ +		OPCODE(o5_stopObjectCode), +		OPCODE(o5_putActor), +		OPCODE(o5_getAnimCounter), +		OPCODE(o5_getActorY), +		/* A4 */ +		OPCODE(o5_loadRoomWithEgo), +		OPCODE(o5_pickupObject), +		OPCODE(o5_setVarRange), +		OPCODE(o2_setState40), +		/* A8 */ +		OPCODE(o5_notEqualZero), +		OPCODE(o5_setOwnerOf), +		OPCODE(o2_addDirect), +		OPCODE(o5_dummy), +		/* AC */ +		OPCODE(o5_expression), //? +		OPCODE(o5_putActorInRoom), +		OPCODE(o2_waitForSentence), +		OPCODE(o2_ifNotState40), +		/* B0 */ +		OPCODE(o5_matrixOps), +		OPCODE(o2_getBitVar), +		OPCODE(o5_setCameraAt), +		OPCODE(o5_roomOps), +		/* B4 */ +		OPCODE(o5_getDist), +		OPCODE(o5_findObject), +		OPCODE(o5_walkActorToObject), +		OPCODE(o5_startObject), //? +		/* B8 */ +		OPCODE(o5_lessOrEqual), +		OPCODE(o5_doSentence), +		OPCODE(o5_subtract), +		OPCODE(o2_waitForActor), +		/* BC */ +		OPCODE(o5_stopSound), +		OPCODE(o5_getActorElevation), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifNotState10), +		/* C0 */ +		OPCODE(o5_endCutscene), +		OPCODE(o5_putActor), +		OPCODE(o5_startScript), +		OPCODE(o5_getActorX), +		/* C4 */ +		OPCODE(o5_isLess), +		OPCODE(o5_drawObject), +		OPCODE(o5_decrement), +		OPCODE(o2_clearState80), +		/* C8 */ +		OPCODE(o5_isEqual), +		OPCODE(o5_faceActor), +		OPCODE(o5_chainScript), +		OPCODE(o2_setObjY), +		/* CC */ +		OPCODE(o5_pseudoRoom), +		OPCODE(o5_walkActorToActor), +		OPCODE(o5_putActorAtObject), +		OPCODE(o2_ifState80), +		/* D0 */ +		OPCODE(o5_pickupObjectOld), +		OPCODE(o5_animateActor), +		OPCODE(o5_actorFollowCamera), +		OPCODE(o5_actorSet), +		/* D4 */ +		OPCODE(o5_setObjectName), +		OPCODE(o5_actorFromPos), +		OPCODE(o5_getActorMoving), +		OPCODE(o2_setState20), +		/* D8 */ +		OPCODE(o5_printEgo), +		OPCODE(o5_doSentence), +		OPCODE(o5_add), +		OPCODE(o5_divide), +		/* DC */ +		OPCODE(o5_oldRoomEffect), +		OPCODE(o5_ifClassOfIs), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifNotState20), +		/* E0 */ +		OPCODE(o5_cursorCommand), +		OPCODE(o5_putActor), +		OPCODE(o5_stopScript), +		OPCODE(o5_getActorFacing), +		/* E4 */ +		OPCODE(o5_loadRoomWithEgo), +		OPCODE(o5_pickupObject), +		OPCODE(o5_getClosestObjActor), +		OPCODE(o2_clearState40), +		/* E8 */ +		OPCODE(o5_isScriptRunning), +		OPCODE(o5_setOwnerOf), +		OPCODE(o2_subDirect), +		OPCODE(o5_dummy), +		/* EC */ +		OPCODE(o2_getObjY), +		OPCODE(o5_putActorInRoom), +		OPCODE(o5_dummy), +		OPCODE(o2_ifState40), +		/* F0 */ +		OPCODE(o5_lights), +		OPCODE(o5_getActorCostume), +		OPCODE(o5_loadRoom), +		OPCODE(o5_roomOps), +		/* F4 */ +		OPCODE(o5_getDist), +		OPCODE(o5_findObject), +		OPCODE(o5_walkActorToObject), +		OPCODE(o2_clearState10), +		/* F8 */ +		OPCODE(o5_isGreater), +		OPCODE(o5_doSentence), +		OPCODE(o5_verbOps), +		OPCODE(o5_getActorWalkBox), +		/* FC */ +		OPCODE(o5_isSoundRunning), +		OPCODE(o5_getActorElevation), +		OPCODE(o5_walkActorTo), +		OPCODE(o2_ifState10) +	}; + +	_opcodesV2 = opcodes; +} + +void Scumm_v2::executeOpcode(int i) { +	OpcodeProcV2 op = _opcodesV2[i].proc; +	(this->*op) (); +} + +const char *Scumm_v2::getOpcodeDesc(int i) { +	return _opcodesV2[i].desc; +} + +void Scumm_v2::o2_setState80() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) | 0x80); +	removeObjectFromRoom(obj); +	clearDrawObjectQueue(); +} + +void Scumm_v2::o2_clearState80() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) & 0x7f); +	removeObjectFromRoom(obj); +	clearDrawObjectQueue(); +} + +void Scumm_v2::o2_setState40() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) | 0x40); +} + +void Scumm_v2::o2_clearState40() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) & 0x40); +} + +void Scumm_v2::o2_setState20() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) | 0x20); +} + +void Scumm_v2::o2_clearState20() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) & 0x20); +} + +void Scumm_v2::o2_setState10() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) | 0x10); +} + +void Scumm_v2::o2_clearState10() { +	int obj = getVarOrDirectWord(0x80); +	putState(obj, getState(obj) & 0x10); +} + +void Scumm_v2::getResultPos() { +	_resultVarNumber = fetchScriptByte(); +} + +void Scumm_v2::getResultPosDirect() { +	_resultVarNumber = _vars[fetchScriptByte()]; +} + +void Scumm_v2::o2_assignVarWordDirect() { +	getResultPosDirect(); +	_vars[_resultVarNumber] = fetchScriptWord(); +} + +void Scumm_v2::o2_assignVarByteDirect() { +	getResultPosDirect(); +	_vars[_resultVarNumber] = fetchScriptByte(); +} + +void Scumm_v2::o2_assignVarByte() { +	getResultPos(); +	_vars[_resultVarNumber] = fetchScriptByte(); +} + +void Scumm_v2::o2_setObjY() { +	int obj = getVarOrDirectWord(0x80); +	int y = fetchScriptByte(); + +	if (whereIsObject(obj) != WIO_NOT_FOUND) { +		ObjectData *od = &_objs[getObjectIndex(obj)]; +		od->walk_y = y; +	} +} + +void Scumm_v2::o2_getObjY() { +	int obj = getVarOrDirectWord(0x80); + +	if (whereIsObject(obj) != WIO_NOT_FOUND) { +		ObjectData *od = &_objs[getObjectIndex(obj)]; +		_vars[_resultVarNumber] = od->walk_y; +	} else { +		_vars[_resultVarNumber] = 0xFF; +	} +} + +void Scumm_v2::o2_setBitVar() { +	byte hi = fetchScriptByte(); +	byte lo = fetchScriptByte(); +	byte a = getVarOrDirectByte(0x80); + +	int bit_var = (hi << 8) + lo + a; +	int bit_offset = bit_var & 0x0f; +  bit_var >>= 4; + +	if (getVarOrDirectByte(0x80)) +		_bitVars[bit_var >> 3] |= (1 << bit_offset); +	else +		_bitVars[bit_var >> 3] &= ~(1 << bit_offset); +} + +void Scumm_v2::o2_getBitVar() { +	getResultPos(); +	byte hi = fetchScriptByte(); +	byte lo = fetchScriptByte(); +	byte a = getVarOrDirectByte(0x80); + +	int bit_var = (hi << 8) + lo + a; +	int bit_offset = bit_var & 0x0f; +  bit_var >>= 4; + +	_vars[_resultVarNumber] = (_bitVars[bit_var >> 3] & (1 << bit_offset)) ? 1 : 0; +} + +void Scumm_v2::ifStateGeneral(byte type) { +	int obj = getVarOrDirectWord(0x80); + +	if ((getState(obj) & type) == 0) +		o5_jumpRelative(); +	else +		ignoreScriptWord(); +} + +void Scumm_v2::ifNotStateGeneral(byte type) { +	int obj = getVarOrDirectWord(0x80); + +	if ((getState(obj) & type) != 0) +		o5_jumpRelative(); +	else +		ignoreScriptWord(); +} + +void Scumm_v2::o2_ifState80() { +	ifStateGeneral(0x80); +} + +void Scumm_v2::o2_ifNotState80() { +	ifNotStateGeneral(0x80); +} + +void Scumm_v2::o2_ifState40() { +	ifStateGeneral(0x40); +} + +void Scumm_v2::o2_ifNotState40() { +	ifNotStateGeneral(0x40); +} + +void Scumm_v2::o2_ifState20() { +	ifStateGeneral(0x20); +} + +void Scumm_v2::o2_ifNotState20() { +	ifNotStateGeneral(0x20); +} + +void Scumm_v2::o2_ifState10() { +	ifStateGeneral(0x10); +} + +void Scumm_v2::o2_ifNotState10() { +	ifNotStateGeneral(0x10); +} + +void Scumm_v2::o2_addDirect() { +	int a; +	getResultPosDirect(); +	a = getVarOrDirectWord(0x80); +	setResult(readVar(_resultVarNumber) + a); +} + +void Scumm_v2::o2_subDirect() { +	int a; +	getResultPosDirect(); +	a = getVarOrDirectWord(0x80); +	setResult(readVar(_resultVarNumber) - a); +} + +void Scumm_v2::o2_waitForActor() { +	byte *oldaddr = _scriptPointer - 1; +	if (derefActorSafe(getVarOrDirectByte(0x80), "o5_wait")->moving) { +		_scriptPointer = oldaddr; +		o5_breakHere(); +	} +} + +void Scumm_v2::o2_waitForSentence() { +	if (_sentenceNum) { +		if (_sentence[_sentenceNum - 1].freezeCount && !isScriptInUse(_vars[VAR_SENTENCE_SCRIPT])) +			return; +	} else if (!isScriptInUse(_vars[VAR_SENTENCE_SCRIPT])) +		return; + +	_scriptPointer--; +	o5_breakHere(); +} + +void Scumm_v2::o2_restart() { +}  | 
