scummvm/scumm/script_c64.cpp
Travis Howell 9d3ee25813 Ooops
svn-id: r18188
2005-05-20 06:39:18 +00:00

681 lines
15 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2001 Ludvig Strigeus
* Copyright (C) 2001-2005 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/actor.h"
#include "scumm/charset.h"
#include "scumm/intern.h"
#include "scumm/object.h"
#include "scumm/scumm.h"
#include "scumm/util.h"
#include "scumm/verbs.h"
namespace Scumm {
#define OPCODE(x) _OPCODE(ScummEngine_c64, x)
void ScummEngine_c64::setupOpcodes() {
static const OpcodeEntryC64 opcodes[256] = {
/* 00 */
OPCODE(o5_stopObjectCode),
OPCODE(o2_putActor),
OPCODE(o5_startMusic),
OPCODE(o5_getActorRoom),
/* 04 */
OPCODE(o_isGreaterEqual),
OPCODE(o_stopScript),
OPCODE(o_getDist),
OPCODE(o5_getActorRoom),
/* 08 */
OPCODE(o_isNotEqual),
OPCODE(o5_faceActor),
OPCODE(o2_assignVarWordIndirect),
OPCODE(o2_setObjPreposition),
/* 0C */
OPCODE(o_loadSound),
OPCODE(o5_walkActorToActor),
OPCODE(o_putActorAtObject),
OPCODE(o2_ifNotState08),
/* 10 */
OPCODE(o5_breakHere),
OPCODE(o2_animateActor),
OPCODE(o2_panCameraTo),
OPCODE(o_unknown13),
/* 14 */
OPCODE(o5_print),
OPCODE(o2_actorFromPos),
OPCODE(o5_getRandomNr),
OPCODE(o_clearState08),
/* 18 */
OPCODE(o5_jumpRelative),
OPCODE(o2_doSentence),
OPCODE(o_move),
OPCODE(o2_setBitVar),
/* 1C */
OPCODE(o5_startSound),
OPCODE(o2_ifClassOfIs),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifState02),
/* 20 */
OPCODE(o5_stopMusic),
OPCODE(o2_putActor),
OPCODE(o5_saveLoadGame),
OPCODE(o2_getActorY),
/* 24 */
OPCODE(o2_loadRoomWithEgo),
OPCODE(o5_loadRoom),
OPCODE(o5_setVarRange),
OPCODE(o2_getActorY),
/* 28 */
OPCODE(o5_equalZero),
OPCODE(o2_setOwnerOf),
OPCODE(o2_delay),
OPCODE(o5_delayVariable),
/* 2C */
OPCODE(o2_assignVarByte),
OPCODE(o5_putActorInRoom),
OPCODE(o2_delay),
OPCODE(o2_ifNotState04),
/* 30 */
OPCODE(o_loadActor),
OPCODE(o2_getBitVar),
OPCODE(o2_setCameraAt),
OPCODE(o_freezeScript),
/* 34 */
OPCODE(o_getDist),
OPCODE(o2_findObject),
OPCODE(o_walkActorToObject),
OPCODE(o2_setState01),
/* 38 */
OPCODE(o_isLessEqual),
OPCODE(o2_doSentence),
OPCODE(o_subtract),
OPCODE(o2_waitForActor),
/* 3C */
OPCODE(o5_stopSound),
OPCODE(o2_setActorElevation),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifState02),
/* 40 */
OPCODE(o2_cutscene),
OPCODE(o2_putActor),
OPCODE(o2_startScript),
OPCODE(o2_getActorX),
/* 44 */
OPCODE(o_isLess),
OPCODE(o2_drawObject),
OPCODE(o_increment),
OPCODE(o2_getActorX),
/* 48 */
OPCODE(o_isEqual),
OPCODE(o5_faceActor),
OPCODE(o_loadRoom),
OPCODE(o2_setObjPreposition),
/* 4C */
OPCODE(o_loadScript),
OPCODE(o_unknown4D),
OPCODE(o_putActorAtObject),
OPCODE(o2_ifState08),
/* 50 */
OPCODE(o2_pickupObject),
OPCODE(o2_animateActor),
OPCODE(o5_actorFollowCamera),
OPCODE(o_unknown53),
/* 54 */
OPCODE(o5_setObjectName),
OPCODE(o2_actorFromPos),
OPCODE(o5_getActorMoving),
OPCODE(o_clearState08),
/* 58 */
OPCODE(o2_beginOverride),
OPCODE(o2_doSentence),
OPCODE(o_add),
OPCODE(o2_setBitVar),
/* 5C */
OPCODE(o5_startSound),
OPCODE(o2_ifClassOfIs),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifNotState02),
/* 60 */
OPCODE(o_cursorCommand),
OPCODE(o2_putActor),
OPCODE(o_stopScript),
OPCODE(o5_getActorFacing),
/* 64 */
OPCODE(o2_loadRoomWithEgo),
OPCODE(o2_drawObject),
OPCODE(o5_getClosestObjActor),
OPCODE(o2_clearState04),
/* 68 */
OPCODE(o5_isScriptRunning),
OPCODE(o2_setOwnerOf),
OPCODE(o2_subIndirect),
OPCODE(o2_dummy),
/* 6C */
OPCODE(o2_getObjPreposition),
OPCODE(o5_putActorInRoom),
OPCODE(o2_dummy),
OPCODE(o2_ifState08),
/* 70 */
OPCODE(o_lights),
OPCODE(o5_getActorCostume),
OPCODE(o5_loadRoom),
OPCODE(o_getObjectOwner),
/* 74 */
OPCODE(o_getDist),
OPCODE(o5_printEgo),
OPCODE(o_walkActorToObject),
OPCODE(o2_clearState01),
/* 78 */
OPCODE(o_isGreater),
OPCODE(o2_doSentence),
OPCODE(o2_verbOps),
OPCODE(o2_getActorWalkBox),
/* 7C */
OPCODE(o5_isSoundRunning),
OPCODE(o2_setActorElevation),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifState01),
/* 80 */
OPCODE(o5_breakHere),
OPCODE(o2_putActor),
OPCODE(o5_startMusic),
OPCODE(o5_getActorRoom),
/* 84 */
OPCODE(o_isGreaterEqual),
OPCODE(o2_drawObject),
OPCODE(o2_getActorElevation),
OPCODE(o5_getActorRoom),
/* 88 */
OPCODE(o_isNotEqual),
OPCODE(o5_faceActor),
OPCODE(o2_assignVarWordIndirect),
OPCODE(o2_setObjPreposition),
/* 8C */
OPCODE(o2_resourceRoutines),
OPCODE(o5_walkActorToActor),
OPCODE(o_putActorAtObject),
OPCODE(o2_ifNotState08),
/* 90 */
OPCODE(o_pickupObject),
OPCODE(o2_animateActor),
OPCODE(o2_panCameraTo),
OPCODE(o_unknown93),
/* 94 */
OPCODE(o5_print),
OPCODE(o2_actorFromPos),
OPCODE(o5_getRandomNr),
OPCODE(o_setState08),
/* 98 */
OPCODE(o2_restart),
OPCODE(o2_doSentence),
OPCODE(o_move),
OPCODE(o2_setBitVar),
/* 9C */
OPCODE(o5_startSound),
OPCODE(o2_ifClassOfIs),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifNotState04),
/* A0 */
OPCODE(o5_stopObjectCode),
OPCODE(o2_putActor),
OPCODE(o5_saveLoadGame),
OPCODE(o2_getActorY),
/* A4 */
OPCODE(o2_loadRoomWithEgo),
OPCODE(o5_loadRoom),
OPCODE(o5_setVarRange),
OPCODE(o2_getActorY),
/* A8 */
OPCODE(o5_notEqualZero),
OPCODE(o2_setOwnerOf),
OPCODE(o2_addIndirect),
OPCODE(o2_switchCostumeSet),
/* AC */
OPCODE(o2_drawSentence),
OPCODE(o5_putActorInRoom),
OPCODE(o2_waitForMessage),
OPCODE(o2_ifNotState08),
/* B0 */
OPCODE(o_loadActor),
OPCODE(o2_getBitVar),
OPCODE(o2_setCameraAt),
OPCODE(o_unfreezeScript),
/* B4 */
OPCODE(o_getDist),
OPCODE(o2_findObject),
OPCODE(o_walkActorToObject),
OPCODE(o2_setState04),
/* B8 */
OPCODE(o_isLessEqual),
OPCODE(o2_doSentence),
OPCODE(o_subtract),
OPCODE(o2_waitForActor),
/* BC */
OPCODE(o5_stopSound),
OPCODE(o2_setActorElevation),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifNotState01),
/* C0 */
OPCODE(o2_endCutscene),
OPCODE(o2_putActor),
OPCODE(o2_startScript),
OPCODE(o2_getActorX),
/* C4 */
OPCODE(o_isLess),
OPCODE(o2_drawObject),
OPCODE(o_decrement),
OPCODE(o2_getActorX),
/* C8 */
OPCODE(o_isEqual),
OPCODE(o5_faceActor),
OPCODE(o_loadRoom),
OPCODE(o2_setObjPreposition),
/* CC */
OPCODE(o_loadScript),
OPCODE(o5_walkActorToActor),
OPCODE(o_putActorAtObject),
OPCODE(o2_ifState08),
/* D0 */
OPCODE(o2_pickupObject),
OPCODE(o2_animateActor),
OPCODE(o5_actorFollowCamera),
OPCODE(o2_actorOps),
/* D4 */
OPCODE(o5_setObjectName),
OPCODE(o2_actorFromPos),
OPCODE(o5_getActorMoving),
OPCODE(o_setState08),
/* D8 */
OPCODE(o5_printEgo),
OPCODE(o2_doSentence),
OPCODE(o_add),
OPCODE(o2_setBitVar),
/* DC */
OPCODE(o5_startSound),
OPCODE(o2_ifClassOfIs),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifNotState04),
/* E0 */
OPCODE(o2_cursorCommand),
OPCODE(o2_putActor),
OPCODE(o_stopScript),
OPCODE(o5_getActorFacing),
/* E4 */
OPCODE(o2_loadRoomWithEgo),
OPCODE(o2_drawObject),
OPCODE(o5_getClosestObjActor),
OPCODE(o2_clearState04),
/* E8 */
OPCODE(o5_isScriptRunning),
OPCODE(o2_setOwnerOf),
OPCODE(o2_subIndirect),
OPCODE(o2_dummy),
/* EC */
OPCODE(o2_getObjPreposition),
OPCODE(o5_putActorInRoom),
OPCODE(o2_dummy),
OPCODE(o2_ifNotState08),
/* F0 */
OPCODE(o_lights),
OPCODE(o5_getActorCostume),
OPCODE(o5_loadRoom),
OPCODE(o_getObjectOwner),
/* F4 */
OPCODE(o_getDist),
OPCODE(o2_findObject),
OPCODE(o_walkActorToObject),
OPCODE(o2_setState04),
/* F8 */
OPCODE(o_isGreater),
OPCODE(o2_doSentence),
OPCODE(o2_verbOps),
OPCODE(o2_getActorWalkBox),
/* FC */
OPCODE(o5_isSoundRunning),
OPCODE(o2_setActorElevation),
OPCODE(o2_walkActorTo),
OPCODE(o2_ifState02)
};
_opcodesC64 = opcodes;
}
#define SENTENCE_SCRIPT 2
#define PARAM_1 0x80
#define PARAM_2 0x40
#define PARAM_3 0x20
void ScummEngine_c64::executeOpcode(byte i) {
OpcodeProcC64 op = _opcodesC64[i].proc;
(this->*op) ();
}
const char *ScummEngine_c64::getOpcodeDesc(byte i) {
return _opcodesC64[i].desc;
}
void ScummEngine_c64::setStateCommon(byte type) {
int obj = fetchScriptByte();
putState(obj, getState(obj) | type);
}
void ScummEngine_c64::clearStateCommon(byte type) {
int obj = fetchScriptByte();
putState(obj, getState(obj) & ~type);
}
void ScummEngine_c64::ifStateCommon(byte type) {
int obj = fetchScriptByte();
if ((getState(obj) & type) == 0)
o5_jumpRelative();
else
ignoreScriptWord();
}
void ScummEngine_c64::ifNotStateCommon(byte type) {
int obj = fetchScriptByte();
if ((getState(obj) & type) != 0)
o5_jumpRelative();
else
ignoreScriptWord();
}
void ScummEngine_c64::o_setState08() {
int obj = getVarOrDirectWord(PARAM_1);
putState(obj, getState(obj) | 0x08);
markObjectRectAsDirty(obj);
clearDrawObjectQueue();
}
void ScummEngine_c64::o_clearState08() {
int obj = getVarOrDirectWord(PARAM_1);
putState(obj, getState(obj) & ~0x08);
markObjectRectAsDirty(obj);
clearDrawObjectQueue();
}
void ScummEngine_c64::o_stopScript() {
int script;
if (_opcode == 0x05) {
script = 0;
} else {
script = getVarOrDirectByte(PARAM_1);
}
if (script == 0)
script = vm.slot[_currentScript].number;
if (_currentScript != 0 && vm.slot[_currentScript].number == script)
stopObjectCode();
else
stopScript(script);
}
void ScummEngine_c64::o_loadSound() {
int resid = fetchScriptByte();
ensureResourceLoaded(rtSound, resid);
}
void ScummEngine_c64::o_move() {
getResultPos();
setResult(getVarOrDirectByte(PARAM_1));
}
void ScummEngine_c64::o_unknown13() {
debug(0, "o_unknown13 (Actor %d)", fetchScriptByte());
}
void ScummEngine_c64::o_loadActor() {
debug(0, "o_loadActor (%d)", getVarOrDirectByte(PARAM_1));
}
void ScummEngine_c64::o_isEqual() {
int16 a, b;
int var;
var = fetchScriptByte();
a = readVar(var);
b = getVarOrDirectByte(PARAM_1);
printf("o_isEqual: a %d b %d\n", a , b);
if (b == a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_isNotEqual() {
int16 a = getVar();
int16 b = getVarOrDirectByte(PARAM_1);
if (b != a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_isGreater() {
uint16 a = getVar();
uint16 b = getVarOrDirectByte(PARAM_1);
if (b > a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_isGreaterEqual() {
uint16 a = getVar();
uint16 b = getVarOrDirectByte(PARAM_1);
if (b >= a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_isLess() {
uint16 a = getVar();
uint16 b = getVarOrDirectByte(PARAM_1);
if (b < a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_isLessEqual() {
uint16 a = getVar();
uint16 b = getVarOrDirectByte(PARAM_1);
if (b <= a)
ignoreScriptWord();
else
o5_jumpRelative();
}
void ScummEngine_c64::o_loadRoom() {
int resid = getVarOrDirectByte(PARAM_1);
ensureResourceLoaded(rtRoom, resid);
}
void ScummEngine_c64::o_unknown4D() {
debug(0, "o_unknown4D (Actor %d)", fetchScriptByte());
}
void ScummEngine_c64::o_loadScript() {
int resid = getVarOrDirectByte(PARAM_1);
ensureResourceLoaded(rtScript, resid);
}
void ScummEngine_c64::o_unknown53() {
debug(0, "o_unknown53 (%d)", fetchScriptByte());
}
void ScummEngine_c64::o_cursorCommand() {
// TODO
byte state = fetchScriptByte();
debug(0, "o_cursorCommand (%d)", state);
if (state >= 1) {
_userPut = 1;
_cursor.state = 1;
} else {
_userPut = 0;
_cursor.state = 0;
}
}
void ScummEngine_c64::o_lights() {
int a;
a = getVarOrDirectByte(PARAM_1);
// Convert older light mode values into
// equivalent values.of later games
// 0 Darkness
// 1 Flashlight
// 2 Lighted area
if (a == 2)
VAR(VAR_CURRENT_LIGHTS) = 11;
else if (a == 1)
VAR(VAR_CURRENT_LIGHTS) = 4;
else
VAR(VAR_CURRENT_LIGHTS) = 0;
_fullRedraw = 1;
}
void ScummEngine_c64::o_getObjectOwner() {
getResultPos();
setResult(getOwner(getVarOrDirectByte(PARAM_1)));
}
void ScummEngine_c64::o_add() {
int a;
getResultPos();
a = getVarOrDirectByte(PARAM_1);
setResult(readVar(_resultVarNumber) + a);
}
void ScummEngine_c64::o_subtract() {
int a;
getResultPos();
a = getVarOrDirectByte(PARAM_1);
_scummVars[_resultVarNumber] -= a;
}
void ScummEngine_c64::o_increment() {
int var = getVarOrDirectByte(PARAM_1);
setResult(readVar(var) + 1);
}
void ScummEngine_c64::o_decrement() {
int var = getVarOrDirectByte(PARAM_1);
setResult(readVar(var) - 1);
}
void ScummEngine_c64::o_unknown93() {
debug(0, "o_unknown93 (Actor %d)", fetchScriptByte());
}
void ScummEngine_c64::o_freezeScript() {
int scr = fetchScriptByte();
vm.slot[scr].status &= 0x80;
vm.slot[scr].freezeCount = 1;
}
void ScummEngine_c64::o_unfreezeScript() {
int scr = fetchScriptByte();
vm.slot[scr].status &= 0x7F;
vm.slot[scr].freezeCount = 0;
}
void ScummEngine_c64::o_getDist() {
int o1, o2;
int r;
getResultPos();
o1 = getVarOrDirectByte(PARAM_1);
o2 = getVarOrDirectByte(PARAM_2);
r = getObjActToObjActDist(o1, o2);
setResult(r);
}
void ScummEngine_c64::o_pickupObject() {
int obj = fetchScriptByte();
if (obj < 1) {
error("pickupObject received invalid index %d (script %d)", obj, vm.slot[_currentScript].number);
}
if (getObjectIndex(obj) == -1)
return;
if (whereIsObject(obj) == WIO_INVENTORY) /* Don't take an */
return; /* object twice */
addObjectToInventory(obj, _roomResource);
markObjectRectAsDirty(obj);
putOwner(obj, VAR(VAR_EGO));
putState(obj, getState(obj) | 0xA);
clearDrawObjectQueue();
runInventoryScript(1);
}
void ScummEngine_c64::o_putActorAtObject() {
int obj, x, y;
Actor *a;
a = derefActor(getVarOrDirectByte(PARAM_1), "o_putActorAtObject");
obj = fetchScriptByte();
if (whereIsObject(obj) != WIO_NOT_FOUND)
getObjectXYPos(obj, x, y);
else {
x = 240;
y = 120;
}
a->putActor(x, y, a->_room);
}
void ScummEngine_c64::o_walkActorToObject() {
int obj;
Actor *a;
a = derefActor(getVarOrDirectByte(PARAM_1), "o_walkActorToObject");
obj = fetchScriptByte();
if (whereIsObject(obj) != WIO_NOT_FOUND) {
int x, y, dir;
getObjectXYPos(obj, x, y, dir);
a->startWalkActor(x, y, dir);
}
}
#undef PARAM_1
#undef PARAM_2
#undef PARAM_3
} // End of namespace Scumm