2007-05-30 21:56:52 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
2003-04-20 16:04:50 +00:00
|
|
|
*
|
|
|
|
* 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
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2003-04-20 16:04:50 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2003-09-11 10:32:15 +00:00
|
|
|
#include "scumm/actor.h"
|
|
|
|
#include "scumm/charset.h"
|
|
|
|
#include "scumm/object.h"
|
2011-05-11 14:03:50 +00:00
|
|
|
#include "scumm/resource.h"
|
2009-03-20 16:33:58 +00:00
|
|
|
#include "scumm/scumm_v2.h"
|
2003-09-11 10:32:15 +00:00
|
|
|
#include "scumm/sound.h"
|
2005-04-10 12:59:17 +00:00
|
|
|
#include "scumm/util.h"
|
2003-09-11 10:32:15 +00:00
|
|
|
#include "scumm/verbs.h"
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-10-03 18:33:57 +00:00
|
|
|
namespace Scumm {
|
|
|
|
|
2009-04-16 09:26:37 +00:00
|
|
|
#define OPCODE(i, x) _opcodes[i]._OPCODE(ScummEngine_v2, x)
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::setupOpcodes() {
|
2009-04-16 09:26:37 +00:00
|
|
|
/* 00 */
|
|
|
|
OPCODE(0x00, o5_stopObjectCode);
|
|
|
|
OPCODE(0x01, o2_putActor);
|
|
|
|
OPCODE(0x02, o5_startMusic);
|
|
|
|
OPCODE(0x03, o5_getActorRoom);
|
|
|
|
/* 04 */
|
|
|
|
OPCODE(0x04, o2_isGreaterEqual);
|
|
|
|
OPCODE(0x05, o2_drawObject);
|
|
|
|
OPCODE(0x06, o2_getActorElevation);
|
|
|
|
OPCODE(0x07, o2_setState08);
|
|
|
|
/* 08 */
|
|
|
|
OPCODE(0x08, o5_isNotEqual);
|
|
|
|
OPCODE(0x09, o5_faceActor);
|
|
|
|
OPCODE(0x0a, o2_assignVarWordIndirect);
|
|
|
|
OPCODE(0x0b, o2_setObjPreposition);
|
|
|
|
/* 0C */
|
|
|
|
OPCODE(0x0c, o2_resourceRoutines);
|
|
|
|
OPCODE(0x0d, o5_walkActorToActor);
|
|
|
|
OPCODE(0x0e, o2_putActorAtObject);
|
|
|
|
OPCODE(0x0f, o2_ifNotState08);
|
|
|
|
/* 10 */
|
|
|
|
OPCODE(0x10, o5_getObjectOwner);
|
|
|
|
OPCODE(0x11, o5_animateActor);
|
|
|
|
OPCODE(0x12, o2_panCameraTo);
|
|
|
|
OPCODE(0x13, o2_actorOps);
|
|
|
|
/* 14 */
|
|
|
|
OPCODE(0x14, o5_print);
|
|
|
|
OPCODE(0x15, o2_actorFromPos);
|
|
|
|
OPCODE(0x16, o5_getRandomNr);
|
|
|
|
OPCODE(0x17, o2_clearState02);
|
|
|
|
/* 18 */
|
|
|
|
OPCODE(0x18, o5_jumpRelative);
|
|
|
|
OPCODE(0x19, o2_doSentence);
|
|
|
|
OPCODE(0x1a, o5_move);
|
|
|
|
OPCODE(0x1b, o2_setBitVar);
|
|
|
|
/* 1C */
|
|
|
|
OPCODE(0x1c, o5_startSound);
|
|
|
|
OPCODE(0x1d, o2_ifClassOfIs);
|
|
|
|
OPCODE(0x1e, o2_walkActorTo);
|
|
|
|
OPCODE(0x1f, o2_ifState02);
|
|
|
|
/* 20 */
|
|
|
|
OPCODE(0x20, o5_stopMusic);
|
|
|
|
OPCODE(0x21, o2_putActor);
|
2009-04-19 01:01:54 +00:00
|
|
|
OPCODE(0x22, o4_saveLoadGame);
|
2009-04-16 09:26:37 +00:00
|
|
|
OPCODE(0x23, o2_getActorY);
|
|
|
|
/* 24 */
|
|
|
|
OPCODE(0x24, o2_loadRoomWithEgo);
|
|
|
|
OPCODE(0x25, o2_drawObject);
|
|
|
|
OPCODE(0x26, o5_setVarRange);
|
|
|
|
OPCODE(0x27, o2_setState04);
|
|
|
|
/* 28 */
|
|
|
|
OPCODE(0x28, o5_equalZero);
|
|
|
|
OPCODE(0x29, o2_setOwnerOf);
|
|
|
|
OPCODE(0x2a, o2_addIndirect);
|
|
|
|
OPCODE(0x2b, o5_delayVariable);
|
|
|
|
/* 2C */
|
|
|
|
OPCODE(0x2c, o2_assignVarByte);
|
|
|
|
OPCODE(0x2d, o2_putActorInRoom);
|
|
|
|
OPCODE(0x2e, o2_delay);
|
|
|
|
OPCODE(0x2f, o2_ifNotState04);
|
|
|
|
/* 30 */
|
2009-04-19 01:00:31 +00:00
|
|
|
OPCODE(0x30, o3_setBoxFlags);
|
2009-04-16 09:26:37 +00:00
|
|
|
OPCODE(0x31, o2_getBitVar);
|
|
|
|
OPCODE(0x32, o2_setCameraAt);
|
|
|
|
OPCODE(0x33, o2_roomOps);
|
|
|
|
/* 34 */
|
|
|
|
OPCODE(0x34, o5_getDist);
|
|
|
|
OPCODE(0x35, o2_findObject);
|
|
|
|
OPCODE(0x36, o2_walkActorToObject);
|
|
|
|
OPCODE(0x37, o2_setState01);
|
|
|
|
/* 38 */
|
|
|
|
OPCODE(0x38, o2_isLessEqual);
|
|
|
|
OPCODE(0x39, o2_doSentence);
|
|
|
|
OPCODE(0x3a, o2_subtract);
|
|
|
|
OPCODE(0x3b, o2_waitForActor);
|
|
|
|
/* 3C */
|
|
|
|
OPCODE(0x3c, o5_stopSound);
|
|
|
|
OPCODE(0x3d, o2_setActorElevation);
|
|
|
|
OPCODE(0x3e, o2_walkActorTo);
|
|
|
|
OPCODE(0x3f, o2_ifNotState01);
|
|
|
|
/* 40 */
|
|
|
|
OPCODE(0x40, o2_cutscene);
|
|
|
|
OPCODE(0x41, o2_putActor);
|
|
|
|
OPCODE(0x42, o2_startScript);
|
|
|
|
OPCODE(0x43, o2_getActorX);
|
|
|
|
/* 44 */
|
|
|
|
OPCODE(0x44, o2_isLess);
|
|
|
|
OPCODE(0x45, o2_drawObject);
|
|
|
|
OPCODE(0x46, o5_increment);
|
|
|
|
OPCODE(0x47, o2_clearState08);
|
|
|
|
/* 48 */
|
|
|
|
OPCODE(0x48, o5_isEqual);
|
|
|
|
OPCODE(0x49, o5_faceActor);
|
|
|
|
OPCODE(0x4a, o2_chainScript);
|
|
|
|
OPCODE(0x4b, o2_setObjPreposition);
|
|
|
|
/* 4C */
|
|
|
|
OPCODE(0x4c, o2_waitForSentence);
|
|
|
|
OPCODE(0x4d, o5_walkActorToActor);
|
|
|
|
OPCODE(0x4e, o2_putActorAtObject);
|
|
|
|
OPCODE(0x4f, o2_ifState08);
|
|
|
|
/* 50 */
|
|
|
|
OPCODE(0x50, o2_pickupObject);
|
|
|
|
OPCODE(0x51, o5_animateActor);
|
|
|
|
OPCODE(0x52, o5_actorFollowCamera);
|
|
|
|
OPCODE(0x53, o2_actorOps);
|
|
|
|
/* 54 */
|
|
|
|
OPCODE(0x54, o5_setObjectName);
|
|
|
|
OPCODE(0x55, o2_actorFromPos);
|
|
|
|
OPCODE(0x56, o5_getActorMoving);
|
|
|
|
OPCODE(0x57, o2_setState02);
|
|
|
|
/* 58 */
|
|
|
|
OPCODE(0x58, o2_beginOverride);
|
|
|
|
OPCODE(0x59, o2_doSentence);
|
|
|
|
OPCODE(0x5a, o2_add);
|
|
|
|
OPCODE(0x5b, o2_setBitVar);
|
|
|
|
/* 5C */
|
|
|
|
OPCODE(0x5c, o2_dummy);
|
|
|
|
OPCODE(0x5d, o2_ifClassOfIs);
|
|
|
|
OPCODE(0x5e, o2_walkActorTo);
|
|
|
|
OPCODE(0x5f, o2_ifNotState02);
|
|
|
|
/* 60 */
|
|
|
|
OPCODE(0x60, o2_cursorCommand);
|
|
|
|
OPCODE(0x61, o2_putActor);
|
|
|
|
OPCODE(0x62, o2_stopScript);
|
|
|
|
OPCODE(0x63, o5_getActorFacing);
|
|
|
|
/* 64 */
|
|
|
|
OPCODE(0x64, o2_loadRoomWithEgo);
|
|
|
|
OPCODE(0x65, o2_drawObject);
|
|
|
|
OPCODE(0x66, o5_getClosestObjActor);
|
|
|
|
OPCODE(0x67, o2_clearState04);
|
|
|
|
/* 68 */
|
|
|
|
OPCODE(0x68, o5_isScriptRunning);
|
|
|
|
OPCODE(0x69, o2_setOwnerOf);
|
|
|
|
OPCODE(0x6a, o2_subIndirect);
|
|
|
|
OPCODE(0x6b, o2_dummy);
|
|
|
|
/* 6C */
|
|
|
|
OPCODE(0x6c, o2_getObjPreposition);
|
|
|
|
OPCODE(0x6d, o2_putActorInRoom);
|
|
|
|
OPCODE(0x6e, o2_dummy);
|
|
|
|
OPCODE(0x6f, o2_ifState04);
|
|
|
|
/* 70 */
|
|
|
|
OPCODE(0x70, o2_lights);
|
|
|
|
OPCODE(0x71, o5_getActorCostume);
|
|
|
|
OPCODE(0x72, o5_loadRoom);
|
|
|
|
OPCODE(0x73, o2_roomOps);
|
|
|
|
/* 74 */
|
|
|
|
OPCODE(0x74, o5_getDist);
|
|
|
|
OPCODE(0x75, o2_findObject);
|
|
|
|
OPCODE(0x76, o2_walkActorToObject);
|
|
|
|
OPCODE(0x77, o2_clearState01);
|
|
|
|
/* 78 */
|
|
|
|
OPCODE(0x78, o2_isGreater);
|
|
|
|
OPCODE(0x79, o2_doSentence);
|
|
|
|
OPCODE(0x7a, o2_verbOps);
|
|
|
|
OPCODE(0x7b, o2_getActorWalkBox);
|
|
|
|
/* 7C */
|
|
|
|
OPCODE(0x7c, o5_isSoundRunning);
|
|
|
|
OPCODE(0x7d, o2_setActorElevation);
|
|
|
|
OPCODE(0x7e, o2_walkActorTo);
|
|
|
|
OPCODE(0x7f, o2_ifState01);
|
|
|
|
/* 80 */
|
|
|
|
OPCODE(0x80, o5_breakHere);
|
|
|
|
OPCODE(0x81, o2_putActor);
|
|
|
|
OPCODE(0x82, o5_startMusic);
|
|
|
|
OPCODE(0x83, o5_getActorRoom);
|
|
|
|
/* 84 */
|
|
|
|
OPCODE(0x84, o2_isGreaterEqual);
|
|
|
|
OPCODE(0x85, o2_drawObject);
|
|
|
|
OPCODE(0x86, o2_getActorElevation);
|
|
|
|
OPCODE(0x87, o2_setState08);
|
|
|
|
/* 88 */
|
|
|
|
OPCODE(0x88, o5_isNotEqual);
|
|
|
|
OPCODE(0x89, o5_faceActor);
|
|
|
|
OPCODE(0x8a, o2_assignVarWordIndirect);
|
|
|
|
OPCODE(0x8b, o2_setObjPreposition);
|
|
|
|
/* 8C */
|
|
|
|
OPCODE(0x8c, o2_resourceRoutines);
|
|
|
|
OPCODE(0x8d, o5_walkActorToActor);
|
|
|
|
OPCODE(0x8e, o2_putActorAtObject);
|
|
|
|
OPCODE(0x8f, o2_ifNotState08);
|
|
|
|
/* 90 */
|
|
|
|
OPCODE(0x90, o5_getObjectOwner);
|
|
|
|
OPCODE(0x91, o5_animateActor);
|
|
|
|
OPCODE(0x92, o2_panCameraTo);
|
|
|
|
OPCODE(0x93, o2_actorOps);
|
|
|
|
/* 94 */
|
|
|
|
OPCODE(0x94, o5_print);
|
|
|
|
OPCODE(0x95, o2_actorFromPos);
|
|
|
|
OPCODE(0x96, o5_getRandomNr);
|
|
|
|
OPCODE(0x97, o2_clearState02);
|
|
|
|
/* 98 */
|
|
|
|
OPCODE(0x98, o2_restart);
|
|
|
|
OPCODE(0x99, o2_doSentence);
|
|
|
|
OPCODE(0x9a, o5_move);
|
|
|
|
OPCODE(0x9b, o2_setBitVar);
|
|
|
|
/* 9C */
|
|
|
|
OPCODE(0x9c, o5_startSound);
|
|
|
|
OPCODE(0x9d, o2_ifClassOfIs);
|
|
|
|
OPCODE(0x9e, o2_walkActorTo);
|
|
|
|
OPCODE(0x9f, o2_ifState02);
|
|
|
|
/* A0 */
|
|
|
|
OPCODE(0xa0, o5_stopObjectCode);
|
|
|
|
OPCODE(0xa1, o2_putActor);
|
2009-04-19 01:01:54 +00:00
|
|
|
OPCODE(0xa2, o4_saveLoadGame);
|
2009-04-16 09:26:37 +00:00
|
|
|
OPCODE(0xa3, o2_getActorY);
|
|
|
|
/* A4 */
|
|
|
|
OPCODE(0xa4, o2_loadRoomWithEgo);
|
|
|
|
OPCODE(0xa5, o2_drawObject);
|
|
|
|
OPCODE(0xa6, o5_setVarRange);
|
|
|
|
OPCODE(0xa7, o2_setState04);
|
|
|
|
/* A8 */
|
|
|
|
OPCODE(0xa8, o5_notEqualZero);
|
|
|
|
OPCODE(0xa9, o2_setOwnerOf);
|
|
|
|
OPCODE(0xaa, o2_addIndirect);
|
|
|
|
OPCODE(0xab, o2_switchCostumeSet);
|
|
|
|
/* AC */
|
|
|
|
OPCODE(0xac, o2_drawSentence);
|
|
|
|
OPCODE(0xad, o2_putActorInRoom);
|
|
|
|
OPCODE(0xae, o2_waitForMessage);
|
|
|
|
OPCODE(0xaf, o2_ifNotState04);
|
|
|
|
/* B0 */
|
2009-04-19 01:00:31 +00:00
|
|
|
OPCODE(0xb0, o3_setBoxFlags);
|
2009-04-16 09:26:37 +00:00
|
|
|
OPCODE(0xb1, o2_getBitVar);
|
|
|
|
OPCODE(0xb2, o2_setCameraAt);
|
|
|
|
OPCODE(0xb3, o2_roomOps);
|
|
|
|
/* B4 */
|
|
|
|
OPCODE(0xb4, o5_getDist);
|
|
|
|
OPCODE(0xb5, o2_findObject);
|
|
|
|
OPCODE(0xb6, o2_walkActorToObject);
|
|
|
|
OPCODE(0xb7, o2_setState01);
|
|
|
|
/* B8 */
|
|
|
|
OPCODE(0xb8, o2_isLessEqual);
|
|
|
|
OPCODE(0xb9, o2_doSentence);
|
|
|
|
OPCODE(0xba, o2_subtract);
|
|
|
|
OPCODE(0xbb, o2_waitForActor);
|
|
|
|
/* BC */
|
|
|
|
OPCODE(0xbc, o5_stopSound);
|
|
|
|
OPCODE(0xbd, o2_setActorElevation);
|
|
|
|
OPCODE(0xbe, o2_walkActorTo);
|
|
|
|
OPCODE(0xbf, o2_ifNotState01);
|
|
|
|
/* C0 */
|
|
|
|
OPCODE(0xc0, o2_endCutscene);
|
|
|
|
OPCODE(0xc1, o2_putActor);
|
|
|
|
OPCODE(0xc2, o2_startScript);
|
|
|
|
OPCODE(0xc3, o2_getActorX);
|
|
|
|
/* C4 */
|
|
|
|
OPCODE(0xc4, o2_isLess);
|
|
|
|
OPCODE(0xc5, o2_drawObject);
|
|
|
|
OPCODE(0xc6, o5_decrement);
|
|
|
|
OPCODE(0xc7, o2_clearState08);
|
|
|
|
/* C8 */
|
|
|
|
OPCODE(0xc8, o5_isEqual);
|
|
|
|
OPCODE(0xc9, o5_faceActor);
|
|
|
|
OPCODE(0xca, o2_chainScript);
|
|
|
|
OPCODE(0xcb, o2_setObjPreposition);
|
|
|
|
/* CC */
|
|
|
|
OPCODE(0xcc, o5_pseudoRoom);
|
|
|
|
OPCODE(0xcd, o5_walkActorToActor);
|
|
|
|
OPCODE(0xce, o2_putActorAtObject);
|
|
|
|
OPCODE(0xcf, o2_ifState08);
|
|
|
|
/* D0 */
|
|
|
|
OPCODE(0xd0, o2_pickupObject);
|
|
|
|
OPCODE(0xd1, o5_animateActor);
|
|
|
|
OPCODE(0xd2, o5_actorFollowCamera);
|
|
|
|
OPCODE(0xd3, o2_actorOps);
|
|
|
|
/* D4 */
|
|
|
|
OPCODE(0xd4, o5_setObjectName);
|
|
|
|
OPCODE(0xd5, o2_actorFromPos);
|
|
|
|
OPCODE(0xd6, o5_getActorMoving);
|
|
|
|
OPCODE(0xd7, o2_setState02);
|
|
|
|
/* D8 */
|
|
|
|
OPCODE(0xd8, o5_printEgo);
|
|
|
|
OPCODE(0xd9, o2_doSentence);
|
|
|
|
OPCODE(0xda, o2_add);
|
|
|
|
OPCODE(0xdb, o2_setBitVar);
|
|
|
|
/* DC */
|
|
|
|
OPCODE(0xdc, o2_dummy);
|
|
|
|
OPCODE(0xdd, o2_ifClassOfIs);
|
|
|
|
OPCODE(0xde, o2_walkActorTo);
|
|
|
|
OPCODE(0xdf, o2_ifNotState02);
|
|
|
|
/* E0 */
|
|
|
|
OPCODE(0xe0, o2_cursorCommand);
|
|
|
|
OPCODE(0xe1, o2_putActor);
|
|
|
|
OPCODE(0xe2, o2_stopScript);
|
|
|
|
OPCODE(0xe3, o5_getActorFacing);
|
|
|
|
/* E4 */
|
|
|
|
OPCODE(0xe4, o2_loadRoomWithEgo);
|
|
|
|
OPCODE(0xe5, o2_drawObject);
|
|
|
|
OPCODE(0xe6, o5_getClosestObjActor);
|
|
|
|
OPCODE(0xe7, o2_clearState04);
|
|
|
|
/* E8 */
|
|
|
|
OPCODE(0xe8, o5_isScriptRunning);
|
|
|
|
OPCODE(0xe9, o2_setOwnerOf);
|
|
|
|
OPCODE(0xea, o2_subIndirect);
|
|
|
|
OPCODE(0xeb, o2_dummy);
|
|
|
|
/* EC */
|
|
|
|
OPCODE(0xec, o2_getObjPreposition);
|
|
|
|
OPCODE(0xed, o2_putActorInRoom);
|
|
|
|
OPCODE(0xee, o2_dummy);
|
|
|
|
OPCODE(0xef, o2_ifState04);
|
|
|
|
/* F0 */
|
|
|
|
OPCODE(0xf0, o2_lights);
|
|
|
|
OPCODE(0xf1, o5_getActorCostume);
|
|
|
|
OPCODE(0xf2, o5_loadRoom);
|
|
|
|
OPCODE(0xf3, o2_roomOps);
|
|
|
|
/* F4 */
|
|
|
|
OPCODE(0xf4, o5_getDist);
|
|
|
|
OPCODE(0xf5, o2_findObject);
|
|
|
|
OPCODE(0xf6, o2_walkActorToObject);
|
|
|
|
OPCODE(0xf7, o2_clearState01);
|
|
|
|
/* F8 */
|
|
|
|
OPCODE(0xf8, o2_isGreater);
|
|
|
|
OPCODE(0xf9, o2_doSentence);
|
|
|
|
OPCODE(0xfa, o2_verbOps);
|
|
|
|
OPCODE(0xfb, o2_getActorWalkBox);
|
|
|
|
/* FC */
|
|
|
|
OPCODE(0xfc, o5_isSoundRunning);
|
|
|
|
OPCODE(0xfd, o2_setActorElevation);
|
|
|
|
OPCODE(0xfe, o2_walkActorTo);
|
|
|
|
OPCODE(0xff, o2_ifState01);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-05-16 01:56:06 +00:00
|
|
|
#define SENTENCE_SCRIPT 2
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
int ScummEngine_v2::getVar() {
|
2003-05-05 09:19:15 +00:00
|
|
|
return readVar(fetchScriptByte());
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::decodeParseString() {
|
2003-08-16 08:55:29 +00:00
|
|
|
byte buffer[512];
|
2003-05-04 02:10:49 +00:00
|
|
|
byte *ptr = buffer;
|
|
|
|
byte c;
|
2003-05-14 14:22:15 +00:00
|
|
|
bool insertSpace = false;
|
|
|
|
|
2003-05-04 02:10:49 +00:00
|
|
|
while ((c = fetchScriptByte())) {
|
2003-05-14 14:22:15 +00:00
|
|
|
|
|
|
|
insertSpace = (c & 0x80) != 0;
|
|
|
|
c &= 0x7f;
|
|
|
|
|
|
|
|
if (c < 8) {
|
2003-05-04 02:10:49 +00:00
|
|
|
// Special codes as seen in CHARSET_1 etc. My guess is that they
|
|
|
|
// have a similar function as the corresponding embedded stuff in modern
|
|
|
|
// games. Hence for now we convert them to the modern format.
|
|
|
|
// This might allow us to reuse the existing code.
|
|
|
|
*ptr++ = 0xFF;
|
|
|
|
*ptr++ = c;
|
|
|
|
if (c > 3) {
|
|
|
|
*ptr++ = fetchScriptByte();
|
2003-05-22 14:22:35 +00:00
|
|
|
*ptr++ = 0;
|
2003-05-04 02:10:49 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
*ptr++ = c;
|
2003-05-14 14:22:15 +00:00
|
|
|
|
|
|
|
if (insertSpace)
|
|
|
|
*ptr++ = ' ';
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-05-04 02:10:49 +00:00
|
|
|
}
|
|
|
|
*ptr = 0;
|
|
|
|
|
2003-05-14 13:32:43 +00:00
|
|
|
int textSlot = 0;
|
2003-05-14 13:30:52 +00:00
|
|
|
_string[textSlot].xpos = 0;
|
|
|
|
_string[textSlot].ypos = 0;
|
2006-05-14 10:40:06 +00:00
|
|
|
_string[textSlot].right = _screenWidth - 1;
|
2003-05-14 13:30:52 +00:00
|
|
|
_string[textSlot].center = false;
|
|
|
|
_string[textSlot].overhead = false;
|
2003-08-16 05:45:19 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_MANIAC && _actorToPrintStrFor == 0xFF) {
|
2012-02-04 17:34:08 +00:00
|
|
|
if (_game.version == 0) {
|
2005-05-19 01:54:37 +00:00
|
|
|
_string[textSlot].color = 14;
|
2006-04-23 00:08:18 +00:00
|
|
|
} else if (_game.features & GF_DEMO) {
|
2006-02-20 16:51:30 +00:00
|
|
|
_string[textSlot].color = (_game.version == 2) ? 15 : 1;
|
2005-05-19 01:54:37 +00:00
|
|
|
}
|
2004-03-03 03:14:22 +00:00
|
|
|
}
|
2003-05-14 13:30:52 +00:00
|
|
|
|
2004-03-15 03:09:48 +00:00
|
|
|
actorTalk(buffer);
|
2003-05-04 02:10:49 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
int ScummEngine_v2::readVar(uint var) {
|
2012-01-29 05:20:16 +00:00
|
|
|
if (_game.version >= 1 && var >= 14 && var <= 16)
|
2003-05-08 15:48:50 +00:00
|
|
|
var = _scummVars[var];
|
2003-05-04 02:10:49 +00:00
|
|
|
|
2006-09-16 13:38:43 +00:00
|
|
|
assertRange(0, var, _numVariables - 1, "variable (reading)");
|
2004-08-22 09:30:08 +00:00
|
|
|
debugC(DEBUG_VARS, "readvar(%d) = %d", var, _scummVars[var]);
|
2003-05-08 15:48:50 +00:00
|
|
|
return _scummVars[var];
|
2003-05-04 02:10:49 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::writeVar(uint var, int value) {
|
2006-09-16 13:38:43 +00:00
|
|
|
assertRange(0, var, _numVariables - 1, "variable (writing)");
|
2004-08-22 09:30:08 +00:00
|
|
|
debugC(DEBUG_VARS, "writeVar(%d) = %d", var, value);
|
2004-03-13 12:55:40 +00:00
|
|
|
|
2005-11-20 09:10:18 +00:00
|
|
|
if (VAR_CUTSCENEEXIT_KEY != 0xFF && var == VAR_CUTSCENEEXIT_KEY) {
|
|
|
|
// Remap the cutscene exit key in earlier games
|
|
|
|
if (value == 4 || value == 13 || value == 64)
|
|
|
|
value = 27;
|
|
|
|
}
|
|
|
|
|
2003-05-21 14:25:14 +00:00
|
|
|
_scummVars[var] = value;
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::getResultPosIndirect() {
|
2003-05-08 15:48:50 +00:00
|
|
|
_resultVarNumber = _scummVars[fetchScriptByte()];
|
2003-05-04 02:27:22 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::getResultPos() {
|
2003-05-04 02:27:22 +00:00
|
|
|
_resultVarNumber = fetchScriptByte();
|
|
|
|
}
|
|
|
|
|
2009-04-20 12:35:17 +00:00
|
|
|
int ScummEngine_v2::getActiveObject() {
|
|
|
|
return getVarOrDirectWord(PARAM_1);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::setStateCommon(byte type) {
|
2009-04-20 12:35:17 +00:00
|
|
|
int obj = getActiveObject();
|
2003-04-21 08:50:16 +00:00
|
|
|
putState(obj, getState(obj) | type);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::clearStateCommon(byte type) {
|
2009-04-20 12:35:17 +00:00
|
|
|
int obj = getActiveObject();
|
2003-04-21 12:31:08 +00:00
|
|
|
putState(obj, getState(obj) & ~type);
|
2003-04-21 08:50:16 +00:00
|
|
|
}
|
|
|
|
|
2009-04-20 12:35:17 +00:00
|
|
|
void ScummEngine_v2::ifStateCommon(byte type) {
|
|
|
|
int obj = getActiveObject();
|
|
|
|
|
|
|
|
jumpRelative((getState(obj) & type) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v2::ifNotStateCommon(byte type) {
|
|
|
|
int obj = getActiveObject();
|
|
|
|
|
|
|
|
jumpRelative((getState(obj) & type) == 0);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setState08() {
|
2009-04-20 12:35:17 +00:00
|
|
|
int obj = getActiveObject();
|
2006-10-29 14:45:31 +00:00
|
|
|
putState(obj, getState(obj) | kObjectState_08);
|
2004-01-11 20:42:40 +00:00
|
|
|
markObjectRectAsDirty(obj);
|
2003-04-20 16:04:50 +00:00
|
|
|
clearDrawObjectQueue();
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_clearState08() {
|
2009-04-20 12:35:17 +00:00
|
|
|
int obj = getActiveObject();
|
2006-10-29 14:45:31 +00:00
|
|
|
putState(obj, getState(obj) & ~kObjectState_08);
|
2004-01-11 20:42:40 +00:00
|
|
|
markObjectRectAsDirty(obj);
|
2003-04-20 16:04:50 +00:00
|
|
|
clearDrawObjectQueue();
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setState04() {
|
2006-10-29 14:45:31 +00:00
|
|
|
setStateCommon(kObjectStateLocked);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_clearState04() {
|
2006-10-29 14:45:31 +00:00
|
|
|
clearStateCommon(kObjectStateLocked);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setState02() {
|
2006-10-29 14:45:31 +00:00
|
|
|
setStateCommon(kObjectStateUntouchable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_clearState02() {
|
2006-10-29 14:45:31 +00:00
|
|
|
clearStateCommon(kObjectStateUntouchable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setState01() {
|
2006-10-29 14:45:31 +00:00
|
|
|
setStateCommon(kObjectStatePickupable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_clearState01() {
|
2006-10-29 14:45:31 +00:00
|
|
|
clearStateCommon(kObjectStatePickupable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_assignVarWordIndirect() {
|
2003-05-04 02:27:22 +00:00
|
|
|
getResultPosIndirect();
|
2003-11-16 18:34:33 +00:00
|
|
|
setResult(getVarOrDirectWord(PARAM_1));
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_assignVarByte() {
|
2003-04-20 16:04:50 +00:00
|
|
|
getResultPos();
|
2003-04-27 07:52:26 +00:00
|
|
|
setResult(fetchScriptByte());
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setObjPreposition() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int obj = getVarOrDirectWord(PARAM_1);
|
2003-05-20 16:13:34 +00:00
|
|
|
int unk = fetchScriptByte();
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2005-04-07 21:13:01 +00:00
|
|
|
return;
|
2003-04-20 16:04:50 +00:00
|
|
|
|
|
|
|
if (whereIsObject(obj) != WIO_NOT_FOUND) {
|
2003-05-22 15:27:44 +00:00
|
|
|
// FIXME: this might not work properly the moment we save and restore the game.
|
|
|
|
byte *ptr = getOBCDFromObject(obj) + 12;
|
|
|
|
*ptr &= 0x1F;
|
|
|
|
*ptr |= unk << 5;
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getObjPreposition() {
|
2003-04-21 12:59:57 +00:00
|
|
|
getResultPos();
|
2003-11-16 18:34:33 +00:00
|
|
|
int obj = getVarOrDirectWord(PARAM_1);
|
2003-04-20 16:04:50 +00:00
|
|
|
|
|
|
|
if (whereIsObject(obj) != WIO_NOT_FOUND) {
|
2003-05-22 15:27:44 +00:00
|
|
|
byte *ptr = getOBCDFromObject(obj) + 12;
|
|
|
|
setResult(*ptr >> 5);
|
2003-04-20 16:04:50 +00:00
|
|
|
} else {
|
2003-04-30 11:15:11 +00:00
|
|
|
setResult(0xFF);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setBitVar() {
|
2003-05-21 14:25:14 +00:00
|
|
|
int var = fetchScriptWord();
|
2003-11-16 18:34:33 +00:00
|
|
|
byte a = getVarOrDirectByte(PARAM_1);
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-05-09 00:57:10 +00:00
|
|
|
int bit_var = var + a;
|
2003-04-20 16:04:50 +00:00
|
|
|
int bit_offset = bit_var & 0x0f;
|
2003-04-27 09:39:52 +00:00
|
|
|
bit_var >>= 4;
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
if (getVarOrDirectByte(PARAM_2))
|
2003-05-08 15:48:50 +00:00
|
|
|
_scummVars[bit_var] |= (1 << bit_offset);
|
2003-04-20 16:04:50 +00:00
|
|
|
else
|
2003-05-08 15:48:50 +00:00
|
|
|
_scummVars[bit_var] &= ~(1 << bit_offset);
|
2003-05-21 14:25:14 +00:00
|
|
|
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getBitVar() {
|
2003-04-20 16:04:50 +00:00
|
|
|
getResultPos();
|
2003-05-21 14:25:14 +00:00
|
|
|
int var = fetchScriptWord();
|
2003-11-16 18:34:33 +00:00
|
|
|
byte a = getVarOrDirectByte(PARAM_1);
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-05-09 00:57:10 +00:00
|
|
|
int bit_var = var + a;
|
2003-04-20 16:04:50 +00:00
|
|
|
int bit_offset = bit_var & 0x0f;
|
2003-04-27 09:39:52 +00:00
|
|
|
bit_var >>= 4;
|
2003-04-20 16:04:50 +00:00
|
|
|
|
2003-11-26 08:53:53 +00:00
|
|
|
setResult((_scummVars[bit_var] & (1 << bit_offset)) ? 1 : 0);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifState08() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifStateCommon(kObjectState_08);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifNotState08() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifNotStateCommon(kObjectState_08);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifState04() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifStateCommon(kObjectStateLocked);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifNotState04() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifNotStateCommon(kObjectStateLocked);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifState02() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifStateCommon(kObjectStateUntouchable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifNotState02() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifNotStateCommon(kObjectStateUntouchable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifState01() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifStateCommon(kObjectStatePickupable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifNotState01() {
|
2006-10-29 14:45:31 +00:00
|
|
|
ifNotStateCommon(kObjectStatePickupable);
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_addIndirect() {
|
2003-04-20 16:04:50 +00:00
|
|
|
int a;
|
2003-05-04 02:27:22 +00:00
|
|
|
getResultPosIndirect();
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectWord(PARAM_1);
|
2003-05-08 15:48:50 +00:00
|
|
|
_scummVars[_resultVarNumber] += a;
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_subIndirect() {
|
2003-04-20 16:04:50 +00:00
|
|
|
int a;
|
2003-05-04 02:27:22 +00:00
|
|
|
getResultPosIndirect();
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectWord(PARAM_1);
|
2003-05-08 15:48:50 +00:00
|
|
|
_scummVars[_resultVarNumber] -= a;
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_add() {
|
2003-05-22 22:42:44 +00:00
|
|
|
int a;
|
|
|
|
getResultPos();
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectWord(PARAM_1);
|
2003-05-22 22:42:44 +00:00
|
|
|
_scummVars[_resultVarNumber] += a;
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_subtract() {
|
2003-05-22 22:42:44 +00:00
|
|
|
int a;
|
|
|
|
getResultPos();
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectWord(PARAM_1);
|
2003-05-22 22:42:44 +00:00
|
|
|
_scummVars[_resultVarNumber] -= a;
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_waitForActor() {
|
2003-11-16 18:34:33 +00:00
|
|
|
Actor *a = derefActor(getVarOrDirectByte(PARAM_1), "o2_waitForActor");
|
2005-03-11 01:10:06 +00:00
|
|
|
if (a->_moving) {
|
2003-04-21 12:59:57 +00:00
|
|
|
_scriptPointer -= 2;
|
2003-04-20 16:04:50 +00:00
|
|
|
o5_breakHere();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_waitForMessage() {
|
2003-05-08 15:48:50 +00:00
|
|
|
if (VAR(VAR_HAVE_MSG)) {
|
2003-05-04 17:39:25 +00:00
|
|
|
_scriptPointer--;
|
|
|
|
o5_breakHere();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_waitForSentence() {
|
2003-05-28 13:28:43 +00:00
|
|
|
if (!_sentenceNum && !isScriptInUse(SENTENCE_SCRIPT))
|
2003-05-04 17:39:25 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
_scriptPointer--;
|
|
|
|
o5_breakHere();
|
|
|
|
}
|
|
|
|
|
2003-11-10 08:46:40 +00:00
|
|
|
void ScummEngine_v2::o2_actorOps() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
|
|
|
int arg = getVarOrDirectByte(PARAM_2);
|
2003-05-23 12:07:36 +00:00
|
|
|
Actor *a;
|
2003-04-21 09:03:17 +00:00
|
|
|
int i;
|
2003-04-20 17:07:25 +00:00
|
|
|
|
2003-05-04 02:10:49 +00:00
|
|
|
_opcode = fetchScriptByte();
|
2003-05-23 12:07:36 +00:00
|
|
|
if (act == 0 && _opcode == 5) {
|
|
|
|
// This case happens in the Zak/MM bootscripts, to set the default talk color (9).
|
|
|
|
_string[0].color = arg;
|
2003-04-20 17:07:25 +00:00
|
|
|
return;
|
2003-05-03 06:48:26 +00:00
|
|
|
}
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-11-10 09:16:41 +00:00
|
|
|
a = derefActor(act, "actorOps");
|
2003-04-20 16:59:52 +00:00
|
|
|
|
2003-05-04 02:10:49 +00:00
|
|
|
switch (_opcode) {
|
2008-01-28 00:14:17 +00:00
|
|
|
case 1: // SO_SOUND
|
2005-03-11 01:10:06 +00:00
|
|
|
a->_sound[0] = arg;
|
2003-09-24 06:33:59 +00:00
|
|
|
break;
|
2003-11-10 09:16:41 +00:00
|
|
|
case 2: // SO_PALETTE
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version == 1)
|
2003-09-24 06:33:59 +00:00
|
|
|
i = act;
|
|
|
|
else
|
|
|
|
i = fetchScriptByte();
|
|
|
|
|
2004-01-05 16:30:00 +00:00
|
|
|
a->setPalette(i, arg);
|
2003-09-24 06:33:59 +00:00
|
|
|
break;
|
2003-11-10 09:16:41 +00:00
|
|
|
case 3: // SO_ACTOR_NAME
|
2005-03-11 01:10:06 +00:00
|
|
|
loadPtrToResource(rtActorName, a->_number, NULL);
|
2003-09-24 06:33:59 +00:00
|
|
|
break;
|
2003-11-10 09:16:41 +00:00
|
|
|
case 4: // SO_COSTUME
|
2003-09-24 06:33:59 +00:00
|
|
|
a->setActorCostume(arg);
|
|
|
|
break;
|
2003-11-10 09:16:41 +00:00
|
|
|
case 5: // SO_TALK_COLOR
|
2006-04-23 00:08:18 +00:00
|
|
|
if (_game.id == GID_MANIAC && _game.version == 2 && (_game.features & GF_DEMO) && arg == 1)
|
2005-03-11 01:10:06 +00:00
|
|
|
a->_talkColor = 15;
|
2003-09-24 06:33:59 +00:00
|
|
|
else
|
2005-03-11 01:10:06 +00:00
|
|
|
a->_talkColor = arg;
|
2003-09-24 06:33:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
2005-08-14 01:41:52 +00:00
|
|
|
error("o2_actorOps: opcode %d not yet supported", _opcode);
|
2003-04-20 16:59:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_restart() {
|
2003-06-02 02:25:24 +00:00
|
|
|
restart();
|
2003-04-20 16:04:50 +00:00
|
|
|
}
|
2003-04-20 16:59:52 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_drawObject() {
|
2003-04-21 12:31:08 +00:00
|
|
|
int obj, idx, i;
|
|
|
|
ObjectData *od;
|
|
|
|
uint16 x, y, w, h;
|
|
|
|
int xpos, ypos;
|
2003-04-20 16:59:52 +00:00
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
obj = getVarOrDirectWord(PARAM_1);
|
|
|
|
xpos = getVarOrDirectByte(PARAM_2);
|
|
|
|
ypos = getVarOrDirectByte(PARAM_3);
|
2003-04-21 12:31:08 +00:00
|
|
|
|
|
|
|
idx = getObjectIndex(obj);
|
|
|
|
if (idx == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
od = &_objs[idx];
|
|
|
|
if (xpos != 0xFF) {
|
2003-11-16 20:52:57 +00:00
|
|
|
od->walk_x += (xpos * 8) - od->x_pos;
|
|
|
|
od->x_pos = xpos * 8;
|
|
|
|
od->walk_y += (ypos * 8) - od->y_pos;
|
|
|
|
od->y_pos = ypos * 8;
|
2003-04-21 12:31:08 +00:00
|
|
|
}
|
|
|
|
addObjectToDrawQue(idx);
|
|
|
|
|
|
|
|
x = od->x_pos;
|
|
|
|
y = od->y_pos;
|
|
|
|
w = od->width;
|
|
|
|
h = od->height;
|
|
|
|
|
|
|
|
i = _numLocalObjects;
|
2003-05-10 21:35:06 +00:00
|
|
|
while (i--) {
|
2003-04-21 12:31:08 +00:00
|
|
|
if (_objs[i].obj_nr && _objs[i].x_pos == x && _objs[i].y_pos == y && _objs[i].width == w && _objs[i].height == h)
|
2006-10-29 14:45:31 +00:00
|
|
|
putState(_objs[i].obj_nr, getState(_objs[i].obj_nr) & ~kObjectState_08);
|
2003-05-10 21:35:06 +00:00
|
|
|
}
|
2003-04-21 12:31:08 +00:00
|
|
|
|
2006-10-29 14:45:31 +00:00
|
|
|
putState(obj, getState(od->obj_nr) | kObjectState_08);
|
2003-04-21 12:31:08 +00:00
|
|
|
}
|
2003-04-21 14:09:16 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_resourceRoutines() {
|
2011-05-13 12:02:53 +00:00
|
|
|
const ResType resTypes[] = {
|
|
|
|
rtInvalid,
|
|
|
|
rtInvalid,
|
2003-11-16 18:34:33 +00:00
|
|
|
rtCostume,
|
|
|
|
rtRoom,
|
2011-05-13 12:02:53 +00:00
|
|
|
rtInvalid,
|
2003-11-16 18:34:33 +00:00
|
|
|
rtScript,
|
|
|
|
rtSound
|
|
|
|
};
|
|
|
|
int resid = getVarOrDirectByte(PARAM_1);
|
2003-04-21 14:20:18 +00:00
|
|
|
int opcode = fetchScriptByte();
|
2003-04-21 14:09:16 +00:00
|
|
|
|
2011-05-13 12:02:53 +00:00
|
|
|
ResType type = rtInvalid;
|
2003-05-08 14:14:37 +00:00
|
|
|
if (0 <= (opcode >> 4) && (opcode >> 4) < (int)ARRAYSIZE(resTypes))
|
|
|
|
type = resTypes[opcode >> 4];
|
|
|
|
|
2011-05-13 12:02:53 +00:00
|
|
|
if ((opcode & 0x0f) == 0 || type == rtInvalid)
|
2003-05-08 14:14:37 +00:00
|
|
|
return;
|
|
|
|
|
2004-03-03 08:17:21 +00:00
|
|
|
// HACK V2 Maniac Mansion tries to load an invalid sound resource in demo script.
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_MANIAC && _game.version == 2 && vm.slot[_currentScript].number == 9 && type == rtSound && resid == 1)
|
2004-03-03 08:17:21 +00:00
|
|
|
return;
|
|
|
|
|
2003-09-06 08:46:36 +00:00
|
|
|
if ((opcode & 0x0f) == 1) {
|
|
|
|
ensureResourceLoaded(type, resid);
|
2003-04-21 14:20:18 +00:00
|
|
|
} else {
|
2003-09-06 08:46:36 +00:00
|
|
|
if (opcode & 1)
|
2006-09-17 20:36:48 +00:00
|
|
|
_res->lock(type, resid);
|
2003-09-06 08:46:36 +00:00
|
|
|
else
|
2006-09-17 20:36:48 +00:00
|
|
|
_res->unlock(type, resid);
|
2003-04-21 14:20:18 +00:00
|
|
|
}
|
2003-04-21 14:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_verbOps() {
|
2003-05-14 12:26:23 +00:00
|
|
|
int verb = fetchScriptByte();
|
|
|
|
int slot, state;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-05-14 12:26:23 +00:00
|
|
|
switch (verb) {
|
2003-11-10 09:16:41 +00:00
|
|
|
case 0: // SO_DELETE_VERBS
|
2003-11-16 18:34:33 +00:00
|
|
|
slot = getVarOrDirectByte(PARAM_1) + 1;
|
2003-12-26 23:11:35 +00:00
|
|
|
assert(0 < slot && slot < _numVerbs);
|
2003-05-08 22:44:46 +00:00
|
|
|
killVerb(slot);
|
2003-05-04 20:07:32 +00:00
|
|
|
break;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-04-21 14:09:16 +00:00
|
|
|
case 0xFF: // Verb On/Off
|
2003-05-08 22:44:46 +00:00
|
|
|
verb = fetchScriptByte();
|
2003-04-21 14:09:16 +00:00
|
|
|
state = fetchScriptByte();
|
2003-05-08 22:44:46 +00:00
|
|
|
slot = getVerbSlot(verb, 0);
|
|
|
|
_verbs[slot].curmode = state;
|
2003-05-04 20:07:32 +00:00
|
|
|
break;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-04-21 14:09:16 +00:00
|
|
|
default: { // New Verb
|
2003-11-16 20:52:57 +00:00
|
|
|
int x = fetchScriptByte() * 8;
|
|
|
|
int y = fetchScriptByte() * 8;
|
2003-11-16 18:34:33 +00:00
|
|
|
slot = getVarOrDirectByte(PARAM_1) + 1;
|
2003-08-05 16:43:33 +00:00
|
|
|
int prep = fetchScriptByte(); // Only used in V1?
|
2003-07-14 06:00:17 +00:00
|
|
|
// V1 Maniac verbs are relative to the 'verb area' - under the sentence
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2005-04-01 01:41:20 +00:00
|
|
|
x += 8;
|
2006-02-20 16:51:30 +00:00
|
|
|
else if ((_game.id == GID_MANIAC) && (_game.version == 1))
|
2005-03-15 04:16:25 +00:00
|
|
|
y += 8;
|
2003-07-09 14:57:15 +00:00
|
|
|
|
2003-05-08 22:44:46 +00:00
|
|
|
VerbSlot *vs;
|
2003-12-26 23:11:35 +00:00
|
|
|
assert(0 < slot && slot < _numVerbs);
|
2003-05-14 12:26:23 +00:00
|
|
|
|
2003-05-08 22:44:46 +00:00
|
|
|
vs = &_verbs[slot];
|
|
|
|
vs->verbid = verb;
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
2005-03-21 23:51:48 +00:00
|
|
|
vs->color = 1;
|
|
|
|
vs->hicolor = 1;
|
|
|
|
vs->dimcolor = 1;
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_game.version == 1) {
|
2006-04-23 00:08:18 +00:00
|
|
|
vs->color = (_game.id == GID_MANIAC && (_game.features & GF_DEMO)) ? 16 : 5;
|
2003-07-13 15:13:43 +00:00
|
|
|
vs->hicolor = 7;
|
|
|
|
vs->dimcolor = 11;
|
|
|
|
} else {
|
2006-04-23 00:08:18 +00:00
|
|
|
vs->color = (_game.id == GID_MANIAC && (_game.features & GF_DEMO)) ? 13 : 2;
|
2003-07-13 15:13:43 +00:00
|
|
|
vs->hicolor = 14;
|
|
|
|
vs->dimcolor = 8;
|
|
|
|
}
|
2003-05-08 22:44:46 +00:00
|
|
|
vs->type = kTextVerbType;
|
2004-04-05 23:54:58 +00:00
|
|
|
vs->charset_nr = _string[0]._default.charset;
|
2003-05-08 22:44:46 +00:00
|
|
|
vs->curmode = 1;
|
|
|
|
vs->saveid = 0;
|
|
|
|
vs->key = 0;
|
|
|
|
vs->center = 0;
|
|
|
|
vs->imgindex = 0;
|
2003-08-05 16:43:33 +00:00
|
|
|
vs->prep = prep;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2004-01-15 19:25:17 +00:00
|
|
|
vs->curRect.left = x;
|
|
|
|
vs->curRect.top = y;
|
2005-03-21 23:51:48 +00:00
|
|
|
|
2007-02-15 10:40:20 +00:00
|
|
|
// FIXME: these keyboard map depends on the language of the game.
|
2003-05-21 23:46:02 +00:00
|
|
|
// E.g. a german keyboard has 'z' and 'y' swapped, while a french
|
2007-02-18 17:53:44 +00:00
|
|
|
// keyboard starts with "azerty", etc.
|
2007-02-15 10:40:20 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
|
|
|
static const char keyboard[] = {
|
|
|
|
'q','w','e','r',
|
|
|
|
'a','s','d','f',
|
|
|
|
'z','x','c','v'
|
|
|
|
};
|
|
|
|
if (1 <= slot && slot <= ARRAYSIZE(keyboard))
|
|
|
|
vs->key = keyboard[slot - 1];
|
|
|
|
} else {
|
|
|
|
static const char keyboard[] = {
|
|
|
|
'q','w','e','r','t',
|
|
|
|
'a','s','d','f','g',
|
|
|
|
'z','x','c','v','b'
|
|
|
|
};
|
|
|
|
if (1 <= slot && slot <= ARRAYSIZE(keyboard))
|
|
|
|
vs->key = keyboard[slot - 1];
|
|
|
|
}
|
2003-05-08 22:44:46 +00:00
|
|
|
|
|
|
|
// It follows the verb name
|
|
|
|
loadPtrToResource(rtVerb, slot, NULL);
|
2003-05-04 20:07:32 +00:00
|
|
|
}
|
|
|
|
break;
|
2003-04-21 14:09:16 +00:00
|
|
|
}
|
2003-05-08 22:44:46 +00:00
|
|
|
|
2003-09-19 14:13:24 +00:00
|
|
|
// Force redraw of the modified verb slot
|
2003-05-08 22:44:46 +00:00
|
|
|
drawVerb(slot, 0);
|
|
|
|
verbMouseOver(0);
|
2003-04-21 14:09:16 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_doSentence() {
|
2003-04-21 14:59:19 +00:00
|
|
|
int a;
|
|
|
|
SentenceTab *st;
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectByte(PARAM_1);
|
2003-05-21 04:09:20 +00:00
|
|
|
if (a == 0xFC) {
|
2003-04-21 14:59:19 +00:00
|
|
|
_sentenceNum = 0;
|
2003-05-20 20:58:26 +00:00
|
|
|
stopScript(SENTENCE_SCRIPT);
|
2003-04-21 14:59:19 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-05-21 04:09:20 +00:00
|
|
|
if (a == 0xFB) {
|
2011-02-07 17:53:34 +00:00
|
|
|
resetSentence(false);
|
2003-04-21 14:59:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-21 10:52:07 +00:00
|
|
|
assert(_sentenceNum < NUM_SENTENCE);
|
2003-04-21 14:59:19 +00:00
|
|
|
st = &_sentence[_sentenceNum++];
|
|
|
|
|
2003-04-28 03:13:49 +00:00
|
|
|
st->verb = a;
|
2003-11-16 18:34:33 +00:00
|
|
|
st->objectA = getVarOrDirectWord(PARAM_2);
|
|
|
|
st->objectB = getVarOrDirectWord(PARAM_3);
|
2003-05-22 14:10:20 +00:00
|
|
|
st->preposition = (st->objectB != 0);
|
2003-04-21 14:59:19 +00:00
|
|
|
st->freezeCount = 0;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-09-10 15:02:58 +00:00
|
|
|
// Execute or print the sentence
|
|
|
|
_opcode = fetchScriptByte();
|
2004-10-22 10:25:56 +00:00
|
|
|
switch (_opcode) {
|
2003-09-10 15:02:58 +00:00
|
|
|
case 0:
|
|
|
|
// Do nothing (besides setting up the sentence above)
|
|
|
|
break;
|
2003-04-21 14:59:19 +00:00
|
|
|
case 1:
|
2003-05-16 01:56:06 +00:00
|
|
|
// Execute the sentence
|
2003-05-11 11:13:24 +00:00
|
|
|
_sentenceNum--;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-07-15 00:23:18 +00:00
|
|
|
if (st->verb == 254) {
|
2003-10-02 22:42:03 +00:00
|
|
|
ScummEngine::stopObjectScript(st->objectA);
|
2003-09-10 15:02:58 +00:00
|
|
|
} else {
|
2003-09-10 17:15:44 +00:00
|
|
|
bool isBackgroundScript;
|
|
|
|
bool isSpecialVerb;
|
|
|
|
if (st->verb != 253 && st->verb != 250) {
|
|
|
|
VAR(VAR_ACTIVE_VERB) = st->verb;
|
2005-07-30 21:11:48 +00:00
|
|
|
VAR(VAR_ACTIVE_OBJECT1) = st->objectA;
|
2003-09-10 17:15:44 +00:00
|
|
|
VAR(VAR_ACTIVE_OBJECT2) = st->objectB;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-09-10 17:15:44 +00:00
|
|
|
isBackgroundScript = false;
|
|
|
|
isSpecialVerb = false;
|
|
|
|
} else {
|
|
|
|
isBackgroundScript = (st->verb == 250);
|
|
|
|
isSpecialVerb = true;
|
|
|
|
st->verb = 253;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if an object script for this object is already running. If
|
|
|
|
// so, reuse its script slot. Note that we abuse two script flags:
|
|
|
|
// freezeResistant and recursive. We use them to track two
|
|
|
|
// script flags used in V1/V2 games. The main reason we do it this
|
|
|
|
// ugly evil way is to avoid having to introduce yet another save
|
|
|
|
// game revision.
|
|
|
|
int slot = -1;
|
|
|
|
ScriptSlot *ss;
|
|
|
|
int i;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-09-10 17:15:44 +00:00
|
|
|
ss = vm.slot;
|
|
|
|
for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) {
|
|
|
|
if (st->objectA == ss->number &&
|
|
|
|
ss->freezeResistant == isBackgroundScript &&
|
|
|
|
ss->recursive == isSpecialVerb &&
|
|
|
|
(ss->where == WIO_ROOM || ss->where == WIO_INVENTORY || ss->where == WIO_FLOBJECT)) {
|
|
|
|
slot = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
runObjectScript(st->objectA, st->verb, isBackgroundScript, isSpecialVerb, NULL, slot);
|
2003-09-10 15:02:58 +00:00
|
|
|
}
|
2003-04-21 14:59:19 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2003-05-16 02:16:59 +00:00
|
|
|
// Print the sentence
|
2003-05-11 11:13:24 +00:00
|
|
|
_sentenceNum--;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-05-21 14:00:19 +00:00
|
|
|
VAR(VAR_SENTENCE_VERB) = st->verb;
|
|
|
|
VAR(VAR_SENTENCE_OBJECT1) = st->objectA;
|
|
|
|
VAR(VAR_SENTENCE_OBJECT2) = st->objectB;
|
2003-05-17 06:04:22 +00:00
|
|
|
|
2003-05-16 02:16:59 +00:00
|
|
|
o2_drawSentence();
|
2003-04-21 14:59:19 +00:00
|
|
|
break;
|
2003-09-10 15:02:58 +00:00
|
|
|
default:
|
|
|
|
error("o2_doSentence: unknown subopcode %d", _opcode);
|
2003-04-21 14:59:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-03 21:10:50 +00:00
|
|
|
void ScummEngine_v2::drawPreposition(int index) {
|
|
|
|
// The prepositions, like the fonts, were hard code in the engine. Thus
|
|
|
|
// we have to do that, too, and provde localized versions for all the
|
|
|
|
// languages MM/Zak are available in.
|
|
|
|
const char *prepositions[][5] = {
|
|
|
|
{ " ", " in", " with", " on", " to" }, // English
|
|
|
|
{ " ", " mit", " mit", " mit", " zu" }, // German
|
|
|
|
{ " ", " dans", " avec", " sur", " <" }, // French
|
|
|
|
{ " ", " in", " con", " su", " a" }, // Italian
|
|
|
|
{ " ", " en", " con", " en", " a" }, // Spanish
|
|
|
|
};
|
|
|
|
int lang;
|
|
|
|
switch (_language) {
|
|
|
|
case Common::DE_DEU:
|
|
|
|
lang = 1;
|
|
|
|
break;
|
|
|
|
case Common::FR_FRA:
|
|
|
|
lang = 2;
|
|
|
|
break;
|
|
|
|
case Common::IT_ITA:
|
|
|
|
lang = 3;
|
|
|
|
break;
|
|
|
|
case Common::ES_ESP:
|
|
|
|
lang = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
lang = 0; // Default to english
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
|
|
|
_sentenceBuf += (const char *)(getResourceAddress(rtCostume, 78) + VAR(VAR_SENTENCE_PREPOSITION) * 8 + 2);
|
|
|
|
} else
|
|
|
|
_sentenceBuf += prepositions[lang][index];
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_drawSentence() {
|
2003-10-02 17:43:02 +00:00
|
|
|
Common::Rect sentenceline;
|
2003-05-21 18:09:49 +00:00
|
|
|
const byte *temp;
|
2003-11-08 21:59:32 +00:00
|
|
|
int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0);
|
2003-08-05 16:51:40 +00:00
|
|
|
|
2012-01-29 16:03:37 +00:00
|
|
|
if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
|
2012-02-04 13:49:44 +00:00
|
|
|
(_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL))))
|
2003-05-21 06:14:02 +00:00
|
|
|
return;
|
|
|
|
|
2003-05-22 11:40:20 +00:00
|
|
|
if (getResourceAddress(rtVerb, slot))
|
2010-05-05 20:43:22 +00:00
|
|
|
_sentenceBuf = (char *)getResourceAddress(rtVerb, slot);
|
2003-05-22 11:40:20 +00:00
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
2003-05-21 14:00:19 +00:00
|
|
|
if (VAR(VAR_SENTENCE_OBJECT1) > 0) {
|
|
|
|
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT1));
|
2003-05-21 11:22:03 +00:00
|
|
|
if (temp) {
|
2010-05-05 20:43:22 +00:00
|
|
|
_sentenceBuf += " ";
|
|
|
|
_sentenceBuf += (const char *)temp;
|
2003-05-21 10:13:06 +00:00
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-08-05 17:58:38 +00:00
|
|
|
// For V1 games, the engine must compute the preposition.
|
|
|
|
// In all other Scumm versions, this is done by the sentence script.
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_game.id == GID_MANIAC && _game.version == 1 && !(_game.platform == Common::kPlatformNES)) && (VAR(VAR_SENTENCE_PREPOSITION) == 0)) {
|
2003-08-05 17:58:38 +00:00
|
|
|
if (_verbs[slot].prep == 0xFF) {
|
|
|
|
byte *ptr = getOBCDFromObject(VAR(VAR_SENTENCE_OBJECT1));
|
|
|
|
assert(ptr);
|
2003-11-08 21:59:32 +00:00
|
|
|
VAR(VAR_SENTENCE_PREPOSITION) = (*(ptr + 12) >> 5);
|
2003-08-05 17:58:38 +00:00
|
|
|
} else
|
|
|
|
VAR(VAR_SENTENCE_PREPOSITION) = _verbs[slot].prep;
|
2003-08-05 16:51:40 +00:00
|
|
|
}
|
2003-05-16 12:58:49 +00:00
|
|
|
}
|
|
|
|
|
2003-05-25 18:56:20 +00:00
|
|
|
if (0 < VAR(VAR_SENTENCE_PREPOSITION) && VAR(VAR_SENTENCE_PREPOSITION) <= 4) {
|
2012-01-03 21:10:50 +00:00
|
|
|
drawPreposition(VAR(VAR_SENTENCE_PREPOSITION));
|
2003-05-21 23:46:02 +00:00
|
|
|
}
|
|
|
|
|
2003-05-21 14:00:19 +00:00
|
|
|
if (VAR(VAR_SENTENCE_OBJECT2) > 0) {
|
|
|
|
temp = getObjOrActorName(VAR(VAR_SENTENCE_OBJECT2));
|
2003-05-21 11:22:03 +00:00
|
|
|
if (temp) {
|
2010-05-05 20:43:22 +00:00
|
|
|
_sentenceBuf += " ";
|
|
|
|
_sentenceBuf += (const char *)temp;
|
2003-05-21 10:13:06 +00:00
|
|
|
}
|
2003-05-16 12:58:49 +00:00
|
|
|
}
|
|
|
|
|
2003-05-21 06:00:16 +00:00
|
|
|
_string[2].charset = 1;
|
2007-09-08 11:15:27 +00:00
|
|
|
_string[2].ypos = _virtscr[kVerbVirtScreen].topline;
|
2003-05-21 06:00:16 +00:00
|
|
|
_string[2].xpos = 0;
|
2007-09-08 11:15:27 +00:00
|
|
|
_string[2].right = _virtscr[kVerbVirtScreen].w - 1;
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
2005-04-01 01:41:20 +00:00
|
|
|
_string[2].xpos = 16;
|
2005-03-21 23:51:48 +00:00
|
|
|
_string[2].color = 0;
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_game.version == 1)
|
2003-12-15 14:54:35 +00:00
|
|
|
_string[2].color = 16;
|
2005-07-30 21:11:48 +00:00
|
|
|
else
|
2003-07-14 06:19:06 +00:00
|
|
|
_string[2].color = 13;
|
2003-05-21 06:00:16 +00:00
|
|
|
|
2005-11-01 11:27:41 +00:00
|
|
|
byte string[80];
|
2010-05-05 20:43:22 +00:00
|
|
|
const char *ptr = _sentenceBuf.c_str();
|
2005-11-01 11:27:41 +00:00
|
|
|
int i = 0, len = 0;
|
2003-07-23 14:33:57 +00:00
|
|
|
|
2005-11-01 11:27:41 +00:00
|
|
|
// Maximum length of printable characters
|
2006-05-14 10:40:06 +00:00
|
|
|
int maxChars = (_game.platform == Common::kPlatformNES) ? 60 : 40;
|
2003-07-23 14:36:18 +00:00
|
|
|
while (*ptr) {
|
2003-07-23 14:33:57 +00:00
|
|
|
if (*ptr != '@')
|
2005-11-01 11:27:41 +00:00
|
|
|
len++;
|
|
|
|
if (len > maxChars) {
|
2003-07-23 14:33:57 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-11-01 11:27:41 +00:00
|
|
|
|
|
|
|
string[i++] = *ptr++;
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES && len == 30) {
|
2005-11-01 11:27:41 +00:00
|
|
|
string[i++] = 0xFF;
|
|
|
|
string[i++] = 8;
|
|
|
|
}
|
2003-07-23 14:33:57 +00:00
|
|
|
}
|
2005-11-01 11:27:41 +00:00
|
|
|
string[i] = 0;
|
2003-07-23 14:33:57 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
2007-09-08 11:15:27 +00:00
|
|
|
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
|
|
|
|
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 16;
|
2005-04-01 01:41:20 +00:00
|
|
|
sentenceline.left = 16;
|
2007-09-08 11:15:27 +00:00
|
|
|
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
|
2005-04-01 01:41:20 +00:00
|
|
|
} else {
|
2007-09-08 11:15:27 +00:00
|
|
|
sentenceline.top = _virtscr[kVerbVirtScreen].topline;
|
|
|
|
sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
|
2005-04-01 01:41:20 +00:00
|
|
|
sentenceline.left = 0;
|
2007-09-08 11:15:27 +00:00
|
|
|
sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
|
2005-04-01 01:41:20 +00:00
|
|
|
}
|
2006-09-17 23:35:09 +00:00
|
|
|
restoreBackground(sentenceline);
|
2003-05-21 06:00:16 +00:00
|
|
|
|
2010-05-05 20:43:22 +00:00
|
|
|
drawString(2, (byte *)string);
|
2003-05-16 01:56:06 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_ifClassOfIs() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int obj = getVarOrDirectWord(PARAM_1);
|
|
|
|
int clsop = getVarOrDirectByte(PARAM_2);
|
2009-04-20 12:35:17 +00:00
|
|
|
|
|
|
|
|
2003-05-23 01:14:29 +00:00
|
|
|
byte *obcd = getOBCDFromObject(obj);
|
2003-04-21 15:25:29 +00:00
|
|
|
|
2003-05-23 01:14:29 +00:00
|
|
|
if (obcd == 0) {
|
2003-04-21 15:25:29 +00:00
|
|
|
o5_jumpRelative();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-05-22 13:57:34 +00:00
|
|
|
byte cls = *(obcd + 6);
|
2009-04-20 12:35:17 +00:00
|
|
|
jumpRelative((cls & clsop) == clsop);
|
2003-04-21 15:25:29 +00:00
|
|
|
}
|
2003-04-21 15:42:55 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_walkActorTo() {
|
2003-04-21 15:42:55 +00:00
|
|
|
int x, y;
|
|
|
|
Actor *a;
|
2005-10-23 13:34:06 +00:00
|
|
|
|
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
|
|
|
|
2006-01-22 20:46:51 +00:00
|
|
|
// WORKAROUND bug #1252606
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_ZAK && _game.version == 1 && vm.slot[_currentScript].number == 115 && act == 249) {
|
2005-10-23 13:34:06 +00:00
|
|
|
act = VAR(VAR_EGO);
|
|
|
|
}
|
|
|
|
|
|
|
|
a = derefActor(act, "o2_walkActorTo");
|
2003-05-23 00:22:41 +00:00
|
|
|
|
2007-02-04 01:24:43 +00:00
|
|
|
x = getVarOrDirectByte(PARAM_2);
|
|
|
|
y = getVarOrDirectByte(PARAM_3);
|
2003-05-11 00:03:03 +00:00
|
|
|
|
2003-05-18 23:46:30 +00:00
|
|
|
a->startWalkActor(x, y, -1);
|
2003-04-21 15:42:55 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_putActor() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
2003-04-21 15:42:55 +00:00
|
|
|
int x, y;
|
|
|
|
Actor *a;
|
|
|
|
|
2003-05-23 13:24:41 +00:00
|
|
|
a = derefActor(act, "o2_putActor");
|
2007-02-04 01:24:43 +00:00
|
|
|
x = getVarOrDirectByte(PARAM_2);
|
|
|
|
y = getVarOrDirectByte(PARAM_3);
|
2003-04-21 15:42:55 +00:00
|
|
|
|
2006-07-24 12:49:58 +00:00
|
|
|
if (_game.id == GID_MANIAC && _game.version <= 1 && _game.platform != Common::kPlatformNES)
|
|
|
|
a->setFacing(180);
|
|
|
|
|
2006-11-19 00:39:48 +00:00
|
|
|
a->putActor(x, y);
|
2003-04-21 15:42:55 +00:00
|
|
|
}
|
2003-04-23 05:13:26 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_startScript() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int script = getVarOrDirectByte(PARAM_1);
|
2003-11-26 08:53:53 +00:00
|
|
|
|
2003-12-11 06:08:43 +00:00
|
|
|
if (!_copyProtection) {
|
|
|
|
// The enhanced version of Zak McKracken included in the
|
|
|
|
// SelectWare Classic Collection bundle used CD check instead
|
|
|
|
// of the usual key code check at airports.
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_game.id == GID_ZAK) && (script == 15) && (_roomResource == 45))
|
2003-12-11 06:08:43 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-11-26 08:58:00 +00:00
|
|
|
|
2010-12-02 00:27:46 +00:00
|
|
|
// WORKAROUND bug #1447058: In Maniac Mansion, when the door bell
|
|
|
|
// rings, then this normally causes Ted Edison to leave his room.
|
|
|
|
// This is controlled by script 87. On the other hand, when the
|
|
|
|
// player enters Ted's room while Ted is in it, then Ted captures
|
|
|
|
// the player and puts his active ego into the cellar prison.
|
|
|
|
//
|
|
|
|
// Unfortunately, the two events can collide: If the cutscene is
|
|
|
|
// playing in which Ted captures the player (controlled by script
|
|
|
|
// 88) and simultaneously the door bell rings (due to package
|
|
|
|
// delivery...) then this leads to an assertion (in ScummVM, due to
|
|
|
|
// its stricter validity checking), or to unexpected / strange
|
|
|
|
// behavior (in the original engine). The script writers apparently
|
|
|
|
// anticipated the possibility of the door bell ringing: Before
|
|
|
|
// script 91 starts script 88, it explicitly stops script 87.
|
|
|
|
// Unfortunately, this is not quite enough, as script 87 can be
|
|
|
|
// started while script 88 is already running -- specifically, by
|
|
|
|
// the package delivery sequence.
|
|
|
|
//
|
|
|
|
// Now, one can easily suppress this particular assertion, but then
|
|
|
|
// one still gets odd behavior: Ted is in the process of
|
|
|
|
// incarcerating the player, when the door bell rings; Ted promptly
|
|
|
|
// leaves to get the package, leaving the player alone (!), but then
|
|
|
|
// moments later we cut to the cellar, where Ted just put the
|
|
|
|
// player. That seems weird and irrational (the Edisons may be mad,
|
|
|
|
// but they are not stupid when it comes to putting people into
|
|
|
|
// their dungeon ;)
|
|
|
|
//
|
|
|
|
// To avoid this, we use a somewhat more elaborate workaround: If
|
|
|
|
// script 88 or 89 are running (which control the capture resp.
|
|
|
|
// imprisonment of the player), then any attempt to start script 87
|
|
|
|
// (which makes Ted go answer the door bell) is simply ignored. This
|
|
|
|
// way, the door bell still chimes, but Ted ignores it.
|
2012-01-29 06:07:38 +00:00
|
|
|
if (_game.id == GID_MANIAC) {
|
|
|
|
if (_game.version >= 1 && script == 87) {
|
|
|
|
if (isScriptRunning(88) || isScriptRunning(89))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Script numbers are different in V0
|
|
|
|
if (_game.version == 0 && script == 82) {
|
|
|
|
if (isScriptRunning(83) || isScriptRunning(84))
|
|
|
|
return;
|
2010-12-02 00:27:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-26 16:37:35 +00:00
|
|
|
runScript(script, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2012-01-03 21:58:25 +00:00
|
|
|
void ScummEngine_v2::stopScriptCommon(int script) {
|
2006-03-04 04:46:15 +00:00
|
|
|
if (_game.id == GID_MANIAC && _roomResource == 26 && vm.slot[_currentScript].number == 10001) {
|
|
|
|
// FIXME: Nasty hack for bug #915575
|
|
|
|
// Don't let the exit script for room 26 stop the script (116), when
|
|
|
|
// switching to the dungeon (script 89)
|
2012-01-29 06:07:38 +00:00
|
|
|
if (_game.version >= 1 && script == 116 && isScriptRunning(89))
|
|
|
|
return;
|
|
|
|
// Script numbers are different in V0
|
|
|
|
if (_game.version == 0 && script == 111 && isScriptRunning(84))
|
2006-03-04 04:46:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-02-22 16:08:13 +00:00
|
|
|
if (script == 0)
|
|
|
|
script = vm.slot[_currentScript].number;
|
|
|
|
|
2004-02-23 09:21:22 +00:00
|
|
|
if (_currentScript != 0 && vm.slot[_currentScript].number == script)
|
|
|
|
stopObjectCode();
|
|
|
|
else
|
2004-02-23 01:10:05 +00:00
|
|
|
stopScript(script);
|
2004-02-22 16:08:13 +00:00
|
|
|
}
|
|
|
|
|
2012-01-03 21:58:25 +00:00
|
|
|
void ScummEngine_v2::o2_stopScript() {
|
|
|
|
stopScriptCommon(getVarOrDirectByte(PARAM_1));
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_panCameraTo() {
|
2006-10-19 00:26:55 +00:00
|
|
|
panCameraTo(getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER, 0);
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2012-01-08 22:51:13 +00:00
|
|
|
void ScummEngine_v2::walkActorToObject(int actor, int obj) {
|
|
|
|
int x, y, dir;
|
|
|
|
getObjectXYPos(obj, x, y, dir);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2012-01-08 22:51:13 +00:00
|
|
|
Actor *a = derefActor(actor, "walkActorToObject");
|
|
|
|
AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
|
|
|
|
x = r.x;
|
|
|
|
y = r.y;
|
|
|
|
|
|
|
|
a->startWalkActor(x, y, dir);
|
|
|
|
}
|
2010-10-25 08:03:55 +00:00
|
|
|
|
2012-01-08 22:51:13 +00:00
|
|
|
void ScummEngine_v2::o2_walkActorToObject() {
|
|
|
|
int actor = getVarOrDirectByte(PARAM_1);
|
|
|
|
int obj = getVarOrDirectWord(PARAM_2);
|
|
|
|
if (whereIsObject(obj) != WIO_NOT_FOUND) {
|
|
|
|
walkActorToObject(actor, obj);
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_putActorAtObject() {
|
2003-04-26 16:37:35 +00:00
|
|
|
int obj, x, y;
|
|
|
|
Actor *a;
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
a = derefActor(getVarOrDirectByte(PARAM_1), "o2_putActorAtObject");
|
|
|
|
obj = getVarOrDirectWord(PARAM_2);
|
A long time ago, in a virtual machine far, far away...
It is a period of bug fixing. Rebel
developers, coding from a public
project, have won their umpteenth victory
against the evil Actor Walk Bugs.
During the debugging, programmers
used secret plans to the LucasArts'
ultimate tool, the SCUMM engine, an
extensible scripting system with enough
power to create an entire adventure.
Pursued by ensuing sinister regressions,
High King Fingolfin gleefully jumps up
and down, making use of the hotkey
that can save his games and restore
them back again later....
[With apologies to George Lucas. Good
riddance to bugs #751662, #771483, #959001,
#1329457, #1329498, #1329529, #1527672,
#1538260, #1571701, #1571705, #1571740,
and a warm welcome to the regressions
this change will cause. :-) ]
svn-id: r26090
2007-03-11 15:23:50 +00:00
|
|
|
if (whereIsObject(obj) != WIO_NOT_FOUND) {
|
2003-04-26 16:37:35 +00:00
|
|
|
getObjectXYPos(obj, x, y);
|
A long time ago, in a virtual machine far, far away...
It is a period of bug fixing. Rebel
developers, coding from a public
project, have won their umpteenth victory
against the evil Actor Walk Bugs.
During the debugging, programmers
used secret plans to the LucasArts'
ultimate tool, the SCUMM engine, an
extensible scripting system with enough
power to create an entire adventure.
Pursued by ensuing sinister regressions,
High King Fingolfin gleefully jumps up
and down, making use of the hotkey
that can save his games and restore
them back again later....
[With apologies to George Lucas. Good
riddance to bugs #751662, #771483, #959001,
#1329457, #1329498, #1329529, #1527672,
#1538260, #1571701, #1571705, #1571740,
and a warm welcome to the regressions
this change will cause. :-) ]
svn-id: r26090
2007-03-11 15:23:50 +00:00
|
|
|
AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
|
|
|
|
x = r.x;
|
|
|
|
y = r.y;
|
|
|
|
} else {
|
2007-02-04 01:24:43 +00:00
|
|
|
x = 30;
|
|
|
|
y = 60;
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
2003-05-23 00:04:17 +00:00
|
|
|
|
2006-11-19 00:39:48 +00:00
|
|
|
a->putActor(x, y);
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2006-07-24 12:49:58 +00:00
|
|
|
void ScummEngine_v2::o2_putActorInRoom() {
|
|
|
|
Actor *a;
|
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
|
|
|
int room = getVarOrDirectByte(PARAM_2);
|
|
|
|
|
|
|
|
a = derefActor(act, "o2_putActorInRoom");
|
|
|
|
|
|
|
|
a->_room = room;
|
|
|
|
if (!room) {
|
|
|
|
if (_game.id == GID_MANIAC && _game.version <= 1 && _game.platform != Common::kPlatformNES)
|
|
|
|
a->setFacing(180);
|
|
|
|
|
|
|
|
a->putActor(0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getActorElevation() {
|
2003-07-02 11:26:13 +00:00
|
|
|
getResultPos();
|
2003-11-16 18:34:33 +00:00
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
2003-07-02 11:26:13 +00:00
|
|
|
Actor *a = derefActor(act, "o2_getActorElevation");
|
2007-02-04 01:24:43 +00:00
|
|
|
setResult(a->getElevation());
|
2003-07-01 04:20:41 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setActorElevation() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int act = getVarOrDirectByte(PARAM_1);
|
|
|
|
int elevation = (int8)getVarOrDirectByte(PARAM_2);
|
2003-04-27 11:38:38 +00:00
|
|
|
|
2003-05-23 13:24:41 +00:00
|
|
|
Actor *a = derefActor(act, "o2_setActorElevation");
|
2007-02-04 01:24:43 +00:00
|
|
|
a->setElevation(elevation);
|
2003-04-27 11:38:38 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_actorFromPos() {
|
2003-04-26 16:37:35 +00:00
|
|
|
int x, y;
|
|
|
|
getResultPos();
|
2006-10-19 00:26:55 +00:00
|
|
|
x = getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER;
|
|
|
|
y = getVarOrDirectByte(PARAM_2) * V12_Y_MULTIPLIER;
|
2003-04-30 11:15:11 +00:00
|
|
|
setResult(getActorFromPos(x, y));
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_findObject() {
|
2005-04-20 23:53:29 +00:00
|
|
|
int obj;
|
2003-05-11 00:03:03 +00:00
|
|
|
getResultPos();
|
2006-10-19 00:26:55 +00:00
|
|
|
int x = getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER;
|
|
|
|
int y = getVarOrDirectByte(PARAM_2) * V12_Y_MULTIPLIER;
|
2005-04-20 23:53:29 +00:00
|
|
|
obj = findObject(x, y);
|
2012-01-29 16:03:37 +00:00
|
|
|
if (obj == 0 && (_game.platform == Common::kPlatformNES) && (_userState & USERSTATE_IFACE_INVENTORY)) {
|
2005-04-20 23:53:29 +00:00
|
|
|
if (_mouseOverBoxV2 >= 0 && _mouseOverBoxV2 < 4)
|
|
|
|
obj = findInventory(VAR(VAR_EGO), _mouseOverBoxV2 + _inventoryOffset + 1);
|
|
|
|
}
|
|
|
|
setResult(obj);
|
2003-05-11 00:03:03 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getActorX() {
|
2003-04-26 16:37:35 +00:00
|
|
|
int a;
|
|
|
|
getResultPos();
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectByte(PARAM_1);
|
2012-01-22 21:58:10 +00:00
|
|
|
setResult(getObjX(actorToObj(a)));
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getActorY() {
|
2003-04-26 16:37:35 +00:00
|
|
|
int a;
|
|
|
|
getResultPos();
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectByte(PARAM_1);
|
2012-01-22 21:58:10 +00:00
|
|
|
setResult(getObjY(actorToObj(a)));
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_isGreater() {
|
2003-07-14 19:57:44 +00:00
|
|
|
uint16 a = getVar();
|
2003-11-16 18:34:33 +00:00
|
|
|
uint16 b = getVarOrDirectWord(PARAM_1);
|
2009-04-20 12:35:17 +00:00
|
|
|
jumpRelative(b > a);
|
2003-07-14 19:57:44 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_isGreaterEqual() {
|
2003-07-14 19:57:44 +00:00
|
|
|
uint16 a = getVar();
|
2003-11-16 18:34:33 +00:00
|
|
|
uint16 b = getVarOrDirectWord(PARAM_1);
|
2009-04-20 12:35:17 +00:00
|
|
|
jumpRelative(b >= a);
|
2003-07-14 19:57:44 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_isLess() {
|
2003-07-14 19:57:44 +00:00
|
|
|
uint16 a = getVar();
|
2003-11-16 18:34:33 +00:00
|
|
|
uint16 b = getVarOrDirectWord(PARAM_1);
|
2003-07-14 19:57:44 +00:00
|
|
|
|
2009-04-20 12:35:17 +00:00
|
|
|
jumpRelative(b < a);
|
2003-07-14 19:57:44 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_isLessEqual() {
|
2003-07-14 19:57:44 +00:00
|
|
|
uint16 a = getVar();
|
2003-11-16 18:34:33 +00:00
|
|
|
uint16 b = getVarOrDirectWord(PARAM_1);
|
2009-04-20 12:35:17 +00:00
|
|
|
jumpRelative(b <= a);
|
2003-07-14 19:57:44 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_lights() {
|
2003-08-18 10:46:42 +00:00
|
|
|
int a, b, c;
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
a = getVarOrDirectByte(PARAM_1);
|
2003-08-18 10:46:42 +00:00
|
|
|
b = fetchScriptByte();
|
|
|
|
c = fetchScriptByte();
|
|
|
|
|
|
|
|
if (c == 0) {
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_MANIAC && _game.version == 1 && !(_game.platform == Common::kPlatformNES)) {
|
2003-08-18 10:46:42 +00:00
|
|
|
// Convert older light mode values into
|
2006-10-19 00:06:59 +00:00
|
|
|
// equivalent values of later games.
|
2003-08-18 10:46:42 +00:00
|
|
|
// 0 Darkness
|
|
|
|
// 1 Flashlight
|
|
|
|
// 2 Lighted area
|
2005-04-07 21:13:01 +00:00
|
|
|
if (a == 2)
|
2005-07-30 21:11:48 +00:00
|
|
|
VAR(VAR_CURRENT_LIGHTS) = 11;
|
2005-04-07 21:13:01 +00:00
|
|
|
else if (a == 1)
|
2003-08-18 10:46:42 +00:00
|
|
|
VAR(VAR_CURRENT_LIGHTS) = 4;
|
2005-07-30 21:11:48 +00:00
|
|
|
else
|
2003-08-18 10:46:42 +00:00
|
|
|
VAR(VAR_CURRENT_LIGHTS) = 0;
|
2003-11-10 09:16:41 +00:00
|
|
|
} else
|
2003-08-18 10:46:42 +00:00
|
|
|
VAR(VAR_CURRENT_LIGHTS) = a;
|
|
|
|
} else if (c == 1) {
|
|
|
|
_flashlight.xStrips = a;
|
|
|
|
_flashlight.yStrips = b;
|
|
|
|
}
|
2005-08-06 14:34:40 +00:00
|
|
|
_fullRedraw = true;
|
2003-08-18 10:46:42 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_loadRoomWithEgo() {
|
2003-04-26 16:37:35 +00:00
|
|
|
Actor *a;
|
2003-09-11 14:11:31 +00:00
|
|
|
int obj, room, x, y, x2, y2, dir;
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
obj = getVarOrDirectWord(PARAM_1);
|
|
|
|
room = getVarOrDirectByte(PARAM_2);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2003-05-23 13:24:41 +00:00
|
|
|
a = derefActor(VAR(VAR_EGO), "o2_loadRoomWithEgo");
|
2003-04-26 16:37:35 +00:00
|
|
|
|
|
|
|
a->putActor(0, 0, room);
|
|
|
|
_egoPositioned = false;
|
|
|
|
|
2007-02-04 01:24:43 +00:00
|
|
|
x = (int8)fetchScriptByte();
|
|
|
|
y = (int8)fetchScriptByte();
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2005-03-11 01:10:06 +00:00
|
|
|
startScene(a->_room, a, obj);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2003-09-11 14:11:31 +00:00
|
|
|
getObjectXYPos(obj, x2, y2, dir);
|
A long time ago, in a virtual machine far, far away...
It is a period of bug fixing. Rebel
developers, coding from a public
project, have won their umpteenth victory
against the evil Actor Walk Bugs.
During the debugging, programmers
used secret plans to the LucasArts'
ultimate tool, the SCUMM engine, an
extensible scripting system with enough
power to create an entire adventure.
Pursued by ensuing sinister regressions,
High King Fingolfin gleefully jumps up
and down, making use of the hotkey
that can save his games and restore
them back again later....
[With apologies to George Lucas. Good
riddance to bugs #751662, #771483, #959001,
#1329457, #1329498, #1329529, #1527672,
#1538260, #1571701, #1571705, #1571740,
and a warm welcome to the regressions
this change will cause. :-) ]
svn-id: r26090
2007-03-11 15:23:50 +00:00
|
|
|
AdjustBoxResult r = a->adjustXYToBeInBox(x2, y2);
|
|
|
|
x2 = r.x;
|
|
|
|
y2 = r.y;
|
2003-09-11 14:11:31 +00:00
|
|
|
a->putActor(x2, y2, _currentRoom);
|
2003-09-12 00:07:42 +00:00
|
|
|
a->setDirection(dir + 180);
|
2003-09-11 14:11:31 +00:00
|
|
|
|
2006-11-19 00:39:48 +00:00
|
|
|
camera._dest.x = camera._cur.x = a->getPos().x;
|
|
|
|
setCameraAt(a->getPos().x, a->getPos().y);
|
2003-04-26 16:37:35 +00:00
|
|
|
setCameraFollows(a);
|
|
|
|
|
2005-08-06 14:34:40 +00:00
|
|
|
_fullRedraw = true;
|
2003-04-26 16:37:35 +00:00
|
|
|
|
2011-02-07 17:53:34 +00:00
|
|
|
resetSentence(false);
|
2003-05-18 12:52:27 +00:00
|
|
|
|
2003-07-02 14:21:13 +00:00
|
|
|
if (x >= 0 && y >= 0) {
|
2003-04-26 16:37:35 +00:00
|
|
|
a->startWalkActor(x, y, -1);
|
|
|
|
}
|
|
|
|
runScript(5, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setOwnerOf() {
|
2003-04-26 16:37:35 +00:00
|
|
|
int obj, owner;
|
|
|
|
|
2003-11-16 18:34:33 +00:00
|
|
|
obj = getVarOrDirectWord(PARAM_1);
|
|
|
|
owner = getVarOrDirectByte(PARAM_2);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
|
|
|
setOwnerOf(obj, owner);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_delay() {
|
2003-05-04 00:41:52 +00:00
|
|
|
int delay = fetchScriptByte();
|
|
|
|
delay |= fetchScriptByte() << 8;
|
|
|
|
delay |= fetchScriptByte() << 16;
|
|
|
|
delay = 0xFFFFFF - delay;
|
|
|
|
|
|
|
|
vm.slot[_currentScript].delay = delay;
|
2005-04-07 21:13:01 +00:00
|
|
|
vm.slot[_currentScript].status = ssPaused;
|
2003-05-04 00:41:52 +00:00
|
|
|
o5_breakHere();
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_setCameraAt() {
|
2006-10-19 00:26:55 +00:00
|
|
|
setCameraAtEx(getVarOrDirectByte(PARAM_1) * V12_X_MULTIPLIER);
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_roomOps() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int a = getVarOrDirectByte(PARAM_1);
|
|
|
|
int b = getVarOrDirectByte(PARAM_2);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
|
|
|
_opcode = fetchScriptByte();
|
|
|
|
switch (_opcode & 0x1F) {
|
2003-11-10 09:16:41 +00:00
|
|
|
case 1: // SO_ROOM_SCROLL
|
2003-05-24 17:18:23 +00:00
|
|
|
a *= 8;
|
|
|
|
b *= 8;
|
2003-05-10 21:49:59 +00:00
|
|
|
if (a < (_screenWidth / 2))
|
|
|
|
a = (_screenWidth / 2);
|
|
|
|
if (b < (_screenWidth / 2))
|
|
|
|
b = (_screenWidth / 2);
|
|
|
|
if (a > _roomWidth - (_screenWidth / 2))
|
|
|
|
a = _roomWidth - (_screenWidth / 2);
|
|
|
|
if (b > _roomWidth - (_screenWidth / 2))
|
|
|
|
b = _roomWidth - (_screenWidth / 2);
|
2003-05-08 15:48:50 +00:00
|
|
|
VAR(VAR_CAMERA_MIN_X) = a;
|
|
|
|
VAR(VAR_CAMERA_MAX_X) = b;
|
2003-04-26 16:37:35 +00:00
|
|
|
break;
|
2003-11-10 09:16:41 +00:00
|
|
|
case 2: // SO_ROOM_COLOR
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version == 1) {
|
2003-08-29 06:46:12 +00:00
|
|
|
// V1 zak needs to know when room color is changed
|
2003-08-27 01:12:18 +00:00
|
|
|
_roomPalette[0] = 255;
|
|
|
|
_roomPalette[1] = a;
|
|
|
|
_roomPalette[2] = b;
|
2003-08-26 15:56:37 +00:00
|
|
|
} else {
|
2003-08-27 01:12:18 +00:00
|
|
|
_roomPalette[b] = a;
|
2003-08-26 15:56:37 +00:00
|
|
|
}
|
2003-09-11 12:48:02 +00:00
|
|
|
_fullRedraw = true;
|
2003-04-26 16:37:35 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_cutscene() {
|
2003-07-12 22:00:59 +00:00
|
|
|
vm.cutSceneData[0] = _userState | (_userPut ? 16 : 0);
|
2003-07-02 14:21:13 +00:00
|
|
|
vm.cutSceneData[1] = (int16)VAR(VAR_CURSORSTATE);
|
2003-05-21 14:00:19 +00:00
|
|
|
vm.cutSceneData[2] = _currentRoom;
|
|
|
|
vm.cutSceneData[3] = camera._mode;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-05-21 14:00:19 +00:00
|
|
|
VAR(VAR_CURSORSTATE) = 200;
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-07-12 22:00:59 +00:00
|
|
|
// Hide inventory, freeze scripts, hide cursor
|
2012-01-29 16:03:37 +00:00
|
|
|
setUserState(USERSTATE_SET_IFACE |
|
|
|
|
USERSTATE_SET_CURSOR |
|
|
|
|
USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON);
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-05-17 18:30:47 +00:00
|
|
|
_sentenceNum = 0;
|
2003-05-20 20:58:26 +00:00
|
|
|
stopScript(SENTENCE_SCRIPT);
|
2011-02-07 17:53:34 +00:00
|
|
|
resetSentence(false);
|
2003-05-21 14:00:19 +00:00
|
|
|
|
|
|
|
vm.cutScenePtr[0] = 0;
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_endCutscene() {
|
2003-05-21 14:00:19 +00:00
|
|
|
vm.cutSceneStackPointer = 0;
|
|
|
|
|
|
|
|
VAR(VAR_OVERRIDE) = 0;
|
|
|
|
vm.cutSceneScript[0] = 0;
|
|
|
|
vm.cutScenePtr[0] = 0;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-05-21 14:00:19 +00:00
|
|
|
VAR(VAR_CURSORSTATE) = vm.cutSceneData[1];
|
|
|
|
|
2003-07-12 22:00:59 +00:00
|
|
|
// Reset user state to values before cutscene
|
2012-01-29 16:03:37 +00:00
|
|
|
setUserState(vm.cutSceneData[0] | USERSTATE_SET_IFACE | USERSTATE_SET_CURSOR | USERSTATE_SET_FREEZE);
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_game.id == GID_MANIAC) && !(_game.platform == Common::kPlatformNES)) {
|
2003-05-21 17:34:01 +00:00
|
|
|
camera._mode = (byte) vm.cutSceneData[3];
|
2004-01-03 21:22:07 +00:00
|
|
|
if (camera._mode == kFollowActorCameraMode) {
|
2003-05-21 14:00:19 +00:00
|
|
|
actorFollowCamera(VAR(VAR_EGO));
|
|
|
|
} else if (vm.cutSceneData[2] != _currentRoom) {
|
|
|
|
startScene(vm.cutSceneData[2], 0, 0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
actorFollowCamera(VAR(VAR_EGO));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_beginOverride() {
|
2003-05-21 14:00:19 +00:00
|
|
|
vm.cutScenePtr[0] = _scriptPointer - _scriptOrgPointer;
|
|
|
|
vm.cutSceneScript[0] = _currentScript;
|
|
|
|
|
|
|
|
// Skip the jump instruction following the override instruction
|
|
|
|
fetchScriptByte();
|
2012-01-29 16:11:54 +00:00
|
|
|
ScummEngine::fetchScriptWord();
|
2003-04-26 20:03:38 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_chainScript() {
|
2010-12-02 00:27:46 +00:00
|
|
|
int script = getVarOrDirectByte(PARAM_1);
|
2003-07-24 17:44:00 +00:00
|
|
|
stopScript(vm.slot[_currentScript].number);
|
2003-04-26 16:37:35 +00:00
|
|
|
_currentScript = 0xFF;
|
2010-12-02 00:27:46 +00:00
|
|
|
runScript(script, 0, 0, 0);
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_pickupObject() {
|
2003-11-16 18:34:33 +00:00
|
|
|
int obj = getVarOrDirectWord(PARAM_1);
|
2003-04-26 16:37:35 +00:00
|
|
|
|
|
|
|
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);
|
2004-01-11 20:42:40 +00:00
|
|
|
markObjectRectAsDirty(obj);
|
2003-05-08 15:48:50 +00:00
|
|
|
putOwner(obj, VAR(VAR_EGO));
|
2006-10-29 14:45:31 +00:00
|
|
|
putState(obj, getState(obj) | kObjectState_08 | kObjectStateUntouchable);
|
2003-04-26 16:37:35 +00:00
|
|
|
clearDrawObjectQueue();
|
2003-05-21 06:00:16 +00:00
|
|
|
|
2003-06-14 12:23:30 +00:00
|
|
|
runInventoryScript(1);
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2005-03-27 21:21:05 +00:00
|
|
|
_sound->addSoundToQueue(51); // play 'pickup' sound
|
2003-04-26 16:37:35 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_cursorCommand() { // TODO: Define the magic numbers
|
2003-11-16 18:34:33 +00:00
|
|
|
uint16 cmd = getVarOrDirectWord(PARAM_1);
|
2003-07-12 22:00:59 +00:00
|
|
|
byte state = cmd >> 8;
|
2003-05-04 04:30:49 +00:00
|
|
|
|
2003-05-21 20:34:21 +00:00
|
|
|
if (cmd & 0xFF) {
|
2003-05-21 14:00:19 +00:00
|
|
|
VAR(VAR_CURSORSTATE) = cmd & 0xFF;
|
2003-05-18 12:52:27 +00:00
|
|
|
}
|
2003-11-08 21:59:32 +00:00
|
|
|
|
2003-07-12 22:00:59 +00:00
|
|
|
setUserState(state);
|
|
|
|
}
|
2003-05-21 06:14:02 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::setUserState(byte state) {
|
2012-01-29 16:03:37 +00:00
|
|
|
if (state & USERSTATE_SET_IFACE) { // Userface
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2012-01-29 16:03:37 +00:00
|
|
|
_userState = (_userState & ~USERSTATE_IFACE_ALL) | (state & USERSTATE_IFACE_ALL);
|
2005-03-27 21:21:05 +00:00
|
|
|
else
|
2012-01-29 16:03:37 +00:00
|
|
|
_userState = state & USERSTATE_IFACE_ALL;
|
2003-05-21 07:22:43 +00:00
|
|
|
}
|
2003-05-04 04:30:49 +00:00
|
|
|
|
2012-01-29 16:03:37 +00:00
|
|
|
if (state & USERSTATE_SET_FREEZE) { // Freeze
|
|
|
|
if (state & USERSTATE_FREEZE_ON)
|
2003-05-04 04:30:49 +00:00
|
|
|
freezeScripts(0);
|
|
|
|
else
|
|
|
|
unfreezeScripts();
|
|
|
|
}
|
|
|
|
|
2012-01-29 16:03:37 +00:00
|
|
|
if (state & USERSTATE_SET_CURSOR) { // Cursor Show/Hide
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2012-01-29 16:03:37 +00:00
|
|
|
_userState = (_userState & ~USERSTATE_CURSOR_ON) | (state & USERSTATE_CURSOR_ON);
|
|
|
|
if (state & USERSTATE_CURSOR_ON) {
|
2003-05-21 07:22:43 +00:00
|
|
|
_userPut = 1;
|
2003-05-10 23:47:39 +00:00
|
|
|
_cursor.state = 1;
|
2003-05-21 07:22:43 +00:00
|
|
|
} else {
|
|
|
|
_userPut = 0;
|
2003-05-10 23:47:39 +00:00
|
|
|
_cursor.state = 0;
|
2003-05-21 07:22:43 +00:00
|
|
|
}
|
2003-05-04 04:30:49 +00:00
|
|
|
}
|
2003-08-24 01:47:45 +00:00
|
|
|
|
|
|
|
// Hide all verbs and inventory
|
2003-10-02 17:43:02 +00:00
|
|
|
Common::Rect rect;
|
2007-09-08 11:15:27 +00:00
|
|
|
rect.top = _virtscr[kVerbVirtScreen].topline;
|
|
|
|
rect.bottom = _virtscr[kVerbVirtScreen].topline + 8 * 88;
|
|
|
|
rect.right = _virtscr[kVerbVirtScreen].w - 1;
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES) {
|
2005-04-01 01:41:20 +00:00
|
|
|
rect.left = 16;
|
|
|
|
} else {
|
|
|
|
rect.left = 0;
|
|
|
|
}
|
2006-09-17 23:35:09 +00:00
|
|
|
restoreBackground(rect);
|
2003-08-24 01:47:45 +00:00
|
|
|
|
|
|
|
// Draw all verbs and inventory
|
|
|
|
redrawVerbs();
|
|
|
|
runInventoryScript(1);
|
2003-04-26 20:03:38 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_getActorWalkBox() {
|
2003-04-26 20:03:38 +00:00
|
|
|
Actor *a;
|
|
|
|
getResultPos();
|
2003-11-16 18:34:33 +00:00
|
|
|
a = derefActor(getVarOrDirectByte(PARAM_1), "o2_getActorWalkbox");
|
2009-05-26 01:25:44 +00:00
|
|
|
setResult(a->isInCurrentRoom() ? a->_walkbox: 0xFF);
|
2003-04-26 20:03:38 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_dummy() {
|
2009-04-19 01:00:31 +00:00
|
|
|
// Opcode 0xEE is used in maniac and zak but has no purpose
|
|
|
|
if (_opcode != 0xEE)
|
2003-08-18 10:46:42 +00:00
|
|
|
warning("o2_dummy invoked (opcode %d)", _opcode);
|
2003-05-04 00:29:52 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine_v2::o2_switchCostumeSet() {
|
2003-08-14 11:40:50 +00:00
|
|
|
// NES version of maniac uses this to switch between the two
|
|
|
|
// groups of costumes it has
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.platform == Common::kPlatformNES)
|
2005-03-24 03:22:32 +00:00
|
|
|
NES_loadCostumeSet(fetchScriptByte());
|
2006-02-20 16:51:30 +00:00
|
|
|
else if (_game.platform == Common::kPlatformC64)
|
2005-05-18 00:46:30 +00:00
|
|
|
fetchScriptByte();
|
2005-03-13 23:18:59 +00:00
|
|
|
else
|
2003-08-14 11:40:50 +00:00
|
|
|
o2_dummy();
|
|
|
|
}
|
|
|
|
|
2011-02-07 17:53:34 +00:00
|
|
|
void ScummEngine_v2::resetSentence(bool walking) {
|
2006-03-02 12:14:06 +00:00
|
|
|
VAR(VAR_SENTENCE_VERB) = VAR(VAR_BACKUP_VERB);
|
|
|
|
VAR(VAR_SENTENCE_OBJECT1) = 0;
|
|
|
|
VAR(VAR_SENTENCE_OBJECT2) = 0;
|
|
|
|
VAR(VAR_SENTENCE_PREPOSITION) = 0;
|
2003-05-18 12:52:27 +00:00
|
|
|
}
|
2003-10-03 18:33:57 +00:00
|
|
|
|
2005-04-20 23:53:29 +00:00
|
|
|
void ScummEngine_v2::runInventoryScript(int i) {
|
|
|
|
redrawV2Inventory();
|
|
|
|
}
|
|
|
|
|
2003-10-03 18:33:57 +00:00
|
|
|
} // End of namespace Scumm
|