2004-08-23 10:34:50 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2001 Ludvig Strigeus
|
|
|
|
* Copyright (C) 2001-2004 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 "common/config-manager.h"
|
|
|
|
|
|
|
|
#include "scumm/actor.h"
|
|
|
|
#include "scumm/charset.h"
|
|
|
|
#include "scumm/intern.h"
|
|
|
|
#include "scumm/object.h"
|
|
|
|
#include "scumm/resource.h"
|
|
|
|
#include "scumm/resource_v7he.h"
|
|
|
|
#include "scumm/scumm.h"
|
|
|
|
#include "scumm/sound.h"
|
|
|
|
#include "scumm/verbs.h"
|
|
|
|
#include "scumm/smush/smush_player.h"
|
|
|
|
|
|
|
|
#include "sound/mididrv.h"
|
|
|
|
#include "sound/mixer.h"
|
|
|
|
|
|
|
|
namespace Scumm {
|
|
|
|
|
|
|
|
#define OPCODE(x) { &ScummEngine_v72he::x, #x }
|
|
|
|
|
|
|
|
void ScummEngine_v72he::setupOpcodes() {
|
|
|
|
static const OpcodeEntryV72he opcodes[256] = {
|
|
|
|
/* 00 */
|
|
|
|
OPCODE(o6_pushByte),
|
|
|
|
OPCODE(o6_pushWord),
|
2004-08-25 08:49:34 +00:00
|
|
|
OPCODE(o72_pushDWord),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_pushWordVar),
|
|
|
|
/* 04 */
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_addMessageToStack),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayRead),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 08 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayIndexedRead),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 0C */
|
|
|
|
OPCODE(o6_dup),
|
|
|
|
OPCODE(o6_not),
|
|
|
|
OPCODE(o6_eq),
|
|
|
|
OPCODE(o6_neq),
|
|
|
|
/* 10 */
|
|
|
|
OPCODE(o6_gt),
|
|
|
|
OPCODE(o6_lt),
|
|
|
|
OPCODE(o6_le),
|
|
|
|
OPCODE(o6_ge),
|
|
|
|
/* 14 */
|
|
|
|
OPCODE(o6_add),
|
|
|
|
OPCODE(o6_sub),
|
|
|
|
OPCODE(o6_mul),
|
|
|
|
OPCODE(o6_div),
|
|
|
|
/* 18 */
|
|
|
|
OPCODE(o6_land),
|
|
|
|
OPCODE(o6_lor),
|
|
|
|
OPCODE(o6_pop),
|
2004-08-24 11:17:28 +00:00
|
|
|
OPCODE(o72_compareStackList),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 1C */
|
2004-08-28 09:19:53 +00:00
|
|
|
OPCODE(o72_unknown1C),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 20 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 24 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-28 14:05:33 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 28 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 2C */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 30 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 34 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 38 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 3C */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* 40 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_writeWordVar),
|
|
|
|
/* 44 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayWrite),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 48 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayIndexedWrite),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 4C */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_wordVarInc),
|
|
|
|
/* 50 */
|
2004-08-26 14:56:10 +00:00
|
|
|
OPCODE(o72_unknown50),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayInc),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 54 */
|
2004-08-25 02:34:17 +00:00
|
|
|
OPCODE(o72_objectX),
|
|
|
|
OPCODE(o72_objectY),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_wordVarDec),
|
|
|
|
/* 58 */
|
2004-08-26 06:08:41 +00:00
|
|
|
OPCODE(o72_getTimer),
|
|
|
|
OPCODE(o72_setTimer),
|
2004-08-23 14:23:40 +00:00
|
|
|
OPCODE(o6_invalid),
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_wordArrayDec),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 5C */
|
|
|
|
OPCODE(o6_if),
|
|
|
|
OPCODE(o6_ifNot),
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_startScript),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_startScriptQuick),
|
|
|
|
/* 60 */
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_startObject),
|
2004-08-23 14:11:53 +00:00
|
|
|
OPCODE(o72_drawObject),
|
|
|
|
OPCODE(o72_unknown62),
|
2004-08-25 02:12:03 +00:00
|
|
|
OPCODE(o72_getArrayDimSize),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 64 */
|
2004-08-28 09:19:53 +00:00
|
|
|
OPCODE(o72_getNumFreeArrays),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_stopObjectCode),
|
|
|
|
OPCODE(o6_stopObjectCode),
|
|
|
|
OPCODE(o6_endCutscene),
|
|
|
|
/* 68 */
|
|
|
|
OPCODE(o6_cutscene),
|
|
|
|
OPCODE(o6_stopMusic),
|
|
|
|
OPCODE(o6_freezeUnfreeze),
|
|
|
|
OPCODE(o7_cursorCommand),
|
|
|
|
/* 6C */
|
|
|
|
OPCODE(o6_breakHere),
|
|
|
|
OPCODE(o6_ifClassOfIs),
|
|
|
|
OPCODE(o6_setClass),
|
|
|
|
OPCODE(o6_getState),
|
|
|
|
/* 70 */
|
|
|
|
OPCODE(o6_setState),
|
|
|
|
OPCODE(o6_setOwner),
|
|
|
|
OPCODE(o6_getOwner),
|
|
|
|
OPCODE(o6_jump),
|
|
|
|
/* 74 */
|
|
|
|
OPCODE(o7_startSound),
|
|
|
|
OPCODE(o6_stopSound),
|
|
|
|
OPCODE(o6_startMusic),
|
|
|
|
OPCODE(o6_stopObjectScript),
|
|
|
|
/* 78 */
|
|
|
|
OPCODE(o6_panCameraTo),
|
|
|
|
OPCODE(o6_actorFollowCamera),
|
|
|
|
OPCODE(o6_setCameraAt),
|
|
|
|
OPCODE(o6_loadRoom),
|
|
|
|
/* 7C */
|
|
|
|
OPCODE(o6_stopScript),
|
|
|
|
OPCODE(o6_walkActorToObj),
|
|
|
|
OPCODE(o6_walkActorTo),
|
|
|
|
OPCODE(o6_putActorAtXY),
|
|
|
|
/* 80 */
|
|
|
|
OPCODE(o6_putActorAtObject),
|
|
|
|
OPCODE(o6_faceActor),
|
|
|
|
OPCODE(o6_animateActor),
|
|
|
|
OPCODE(o6_doSentence),
|
|
|
|
/* 84 */
|
2004-08-28 14:05:33 +00:00
|
|
|
OPCODE(o72_pickupObject),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_loadRoomWithEgo),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_getRandomNumber),
|
|
|
|
/* 88 */
|
|
|
|
OPCODE(o6_getRandomNumberRange),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_getActorMoving),
|
|
|
|
OPCODE(o6_isScriptRunning),
|
|
|
|
/* 8C */
|
|
|
|
OPCODE(o7_getActorRoom),
|
|
|
|
OPCODE(o6_getObjectX),
|
|
|
|
OPCODE(o6_getObjectY),
|
|
|
|
OPCODE(o6_getObjectOldDir),
|
|
|
|
/* 90 */
|
|
|
|
OPCODE(o6_getActorWalkBox),
|
|
|
|
OPCODE(o6_getActorCostume),
|
|
|
|
OPCODE(o6_findInventory),
|
|
|
|
OPCODE(o6_getInventoryCount),
|
|
|
|
/* 94 */
|
|
|
|
OPCODE(o6_getVerbFromXY),
|
|
|
|
OPCODE(o6_beginOverride),
|
|
|
|
OPCODE(o6_endOverride),
|
|
|
|
OPCODE(o6_setObjectName),
|
|
|
|
/* 98 */
|
|
|
|
OPCODE(o6_isSoundRunning),
|
|
|
|
OPCODE(o6_setBoxFlags),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-24 11:18:45 +00:00
|
|
|
OPCODE(o7_resourceRoutines),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* 9C */
|
|
|
|
OPCODE(o6_roomOps),
|
|
|
|
OPCODE(o6_actorOps),
|
|
|
|
OPCODE(o6_verbOps),
|
|
|
|
OPCODE(o6_getActorFromXY),
|
|
|
|
/* A0 */
|
|
|
|
OPCODE(o6_findObject),
|
|
|
|
OPCODE(o6_pseudoRoom),
|
|
|
|
OPCODE(o6_getActorElevation),
|
|
|
|
OPCODE(o6_getVerbEntrypoint),
|
|
|
|
/* A4 */
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_arrayOps),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_saveRestoreVerbs),
|
|
|
|
OPCODE(o6_drawBox),
|
|
|
|
OPCODE(o6_pop),
|
|
|
|
/* A8 */
|
|
|
|
OPCODE(o6_getActorWidth),
|
|
|
|
OPCODE(o6_wait),
|
|
|
|
OPCODE(o6_getActorScaleX),
|
|
|
|
OPCODE(o6_getActorAnimCounter1),
|
|
|
|
/* AC */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_isAnyOf),
|
|
|
|
OPCODE(o7_quitPauseRestart),
|
|
|
|
OPCODE(o6_isActorInBox),
|
|
|
|
/* B0 */
|
|
|
|
OPCODE(o6_delay),
|
|
|
|
OPCODE(o6_delaySeconds),
|
|
|
|
OPCODE(o6_delayMinutes),
|
|
|
|
OPCODE(o6_stopSentence),
|
|
|
|
/* B4 */
|
|
|
|
OPCODE(o6_printLine),
|
|
|
|
OPCODE(o6_printCursor),
|
|
|
|
OPCODE(o6_printDebug),
|
|
|
|
OPCODE(o6_printSystem),
|
|
|
|
/* B8 */
|
|
|
|
OPCODE(o6_printActor),
|
|
|
|
OPCODE(o6_printEgo),
|
|
|
|
OPCODE(o6_talkActor),
|
|
|
|
OPCODE(o6_talkEgo),
|
|
|
|
/* BC */
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_dimArray),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_dummy),
|
|
|
|
OPCODE(o6_startObjectQuick),
|
|
|
|
OPCODE(o6_startScriptQuick2),
|
|
|
|
/* C0 */
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_dim2dimArray),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* C4 */
|
|
|
|
OPCODE(o6_abs),
|
|
|
|
OPCODE(o6_distObjectObject),
|
|
|
|
OPCODE(o6_distObjectPt),
|
|
|
|
OPCODE(o6_distPtPt),
|
|
|
|
/* C8 */
|
|
|
|
OPCODE(o6_kernelGetFunctions),
|
2004-08-28 14:05:33 +00:00
|
|
|
OPCODE(o7_kernelSetFunctions),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_delayFrames),
|
|
|
|
OPCODE(o6_pickOneOf),
|
|
|
|
/* CC */
|
|
|
|
OPCODE(o6_pickOneOfDefault),
|
|
|
|
OPCODE(o6_stampObject),
|
2004-08-26 06:08:41 +00:00
|
|
|
OPCODE(o72_unknownCE),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* D0 */
|
|
|
|
OPCODE(o6_getDateTime),
|
|
|
|
OPCODE(o6_stopTalking),
|
|
|
|
OPCODE(o6_getAnimateVariable),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* D4 */
|
2004-08-25 06:34:33 +00:00
|
|
|
OPCODE(o72_shuffle),
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_jumpToScript),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_band),
|
|
|
|
OPCODE(o6_bor),
|
|
|
|
/* D8 */
|
|
|
|
OPCODE(o6_isRoomScriptRunning),
|
|
|
|
OPCODE(o6_closeFile),
|
2004-08-25 12:48:47 +00:00
|
|
|
OPCODE(o72_openFile),
|
|
|
|
OPCODE(o72_readFile),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* DC */
|
2004-08-25 12:48:47 +00:00
|
|
|
OPCODE(o72_writeFile),
|
2004-08-25 02:12:03 +00:00
|
|
|
OPCODE(o72_findAllObjects),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_deleteFile),
|
|
|
|
OPCODE(o6_rename),
|
|
|
|
/* E0 */
|
|
|
|
OPCODE(o6_soundOps),
|
2004-08-24 11:17:28 +00:00
|
|
|
OPCODE(o72_getPixel),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_localizeArray),
|
2004-08-25 02:12:03 +00:00
|
|
|
OPCODE(o72_pickVarRandom),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* E4 */
|
|
|
|
OPCODE(o6_setBoxSet),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-28 09:19:53 +00:00
|
|
|
OPCODE(o7_unknownEF),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* E8 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_seekFilePos),
|
2004-08-25 02:12:03 +00:00
|
|
|
OPCODE(o72_redimArray),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_readFilePos),
|
|
|
|
/* EC */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-28 03:18:52 +00:00
|
|
|
OPCODE(o7_stringLen),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* F0 */
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_readINI),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* F4 */
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_unknownF4),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
/* F8 */
|
2004-08-26 08:47:07 +00:00
|
|
|
OPCODE(o72_unknownF8),
|
|
|
|
OPCODE(o72_unknownF9),
|
2004-08-23 12:19:08 +00:00
|
|
|
OPCODE(o72_unknownFA),
|
|
|
|
OPCODE(o72_unknownFB),
|
2004-08-23 10:34:50 +00:00
|
|
|
/* FC */
|
2004-08-25 07:18:18 +00:00
|
|
|
OPCODE(o72_unknownFC),
|
2004-08-23 10:34:50 +00:00
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
OPCODE(o6_invalid),
|
|
|
|
};
|
|
|
|
|
|
|
|
_opcodesV72he = opcodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::executeOpcode(byte i) {
|
|
|
|
OpcodeProcV72he op = _opcodesV72he[i].proc;
|
|
|
|
(this->*op) ();
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *ScummEngine_v72he::getOpcodeDesc(byte i) {
|
|
|
|
return _opcodesV72he[i].desc;
|
|
|
|
}
|
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
static int arrayDataSizes[] = {0, 1, 4, 8, 8, 16, 32};
|
|
|
|
|
|
|
|
ScummEngine_v72he::ArrayHeader *ScummEngine_v72he::defineArray(int array, int type, int dim2start, int dim2end,
|
|
|
|
int dim1start, int dim1end) {
|
2004-08-28 09:19:53 +00:00
|
|
|
debug(5,"defineArray (array %d, dim2start %d, dim2end %d dim1start %d dim1end %d", array, dim2start, dim2end, dim1start, dim1end);
|
2004-08-25 06:34:33 +00:00
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
int id;
|
|
|
|
int size;
|
|
|
|
ArrayHeader *ah;
|
|
|
|
|
|
|
|
assert(dim2start >= 0 && dim2start <= dim2end);
|
|
|
|
assert(dim1start >= 0 && dim1start <= dim1end);
|
2004-08-25 06:34:33 +00:00
|
|
|
assert(0 <= type && type <= 6);
|
2004-08-25 02:12:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (type == kBitArray || type == kNibbleArray)
|
|
|
|
type = kByteArray;
|
|
|
|
|
|
|
|
nukeArray(array);
|
|
|
|
|
|
|
|
id = findFreeArrayId();
|
|
|
|
|
|
|
|
if (array & 0x80000000) {
|
|
|
|
error("Can't define bit variable as array pointer");
|
|
|
|
}
|
|
|
|
|
|
|
|
size = arrayDataSizes[type];
|
|
|
|
|
|
|
|
writeVar(array, id);
|
|
|
|
|
|
|
|
size *= dim2end - dim2start + 1;
|
|
|
|
size *= dim1end - dim1start + 1;
|
|
|
|
size >>= 3;
|
|
|
|
|
|
|
|
ah = (ArrayHeader *)createResource(rtString, id, size + sizeof(ArrayHeader));
|
|
|
|
|
|
|
|
ah->type = TO_LE_32(type);
|
|
|
|
ah->dim1start = TO_LE_32(dim1start);
|
|
|
|
ah->dim1end = TO_LE_32(dim1end);
|
|
|
|
ah->dim2start = TO_LE_32(dim2start);
|
|
|
|
ah->dim2end = TO_LE_32(dim2end);
|
|
|
|
|
|
|
|
return ah;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ScummEngine_v72he::readArray(int array, int idx2, int idx1) {
|
2004-08-28 09:19:53 +00:00
|
|
|
debug(5, "readArray (array %d, idx2 %d, idx1 %d)", array, idx2, idx1);
|
2004-08-25 06:34:33 +00:00
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
if (readVar(array) == 0)
|
|
|
|
error("readArray: Reference to zeroed array pointer");
|
|
|
|
|
|
|
|
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
|
|
|
|
|
|
|
|
if (ah == NULL || ah->data == NULL)
|
|
|
|
error("readArray: invalid array %d (%d)", array, readVar(array));
|
|
|
|
|
2004-08-25 11:34:28 +00:00
|
|
|
if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) ||
|
|
|
|
idx1 < (int)FROM_LE_32(ah->dim2start) || idx1 > (int)FROM_LE_32(ah->dim1end)) {
|
2004-08-25 02:12:03 +00:00
|
|
|
error("readArray: array %d out of bounds: [%d, %d] exceeds [%d..%d, %d..%d]",
|
|
|
|
array, idx1, idx2, FROM_LE_32(ah->dim1start), FROM_LE_32(ah->dim1end),
|
|
|
|
FROM_LE_32(ah->dim2start), FROM_LE_32(ah->dim2end));
|
|
|
|
}
|
2004-08-25 06:34:33 +00:00
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
const int offset = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
|
|
|
|
(idx2 - FROM_LE_32(ah->dim2start)) - FROM_LE_32(ah->dim1start) + idx1;
|
|
|
|
|
|
|
|
switch (FROM_LE_32(ah->type)) {
|
|
|
|
case kByteArray:
|
|
|
|
case kStringArray:
|
|
|
|
return ah->data[offset];
|
|
|
|
|
|
|
|
case kIntArray:
|
|
|
|
return (int16)READ_LE_UINT16(ah->data + offset * 2);
|
|
|
|
|
|
|
|
case kDwordArray:
|
|
|
|
return (int32)READ_LE_UINT32(ah->data + offset * 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::writeArray(int array, int idx2, int idx1, int value) {
|
2004-08-28 09:19:53 +00:00
|
|
|
debug(5, "writeArray (array %d, idx2 %d, idx1 %d, value %d)", array, idx2, idx1, value);
|
2004-08-25 06:34:33 +00:00
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
if (readVar(array) == 0)
|
|
|
|
error("writeArray: Reference to zeroed array pointer");
|
|
|
|
|
|
|
|
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array));
|
|
|
|
|
|
|
|
if (!ah)
|
|
|
|
error("writeArray: Invalid array (%d) reference", readVar(array));
|
|
|
|
|
2004-08-25 11:34:28 +00:00
|
|
|
if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) ||
|
|
|
|
idx1 < (int)FROM_LE_32(ah->dim1start) || idx1 > (int)FROM_LE_32(ah->dim1end)) {
|
2004-08-25 02:12:03 +00:00
|
|
|
error("writeArray: array %d out of bounds: [%d, %d] exceeds [%d..%d, %d..%d]",
|
|
|
|
array, idx1, idx2, FROM_LE_32(ah->dim1start), FROM_LE_32(ah->dim1end),
|
|
|
|
FROM_LE_32(ah->dim2start), FROM_LE_32(ah->dim2end));
|
|
|
|
}
|
|
|
|
|
|
|
|
const int offset = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
|
|
|
|
(idx2 - FROM_LE_32(ah->dim2start)) - FROM_LE_32(ah->dim1start) + idx1;
|
|
|
|
|
|
|
|
switch (FROM_LE_32(ah->type)) {
|
|
|
|
case kByteArray:
|
|
|
|
case kStringArray:
|
|
|
|
ah->data[offset] = value;
|
2004-08-25 08:49:34 +00:00
|
|
|
break;
|
2004-08-25 02:12:03 +00:00
|
|
|
|
|
|
|
case kIntArray:
|
|
|
|
WRITE_LE_UINT16(ah->data + offset * 2, value);
|
2004-08-25 08:49:34 +00:00
|
|
|
break;
|
2004-08-25 02:12:03 +00:00
|
|
|
|
|
|
|
case kDwordArray:
|
|
|
|
WRITE_LE_UINT32(ah->data + offset * 4, value);
|
2004-08-25 08:49:34 +00:00
|
|
|
break;
|
2004-08-24 16:02:26 +00:00
|
|
|
}
|
|
|
|
}
|
2004-08-23 10:34:50 +00:00
|
|
|
|
2004-08-25 02:48:44 +00:00
|
|
|
void ScummEngine_v72he::readArrayFromIndexFile() {
|
|
|
|
int num;
|
|
|
|
int a, b, c;
|
|
|
|
|
|
|
|
while ((num = _fileHandle.readUint16LE()) != 0) {
|
|
|
|
a = _fileHandle.readUint16LE();
|
|
|
|
b = _fileHandle.readUint16LE();
|
|
|
|
c = _fileHandle.readUint16LE();
|
2004-08-25 07:18:18 +00:00
|
|
|
|
2004-08-25 02:48:44 +00:00
|
|
|
if (c == 1)
|
|
|
|
defineArray(num, kBitArray, 0, a, 0, b);
|
|
|
|
else
|
|
|
|
defineArray(num, kDwordArray, 0, a, 0, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-25 08:49:34 +00:00
|
|
|
void ScummEngine_v72he::o72_pushDWord() {
|
2004-08-25 02:34:17 +00:00
|
|
|
int a;
|
|
|
|
if (*_lastCodePtr + sizeof(MemBlkHeader) != _scriptOrgPointer) {
|
|
|
|
uint32 oldoffs = _scriptPointer - _scriptOrgPointer;
|
|
|
|
getScriptBaseAddress();
|
|
|
|
_scriptPointer = _scriptOrgPointer + oldoffs;
|
|
|
|
}
|
|
|
|
a = READ_LE_UINT32(_scriptPointer);
|
|
|
|
_scriptPointer += 4;
|
|
|
|
push(a);
|
|
|
|
}
|
|
|
|
|
2004-08-25 06:34:33 +00:00
|
|
|
void ScummEngine_v72he::o72_addMessageToStack() {
|
|
|
|
_stringLength = resStrLen(_scriptPointer) + 1;
|
|
|
|
addMessageToStack(_scriptPointer, _stringBuffer, _stringLength);
|
|
|
|
|
2004-08-28 09:19:53 +00:00
|
|
|
debug(0,"o72_addMessageToStack(\"%s\")", _scriptPointer);
|
2004-08-25 06:34:33 +00:00
|
|
|
|
|
|
|
_scriptPointer += _stringLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_wordArrayRead() {
|
|
|
|
int base = pop();
|
|
|
|
push(readArray(fetchScriptWord(), 0, base));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_wordArrayIndexedRead() {
|
|
|
|
int base = pop();
|
|
|
|
int idx = pop();
|
|
|
|
push(readArray(fetchScriptWord(), idx, base));
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
2004-08-24 11:17:28 +00:00
|
|
|
void ScummEngine_v72he::o72_compareStackList() {
|
|
|
|
int args[128], i;
|
|
|
|
int num = getStackList(args, ARRAYSIZE(args));
|
|
|
|
int value = pop();
|
|
|
|
|
|
|
|
if (num) {
|
2004-08-25 02:34:17 +00:00
|
|
|
for (i = 1; i < num; i++) {
|
2004-08-24 15:08:26 +00:00
|
|
|
if (args[i] == value) {
|
2004-08-24 11:17:28 +00:00
|
|
|
push(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2004-08-23 10:34:50 +00:00
|
|
|
push(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-28 09:19:53 +00:00
|
|
|
void ScummEngine_v72he::o72_unknown1C() {
|
2004-08-28 14:05:33 +00:00
|
|
|
// HE 90+ specific
|
|
|
|
if (_heversion < 90)
|
|
|
|
error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer);
|
|
|
|
|
|
|
|
// For Pajame Sam 2 demo
|
2004-08-28 09:19:53 +00:00
|
|
|
// Incomplete
|
|
|
|
int value = fetchScriptByte();
|
|
|
|
value -= 46;
|
|
|
|
|
|
|
|
if (value == 10) {
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
warning("o72_unknown1C stub (%d)", value);
|
|
|
|
}
|
|
|
|
|
2004-08-25 06:34:33 +00:00
|
|
|
void ScummEngine_v72he::o72_wordArrayWrite() {
|
|
|
|
int a = pop();
|
|
|
|
writeArray(fetchScriptWord(), 0, pop(), a);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_wordArrayIndexedWrite() {
|
|
|
|
int val = pop();
|
|
|
|
int base = pop();
|
|
|
|
writeArray(fetchScriptWord(), pop(), base, val);
|
|
|
|
}
|
|
|
|
|
2004-08-26 14:56:10 +00:00
|
|
|
void ScummEngine_v72he::o72_unknown50() {
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
idx = vm.cutSceneStackPointer;
|
|
|
|
vm.cutSceneStackPointer = 0;
|
|
|
|
vm.cutScenePtr[idx] = 0;
|
|
|
|
vm.cutSceneScript[idx] = 0;
|
|
|
|
|
|
|
|
VAR(VAR_OVERRIDE) = 0;
|
|
|
|
}
|
|
|
|
|
2004-08-25 06:34:33 +00:00
|
|
|
void ScummEngine_v72he::o72_wordArrayInc() {
|
|
|
|
int var = fetchScriptWord();
|
|
|
|
int base = pop();
|
|
|
|
writeArray(var, 0, base, readArray(var, 0, base) + 1);
|
|
|
|
}
|
|
|
|
|
2004-08-25 02:34:17 +00:00
|
|
|
void ScummEngine_v72he::o72_objectX() {
|
|
|
|
int object = pop();
|
|
|
|
int objnum = getObjectIndex(object);
|
|
|
|
|
|
|
|
if (objnum == -1) {
|
|
|
|
push(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
push(_objs[objnum].x_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_objectY() {
|
|
|
|
int object = pop();
|
|
|
|
int objnum = getObjectIndex(object);
|
|
|
|
|
|
|
|
if (objnum == -1) {
|
|
|
|
push(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
push(_objs[objnum].y_pos);
|
|
|
|
}
|
|
|
|
|
2004-08-26 06:08:41 +00:00
|
|
|
void ScummEngine_v72he::o72_getTimer() {
|
2004-08-26 14:28:42 +00:00
|
|
|
int timer = pop();
|
|
|
|
int cmd = fetchScriptByte();
|
|
|
|
|
|
|
|
if (cmd == 10) {
|
|
|
|
checkRange(3, 1, timer, "o72_getTimer: Timer %d out of range(%d)");
|
|
|
|
int diff = _system->get_msecs() - _timers[timer];
|
|
|
|
push(diff);
|
|
|
|
} else {
|
2004-08-26 06:08:41 +00:00
|
|
|
push(0);
|
2004-08-26 14:28:42 +00:00
|
|
|
}
|
2004-08-26 06:08:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_setTimer() {
|
2004-08-26 14:28:42 +00:00
|
|
|
int timer = pop();
|
|
|
|
int cmd = fetchScriptByte();
|
|
|
|
|
|
|
|
if (cmd == 158) {
|
|
|
|
checkRange(3, 1, timer, "o72_setTimer: Timer %d out of range(%d)");
|
|
|
|
_timers[timer] = _system->get_msecs();
|
|
|
|
} else {
|
|
|
|
error("TIMER command %d?", cmd);
|
|
|
|
}
|
2004-08-26 06:08:41 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 06:34:33 +00:00
|
|
|
void ScummEngine_v72he::o72_wordArrayDec() {
|
|
|
|
int var = fetchScriptWord();
|
|
|
|
int base = pop();
|
|
|
|
writeArray(var, 0, base, readArray(var, 0, base) - 1);
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_startScript() {
|
2004-08-23 11:20:25 +00:00
|
|
|
int args[16];
|
|
|
|
int script, flags;
|
|
|
|
|
|
|
|
getStackList(args, ARRAYSIZE(args));
|
|
|
|
script = pop();
|
|
|
|
flags = fetchScriptByte();
|
2004-08-23 10:34:50 +00:00
|
|
|
|
2004-08-23 11:20:25 +00:00
|
|
|
runScript(script, (flags == 199 || flags == 200), (flags == 195 || flags == 200), args);
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_startObject() {
|
2004-08-23 11:20:25 +00:00
|
|
|
int args[16];
|
|
|
|
int script, entryp;
|
|
|
|
int flags;
|
|
|
|
getStackList(args, ARRAYSIZE(args));
|
|
|
|
entryp = pop();
|
|
|
|
script = pop();
|
|
|
|
flags = fetchScriptByte();
|
|
|
|
runObjectScript(script, entryp, (flags == 199 || flags == 200), (flags == 195 || flags == 200), args);
|
2004-08-23 10:34:50 +00:00
|
|
|
}
|
|
|
|
|
2004-08-23 14:11:53 +00:00
|
|
|
void ScummEngine_v72he::o72_drawObject() {
|
|
|
|
int subOp = fetchScriptByte();
|
|
|
|
int state = 0, y = -1, x = -1;
|
|
|
|
|
|
|
|
switch (subOp) {
|
|
|
|
case 62:
|
|
|
|
state = pop();
|
|
|
|
y = pop();
|
|
|
|
x = pop();
|
|
|
|
break;
|
|
|
|
case 63:
|
|
|
|
state = pop();
|
|
|
|
if (state == 0)
|
|
|
|
state = 1;
|
|
|
|
break;
|
|
|
|
case 65:
|
|
|
|
state = 1;
|
|
|
|
y = pop();
|
|
|
|
x = pop();
|
2004-08-25 08:54:43 +00:00
|
|
|
break;
|
2004-08-23 14:11:53 +00:00
|
|
|
default:
|
|
|
|
warning("o72_drawObject: default case %d", subOp);
|
|
|
|
}
|
|
|
|
|
|
|
|
int object = pop();
|
|
|
|
int objnum = getObjectIndex(object);
|
|
|
|
if (objnum == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (y != -1 && x != -1) {
|
|
|
|
_objs[objnum].x_pos = x * 8;
|
|
|
|
_objs[objnum].y_pos = y * 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state != -1) {
|
|
|
|
addObjectToDrawQue(objnum);
|
|
|
|
putState(object, state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_unknown62() {
|
|
|
|
int a = pop();
|
|
|
|
// unknown62(a, 0, 0, 4);
|
|
|
|
warning("o72_unknown62 stub (%d)", a);
|
|
|
|
}
|
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
void ScummEngine_v72he::o72_getArrayDimSize() {
|
2004-08-24 11:17:28 +00:00
|
|
|
int subOp = fetchScriptByte();
|
2004-08-25 02:12:03 +00:00
|
|
|
int32 val1, val2;
|
|
|
|
ArrayHeader *ah;
|
2004-08-24 11:17:28 +00:00
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
switch (subOp) {
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
ah = (ArrayHeader *)getResourceAddress(rtString, readVar(fetchScriptWord()));
|
|
|
|
val1 = FROM_LE_32(ah->dim1end);
|
|
|
|
val2 = FROM_LE_32(ah->dim1start);
|
|
|
|
push(val1 - val2 + 1);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ah = (ArrayHeader *)getResourceAddress(rtString, readVar(fetchScriptWord()));
|
|
|
|
val1 = FROM_LE_32(ah->dim2end);
|
|
|
|
val2 = FROM_LE_32(ah->dim2start);
|
|
|
|
push(val1 - val2 + 1);
|
|
|
|
break;
|
|
|
|
}
|
2004-08-23 10:34:50 +00:00
|
|
|
}
|
|
|
|
|
2004-08-28 09:19:53 +00:00
|
|
|
void ScummEngine_v72he::o72_getNumFreeArrays() {
|
|
|
|
byte **addr = _baseArrays;
|
|
|
|
int i, num = 0;
|
|
|
|
|
|
|
|
for (i = 1; i < _numArray; i++) {
|
|
|
|
if (!addr[i])
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
|
|
|
|
push (num);
|
|
|
|
}
|
|
|
|
|
2004-08-28 14:05:33 +00:00
|
|
|
void ScummEngine_v72he::o72_pickupObject() {
|
|
|
|
int obj, room;
|
|
|
|
|
|
|
|
room = pop();
|
|
|
|
obj = pop();
|
|
|
|
if (room == 0)
|
|
|
|
room = getObjectRoom(obj);
|
|
|
|
|
|
|
|
addObjectToInventory(obj, room);
|
|
|
|
putOwner(obj, VAR(VAR_EGO));
|
|
|
|
runInventoryScript(obj);
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_arrayOps() {
|
2004-08-23 11:20:25 +00:00
|
|
|
byte subOp = fetchScriptByte();
|
2004-08-25 06:34:33 +00:00
|
|
|
int array = 0;
|
2004-08-23 11:20:25 +00:00
|
|
|
int b, c, d, len;
|
|
|
|
ArrayHeader *ah;
|
|
|
|
int list[128];
|
|
|
|
|
|
|
|
switch (subOp) {
|
|
|
|
case 7: // SO_ASSIGN_STRING
|
2004-08-25 06:34:33 +00:00
|
|
|
array = fetchScriptWord();
|
2004-08-26 08:47:07 +00:00
|
|
|
ah = defineArray(array, kStringArray, 0, 0, 0, 1024);
|
|
|
|
copyScriptString(ah->data);
|
|
|
|
break;
|
|
|
|
case 194: // SO_ASSIGN_STRING
|
|
|
|
array = fetchScriptWord();
|
|
|
|
len = getStackList(list, ARRAYSIZE(list));
|
|
|
|
ah = defineArray(array, kStringArray, 0, 0, 0, 1024);
|
2004-08-23 11:20:25 +00:00
|
|
|
copyScriptString(ah->data);
|
|
|
|
break;
|
|
|
|
case 208: // SO_ASSIGN_INT_LIST
|
2004-08-25 06:34:33 +00:00
|
|
|
array = fetchScriptWord();
|
2004-08-23 11:20:25 +00:00
|
|
|
b = pop();
|
|
|
|
c = pop();
|
|
|
|
d = readVar(array);
|
|
|
|
if (d == 0) {
|
2004-08-25 06:34:33 +00:00
|
|
|
defineArray(array, kDwordArray, 0, 0, 0, b + c);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
2004-08-25 06:34:33 +00:00
|
|
|
while (--c) {
|
2004-08-23 11:20:25 +00:00
|
|
|
writeArray(array, 0, b + c, pop());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 212: // SO_ASSIGN_2DIM_LIST
|
2004-08-25 06:34:33 +00:00
|
|
|
array = fetchScriptWord();
|
2004-08-23 11:20:25 +00:00
|
|
|
len = getStackList(list, ARRAYSIZE(list));
|
|
|
|
d = readVar(array);
|
|
|
|
if (d == 0)
|
|
|
|
error("Must DIM a two dimensional array before assigning");
|
|
|
|
c = pop();
|
|
|
|
while (--len >= 0) {
|
2004-08-25 06:34:33 +00:00
|
|
|
writeArray(array, c, len, list[len]);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2004-08-23 12:19:08 +00:00
|
|
|
error("o72_arrayOps: default case %d (array %d)", subOp, array);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_dimArray() {
|
2004-08-23 11:20:25 +00:00
|
|
|
int data;
|
|
|
|
int type = fetchScriptByte();
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 2: // SO_BIT_ARRAY
|
|
|
|
data = kBitArray;
|
|
|
|
break;
|
|
|
|
case 3: // SO_NIBBLE_ARRAY
|
|
|
|
data = kNibbleArray;
|
|
|
|
break;
|
|
|
|
case 4: // SO_BYTE_ARRAY
|
|
|
|
data = kByteArray;
|
|
|
|
break;
|
2004-08-28 14:48:51 +00:00
|
|
|
case 5: // SO_INT_ARRAY
|
|
|
|
data = kIntArray;
|
|
|
|
break;
|
2004-08-24 05:04:14 +00:00
|
|
|
case 6:
|
2004-08-25 02:12:03 +00:00
|
|
|
data = kDwordArray;
|
2004-08-24 05:04:14 +00:00
|
|
|
break;
|
2004-08-23 11:20:25 +00:00
|
|
|
case 7: // SO_STRING_ARRAY
|
|
|
|
data = kStringArray;
|
|
|
|
break;
|
|
|
|
case 204: // SO_UNDIM_ARRAY
|
|
|
|
nukeArray(fetchScriptWord());
|
|
|
|
return;
|
|
|
|
default:
|
2004-08-23 12:19:08 +00:00
|
|
|
error("o72_dimArray: default case %d", type);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
defineArray(fetchScriptWord(), data, 0, 0, 0, pop());
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_dim2dimArray() {
|
2004-08-23 11:20:25 +00:00
|
|
|
int a, b, data;
|
|
|
|
int type = fetchScriptByte();
|
2004-08-24 05:04:14 +00:00
|
|
|
switch (type) {
|
|
|
|
case 2: // SO_BIT_ARRAY
|
2004-08-23 11:20:25 +00:00
|
|
|
data = kBitArray;
|
|
|
|
break;
|
2004-08-24 05:04:14 +00:00
|
|
|
case 3: // SO_NIBBLE_ARRAY
|
2004-08-23 11:20:25 +00:00
|
|
|
data = kNibbleArray;
|
|
|
|
break;
|
2004-08-24 05:04:14 +00:00
|
|
|
case 4: // SO_BYTE_ARRAY
|
2004-08-23 11:20:25 +00:00
|
|
|
data = kByteArray;
|
|
|
|
break;
|
2004-08-24 05:04:14 +00:00
|
|
|
case 5: // SO_INT_ARRAY
|
|
|
|
data = kIntArray;
|
|
|
|
break;
|
|
|
|
case 6:
|
2004-08-25 02:12:03 +00:00
|
|
|
data = kDwordArray;
|
2004-08-24 05:04:14 +00:00
|
|
|
break;
|
|
|
|
case 7: // SO_STRING_ARRAY
|
2004-08-23 11:20:25 +00:00
|
|
|
data = kStringArray;
|
|
|
|
break;
|
|
|
|
default:
|
2004-08-23 12:19:08 +00:00
|
|
|
error("o72_dim2dimArray: default case %d", type);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
b = pop();
|
|
|
|
a = pop();
|
2004-08-25 02:12:03 +00:00
|
|
|
defineArray(fetchScriptWord(), data, 0, a, 0, b);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
2004-08-26 06:08:41 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownCE() {
|
|
|
|
int a = pop();
|
|
|
|
int b = pop();
|
|
|
|
int c = pop();
|
|
|
|
int d = pop();
|
2004-08-29 03:19:44 +00:00
|
|
|
debug(1,"o72_unknownCE stub (%d, %d, %d, %d)", d, c, b, a);
|
2004-08-26 06:08:41 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 06:34:33 +00:00
|
|
|
void ScummEngine_v72he::shuffleArray(int num, int minIdx, int maxIdx) {
|
|
|
|
int range = maxIdx - minIdx;
|
|
|
|
int count = range * 2;
|
|
|
|
|
|
|
|
// Shuffle the array 'num'
|
|
|
|
while (count--) {
|
|
|
|
// Determine two random elements...
|
|
|
|
int rand1 = _rnd.getRandomNumber(range) + minIdx;
|
|
|
|
int rand2 = _rnd.getRandomNumber(range) + minIdx;
|
|
|
|
|
|
|
|
// ...and swap them
|
|
|
|
int val1 = readArray(num, 0, rand1);
|
|
|
|
int val2 = readArray(num, 0, rand2);
|
|
|
|
writeArray(num, 0, rand1, val2);
|
|
|
|
writeArray(num, 0, rand2, val1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_shuffle() {
|
|
|
|
int b = pop();
|
|
|
|
int a = pop();
|
|
|
|
shuffleArray(fetchScriptWord(), a, b);
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_jumpToScript() {
|
2004-08-23 11:20:25 +00:00
|
|
|
int args[16];
|
|
|
|
int script, flags;
|
|
|
|
|
|
|
|
getStackList(args, ARRAYSIZE(args));
|
|
|
|
script = pop();
|
|
|
|
flags = fetchScriptByte();
|
|
|
|
stopObjectCode();
|
|
|
|
runScript(script, (flags == 199 || flags == 200), (flags == 195 || flags == 200), args);
|
2004-08-23 10:34:50 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 12:48:47 +00:00
|
|
|
void ScummEngine_v72he::o72_openFile() {
|
|
|
|
int mode, slot, l, r;
|
|
|
|
byte filename[100];
|
|
|
|
|
2004-08-26 08:47:07 +00:00
|
|
|
copyScriptString(filename, true);
|
2004-08-25 12:48:47 +00:00
|
|
|
printf("File %s\n", filename);
|
|
|
|
|
|
|
|
for (r = strlen((char*)filename); r != 0; r--) {
|
|
|
|
if (filename[r - 1] == '\\')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
mode = pop();
|
|
|
|
slot = -1;
|
|
|
|
for (l = 0; l < 17; l++) {
|
|
|
|
if (_hFileTable[l].isOpen() == false) {
|
|
|
|
slot = l;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (slot != -1) {
|
|
|
|
if (mode == -1)
|
|
|
|
_hFileTable[slot].open((char*)filename + r, File::kFileReadMode);
|
|
|
|
else if (mode == -2)
|
|
|
|
_hFileTable[slot].open((char*)filename + r, File::kFileWriteMode);
|
|
|
|
else
|
|
|
|
error("o6_openFile(): wrong open file mode %d", mode);
|
|
|
|
|
|
|
|
if (_hFileTable[slot].isOpen() == false)
|
|
|
|
slot = -1;
|
|
|
|
|
|
|
|
}
|
2004-08-26 08:47:07 +00:00
|
|
|
debug(1, "o72_openFile: slot %d, mode %d", slot, mode);
|
2004-08-25 12:48:47 +00:00
|
|
|
push(slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ScummEngine_v72he::readFileToArray(int slot, int32 size) {
|
|
|
|
if (size == 0)
|
|
|
|
size = _hFileTable[slot].size() - _hFileTable[slot].pos();
|
|
|
|
|
|
|
|
writeVar(0, 0);
|
|
|
|
|
|
|
|
ArrayHeader *ah = defineArray(0, kByteArray, 0, 0, 0, size);
|
|
|
|
_hFileTable[slot].read(ah->data, size);
|
|
|
|
|
|
|
|
return readVar(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_readFile() {
|
|
|
|
int slot, val;
|
|
|
|
int32 size;
|
|
|
|
int subOp = fetchScriptByte();
|
|
|
|
|
|
|
|
switch (subOp) {
|
|
|
|
case 4:
|
|
|
|
slot = pop();
|
|
|
|
val = _hFileTable[slot].readByte();
|
|
|
|
push(val);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
slot = pop();
|
|
|
|
val = _hFileTable[slot].readUint16LE();
|
|
|
|
push(val);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
slot = pop();
|
|
|
|
val = _hFileTable[slot].readUint32LE();
|
|
|
|
push(val);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
fetchScriptByte();
|
|
|
|
size = pop();
|
|
|
|
slot = pop();
|
|
|
|
val = readFileToArray(slot, size);
|
|
|
|
push(val);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("default case %d", subOp);
|
|
|
|
}
|
2004-08-26 08:47:07 +00:00
|
|
|
debug(1, "o72_readFile: slot %d, subOp %d val %d", slot, subOp, val);
|
|
|
|
|
2004-08-25 12:48:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::writeFileFromArray(int slot, int resID) {
|
|
|
|
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resID);
|
|
|
|
int32 size = (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
|
|
|
|
(FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
|
|
|
|
|
|
|
|
_hFileTable[slot].write(ah->data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_writeFile() {
|
|
|
|
int16 resID = pop();
|
|
|
|
int slot = pop();
|
|
|
|
int subOp = fetchScriptByte();
|
|
|
|
|
|
|
|
switch (subOp) {
|
|
|
|
case 4:
|
|
|
|
_hFileTable[slot].writeByte(resID);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
_hFileTable[slot].writeUint16LE(resID);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
_hFileTable[slot].writeUint32LE(resID);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
writeFileFromArray(slot, resID);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("default case %d", subOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
void ScummEngine_v72he::o72_findAllObjects() {
|
2004-08-25 08:49:34 +00:00
|
|
|
int room = pop();
|
2004-08-25 02:12:03 +00:00
|
|
|
int i = 1;
|
|
|
|
|
2004-08-25 08:49:34 +00:00
|
|
|
if (room != _currentRoom)
|
|
|
|
warning("o72_findAllObjects: current room is not %d", room);
|
2004-08-25 02:12:03 +00:00
|
|
|
writeVar(0, 0);
|
|
|
|
defineArray(0, kDwordArray, 0, 0, 0, _numLocalObjects + 1);
|
|
|
|
writeArray(0, 0, 0, _numLocalObjects);
|
|
|
|
|
|
|
|
while (i < _numLocalObjects) {
|
|
|
|
writeArray(0, 0, i, _objs[i].obj_nr);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
push(readVar(0));
|
|
|
|
}
|
|
|
|
|
2004-08-24 11:17:28 +00:00
|
|
|
void ScummEngine_v72he::o72_getPixel() {
|
|
|
|
byte area;
|
|
|
|
int x = pop();
|
|
|
|
int y = pop();
|
|
|
|
int subOp = fetchScriptByte();
|
|
|
|
|
|
|
|
if (subOp != 218 && subOp != 219)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VirtScreen *vs = findVirtScreen(y);
|
|
|
|
if (vs == NULL || x > _screenWidth - 1 || x < 0) {
|
|
|
|
push(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subOp == 218)
|
|
|
|
area = *vs->getBackPixels(x, y - vs->topline);
|
|
|
|
else
|
|
|
|
area = *vs->getPixels(x, y - vs->topline);
|
|
|
|
push(area);
|
|
|
|
}
|
|
|
|
|
2004-08-25 02:12:03 +00:00
|
|
|
void ScummEngine_v72he::o72_pickVarRandom() {
|
|
|
|
int num;
|
|
|
|
int args[100];
|
|
|
|
int32 var_A;
|
|
|
|
|
|
|
|
num = getStackList(args, ARRAYSIZE(args));
|
|
|
|
int value = fetchScriptWord();
|
|
|
|
|
|
|
|
if (readVar(value) == 0) {
|
|
|
|
defineArray(value, kDwordArray, 0, 0, 0, num + 1);
|
|
|
|
if (num > 0) {
|
|
|
|
int16 counter = 0;
|
|
|
|
do {
|
|
|
|
writeArray(value, 0, counter + 1, args[counter]);
|
|
|
|
} while (++counter < num);
|
|
|
|
}
|
|
|
|
|
|
|
|
shuffleArray(value, 1, num-1);
|
|
|
|
writeArray(value, 0, 0, 2);
|
|
|
|
push(readArray(value, 0, 1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = readArray(value, 0, 0);
|
|
|
|
|
|
|
|
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, num);
|
|
|
|
var_A = FROM_LE_32(ah->dim1end);
|
|
|
|
|
|
|
|
if (var_A-1 <= num) {
|
|
|
|
int16 var_2 = readArray(value, 0, num - 1);
|
|
|
|
shuffleArray(value, 1, num - 1);
|
|
|
|
if (readArray(value, 0, 1) == var_2) {
|
|
|
|
num = 2;
|
|
|
|
} else {
|
|
|
|
num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeArray(value, 0, 0, num + 1);
|
|
|
|
push(readArray(value, 0, num));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_redimArray() {
|
|
|
|
int subcode, newX, newY;
|
|
|
|
newY = pop();
|
|
|
|
newX = pop();
|
|
|
|
|
|
|
|
subcode = fetchScriptByte();
|
|
|
|
switch (subcode) {
|
|
|
|
case 5:
|
|
|
|
redimArray(fetchScriptWord(), 0, newX, 0, newY, kIntArray);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
redimArray(fetchScriptWord(), 0, newX, 0, newY, kByteArray);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
redimArray(fetchScriptWord(), 0, newX, 0, newY, kDwordArray);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::redimArray(int arrayId, int newDim2start, int newDim2end,
|
|
|
|
int newDim1start, int newDim1end, int type) {
|
|
|
|
int newSize, oldSize;
|
|
|
|
|
|
|
|
if (readVar(arrayId) == 0)
|
|
|
|
error("redimArray: Reference to zeroed array pointer");
|
|
|
|
|
|
|
|
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(arrayId));
|
|
|
|
|
|
|
|
if (!ah)
|
|
|
|
error("redimArray: Invalid array (%d) reference", readVar(arrayId));
|
|
|
|
|
|
|
|
newSize = arrayDataSizes[type];
|
|
|
|
oldSize = arrayDataSizes[FROM_LE_32(ah->type)];
|
|
|
|
|
2004-08-25 11:34:28 +00:00
|
|
|
newSize *= (newDim1end - newDim1start + 1) * (newDim2end - newDim2start + 1);
|
2004-08-25 02:12:03 +00:00
|
|
|
oldSize *= (FROM_LE_32(ah->dim1end) - FROM_LE_32(ah->dim1start) + 1) *
|
|
|
|
(FROM_LE_32(ah->dim2end) - FROM_LE_32(ah->dim2start) + 1);
|
|
|
|
|
|
|
|
newSize >>= 3;
|
|
|
|
oldSize >>= 3;
|
|
|
|
|
|
|
|
if (newSize != oldSize)
|
|
|
|
error("redimArray: array %d redim mismatch", readVar(arrayId));
|
|
|
|
|
|
|
|
ah->type = TO_LE_32(type);
|
|
|
|
ah->dim1start = TO_LE_32(newDim1start);
|
|
|
|
ah->dim1end = TO_LE_32(newDim1end);
|
|
|
|
ah->dim2start = TO_LE_32(newDim2start);
|
|
|
|
ah->dim2end = TO_LE_32(newDim2end);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_readINI() {
|
2004-08-25 06:34:33 +00:00
|
|
|
byte name[100];
|
2004-08-23 10:34:50 +00:00
|
|
|
int type;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
// we pretend that we don't have .ini file
|
|
|
|
type = fetchScriptByte();
|
|
|
|
switch (type) {
|
|
|
|
case 6: // number
|
|
|
|
push(0);
|
|
|
|
break;
|
|
|
|
case 7: // string
|
2004-08-25 06:34:33 +00:00
|
|
|
copyScriptString(name);
|
2004-08-25 02:12:03 +00:00
|
|
|
defineArray(0, kStringArray, 0, 0, 0, 0);
|
2004-08-23 10:34:50 +00:00
|
|
|
retval = readVar(0);
|
|
|
|
writeArray(0, 0, 0, 0);
|
|
|
|
push(retval); // var ID string
|
|
|
|
break;
|
|
|
|
default:
|
2004-08-23 12:19:08 +00:00
|
|
|
warning("o72_readINI(..., %d): read-ini string not implemented", type);
|
2004-08-23 10:34:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownF4() {
|
2004-08-23 10:34:50 +00:00
|
|
|
byte b;
|
2004-08-28 03:18:52 +00:00
|
|
|
byte name[256], name2[1024];
|
|
|
|
|
2004-08-23 10:34:50 +00:00
|
|
|
b = fetchScriptByte();
|
|
|
|
|
|
|
|
switch (b) {
|
|
|
|
case 6:
|
|
|
|
pop();
|
2004-08-28 03:18:52 +00:00
|
|
|
copyScriptString(name);
|
2004-08-23 10:34:50 +00:00
|
|
|
break;
|
2004-08-28 03:18:52 +00:00
|
|
|
warning("o72_unknownF4 stub (%s)", name);
|
2004-08-23 10:34:50 +00:00
|
|
|
case 7:
|
2004-08-28 03:18:52 +00:00
|
|
|
copyScriptString(name2);
|
|
|
|
copyScriptString(name);
|
|
|
|
warning("o72_unknownF4 stub (%s, %s)", name, name2);
|
2004-08-23 10:34:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownFA() {
|
2004-08-25 06:34:33 +00:00
|
|
|
byte name[100];
|
|
|
|
int id = fetchScriptByte();
|
|
|
|
copyScriptString(name);
|
|
|
|
|
|
|
|
debug(1,"o72_unknownFA: (%d) %s", id, name);
|
2004-08-23 11:20:25 +00:00
|
|
|
}
|
|
|
|
|
2004-08-26 08:47:07 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownF8() {
|
|
|
|
int a = fetchScriptByte();
|
|
|
|
push(1);
|
|
|
|
|
|
|
|
warning("stub o72_unknownF8(%d)", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::o72_unknownF9() {
|
|
|
|
// File related
|
|
|
|
int r;
|
|
|
|
byte filename[255];
|
|
|
|
|
|
|
|
copyScriptString(filename);
|
|
|
|
|
|
|
|
for (r = strlen((char*)filename); r != 0; r--) {
|
|
|
|
if (filename[r - 1] == '\\')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
warning("stub o72_unknownF9(\"%s\")", filename + r);
|
|
|
|
}
|
|
|
|
|
2004-08-23 12:19:08 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownFB() {
|
2004-08-23 10:34:50 +00:00
|
|
|
byte b;
|
|
|
|
b = fetchScriptByte();
|
|
|
|
|
|
|
|
switch (b) {
|
|
|
|
case 246:
|
|
|
|
case 248:
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
break;
|
|
|
|
case 247:
|
|
|
|
pop();
|
|
|
|
pop();
|
|
|
|
break;
|
|
|
|
}
|
2004-08-29 03:19:44 +00:00
|
|
|
debug(1, "o72_unknownFB stub");
|
2004-08-23 10:34:50 +00:00
|
|
|
}
|
|
|
|
|
2004-08-25 07:18:18 +00:00
|
|
|
void ScummEngine_v72he::o72_unknownFC() {
|
|
|
|
int a = pop();
|
|
|
|
int b = pop();
|
2004-08-29 03:19:44 +00:00
|
|
|
debug(1,"o7_unknownFC stub (%d, %d)", b, a);
|
2004-08-25 07:18:18 +00:00
|
|
|
push(0);
|
|
|
|
}
|
|
|
|
|
2004-08-23 10:34:50 +00:00
|
|
|
} // End of namespace Scumm
|