diff options
| author | Max Horn | 2006-02-11 22:45:04 +0000 |
|---|---|---|
| committer | Max Horn | 2006-02-11 22:45:04 +0000 |
| commit | 26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch) | |
| tree | 26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /scumm/script_v6.cpp | |
| parent | 2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff) | |
| download | scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.gz scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.bz2 scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.zip | |
Moved engines to the new engines/ directory
svn-id: r20582
Diffstat (limited to 'scumm/script_v6.cpp')
| -rw-r--r-- | scumm/script_v6.cpp | 3183 |
1 files changed, 0 insertions, 3183 deletions
diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp deleted file mode 100644 index 77709eed21..0000000000 --- a/scumm/script_v6.cpp +++ /dev/null @@ -1,3183 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2001 Ludvig Strigeus - * Copyright (C) 2001-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/stdafx.h" - -#include "common/config-manager.h" - -#include "scumm/actor.h" -#include "scumm/charset.h" -#include "scumm/imuse.h" -#include "scumm/imuse_digi/dimuse.h" -#include "scumm/insane/insane.h" -#include "scumm/intern.h" -#include "scumm/object.h" -#include "scumm/resource.h" -#include "scumm/scumm.h" -#include "scumm/smush/smush_player.h" -#include "scumm/sound.h" -#include "scumm/util.h" -#include "scumm/verbs.h" - -#include "sound/mididrv.h" -#include "sound/mixer.h" - -namespace Scumm { - -#define OPCODE(x) _OPCODE(ScummEngine_v6, x) - -void ScummEngine_v6::setupOpcodes() { - static const OpcodeEntryV6 opcodes[256] = { - /* 00 */ - OPCODE(o6_pushByte), - OPCODE(o6_pushWord), - OPCODE(o6_pushByteVar), - OPCODE(o6_pushWordVar), - /* 04 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayRead), - OPCODE(o6_wordArrayRead), - /* 08 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayIndexedRead), - OPCODE(o6_wordArrayIndexedRead), - /* 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), - OPCODE(o6_invalid), - /* 1C */ - OPCODE(o6_invalid), - 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), - OPCODE(o6_invalid), - 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), - OPCODE(o6_writeByteVar), - OPCODE(o6_writeWordVar), - /* 44 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayWrite), - OPCODE(o6_wordArrayWrite), - /* 48 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayIndexedWrite), - OPCODE(o6_wordArrayIndexedWrite), - /* 4C */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteVarInc), - OPCODE(o6_wordVarInc), - /* 50 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayInc), - OPCODE(o6_wordArrayInc), - /* 54 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteVarDec), - OPCODE(o6_wordVarDec), - /* 58 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_byteArrayDec), - OPCODE(o6_wordArrayDec), - /* 5C */ - OPCODE(o6_if), - OPCODE(o6_ifNot), - OPCODE(o6_startScript), - OPCODE(o6_startScriptQuick), - /* 60 */ - OPCODE(o6_startObject), - OPCODE(o6_drawObject), - OPCODE(o6_drawObjectAt), - OPCODE(o6_drawBlastObject), - /* 64 */ - OPCODE(o6_setBlastObjectWindow), - OPCODE(o6_stopObjectCode), - OPCODE(o6_stopObjectCode), - OPCODE(o6_endCutscene), - /* 68 */ - OPCODE(o6_cutscene), - OPCODE(o6_stopMusic), - OPCODE(o6_freezeUnfreeze), - OPCODE(o6_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(o6_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 */ - OPCODE(o6_pickupObject), - OPCODE(o6_loadRoomWithEgo), - OPCODE(o6_invalid), - OPCODE(o6_getRandomNumber), - /* 88 */ - OPCODE(o6_getRandomNumberRange), - OPCODE(o6_invalid), - OPCODE(o6_getActorMoving), - OPCODE(o6_isScriptRunning), - /* 8C */ - OPCODE(o6_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_createBoxMatrix), - OPCODE(o6_resourceRoutines), - /* 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 */ - OPCODE(o6_arrayOps), - 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_soundKludge), - OPCODE(o6_isAnyOf), - OPCODE(o6_systemOps), - OPCODE(o6_isActorInBox), - /* B0 */ - OPCODE(o6_delay), - OPCODE(o6_delaySeconds), - OPCODE(o6_delayMinutes), - OPCODE(o6_stopSentence), - /* B4 */ - OPCODE(o6_printLine), - OPCODE(o6_printText), - OPCODE(o6_printDebug), - OPCODE(o6_printSystem), - /* B8 */ - OPCODE(o6_printActor), - OPCODE(o6_printEgo), - OPCODE(o6_talkActor), - OPCODE(o6_talkEgo), - /* BC */ - OPCODE(o6_dimArray), - OPCODE(o6_dummy), - OPCODE(o6_startObjectQuick), - OPCODE(o6_startScriptQuick2), - /* C0 */ - OPCODE(o6_dim2dimArray), - 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), - OPCODE(o6_kernelSetFunctions), - OPCODE(o6_delayFrames), - OPCODE(o6_pickOneOf), - /* CC */ - OPCODE(o6_pickOneOfDefault), - OPCODE(o6_stampObject), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* D0 */ - OPCODE(o6_getDateTime), - OPCODE(o6_stopTalking), - OPCODE(o6_getAnimateVariable), - OPCODE(o6_invalid), - /* D4 */ - OPCODE(o6_shuffle), - OPCODE(o6_jumpToScript), - OPCODE(o6_band), - OPCODE(o6_bor), - /* D8 */ - OPCODE(o6_isRoomScriptRunning), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* DC */ - OPCODE(o6_invalid), - OPCODE(o6_findAllObjects), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* E0 */ - OPCODE(o6_invalid), - OPCODE(o6_getPixel), - OPCODE(o6_invalid), - OPCODE(o6_pickVarRandom), - /* E4 */ - OPCODE(o6_setBoxSet), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* E8 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* EC */ - OPCODE(o6_getActorLayer), - OPCODE(o6_getObjectNewDir), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* F0 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* F4 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* F8 */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - /* FC */ - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - OPCODE(o6_invalid), - }; - - _opcodesV6 = opcodes; -} - -void ScummEngine_v6::executeOpcode(byte i) { - OpcodeProcV6 op = _opcodesV6[i].proc; - (this->*op) (); -} - -const char *ScummEngine_v6::getOpcodeDesc(byte i) { - return _opcodesV6[i].desc; -} - -int ScummEngine_v6::popRoomAndObj(int *room) { - int obj; - - if (_version >= 7) { - obj = pop(); - *room = getObjectRoom(obj); - } else { - *room = pop(); - obj = pop(); - } - - return obj; -} - -ScummEngine_v6::ArrayHeader *ScummEngine_v6::defineArray(int array, int type, int dim2, int dim1) { - int id; - int size; - ArrayHeader *ah; - - assert(0 <= type && type <= 5); - - - if (_heversion >= 61) { - if (type == kBitArray || type == kNibbleArray) - type = kByteArray; - } else { - // NOTE: The following code turns all arrays except string arrays into - // integer arrays. There seems to be no reason for this, and it wastes - // space. However, we can't just remove this either, as that would - // break savegame compatibility. So do not touch this unless you are - // also adding code which updated old savegames, too. And of course - // readArray() and writeArray() would have to be updated, too... - if (type != kStringArray) - type = kIntArray; - } - - nukeArray(array); - - id = findFreeArrayId(); - - if (_version == 8) { - if (array & 0x40000000) { - } - - if (array & 0x80000000) { - error("Can't define bit variable as array pointer"); - } - - size = (type == kIntArray) ? 4 : 1; - } else { - if (array & 0x4000) { - } - - if (array & 0x8000) { - error("Can't define bit variable as array pointer"); - } - - size = (type == kIntArray) ? 2 : 1; - } - - writeVar(array, id); - - size *= dim2 + 1; - size *= dim1 + 1; - - ah = (ArrayHeader *)res.createResource(rtString, id, size + sizeof(ArrayHeader)); - - ah->type = TO_LE_16(type); - ah->dim1 = TO_LE_16(dim1 + 1); - ah->dim2 = TO_LE_16(dim2 + 1); - - return ah; -} - -void ScummEngine_v6::nukeArray(int a) { - int data; - - data = readVar(a); - - if (_heversion >= 80) - data &= ~0x33539000; - - if (data) - res.nukeResource(rtString, data); - if (_heversion >= 60) - _arraySlot[data] = 0; - - writeVar(a, 0); -} - -int ScummEngine_v6::findFreeArrayId() { - byte **addr = res.address[rtString]; - int i; - - for (i = 1; i < _numArray; i++) { - if (!addr[i]) - return i; - } - error("Out of array pointers, %d max", _numArray); - return -1; -} - -#define SWAP16(x) x = SWAP_BYTES_16(x) - -ScummEngine_v6::ArrayHeader *ScummEngine_v6::getArray(int array) { - ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array)); - if (!ah) - return 0; - - // Workaround for a long standing bug where we save array headers in native - // endianness, instead of a fixed endianness. We try to detect savegames - // which were created on a big endian system and convert them to little - // endian. - if ((FROM_LE_16(ah->dim1) & 0xF000) || (FROM_LE_16(ah->dim2) & 0xF000) || (FROM_LE_16(ah->type) & 0xFF00)) { - SWAP16(ah->dim1); - SWAP16(ah->dim2); - SWAP16(ah->type); - } - - return ah; -} - -int ScummEngine_v6::readArray(int array, int idx, int base) { - ArrayHeader *ah = getArray(array); - - if (ah == NULL || ah->data == NULL) - error("readArray: invalid array %d (%d)", array, readVar(array)); - - // WORKAROUND bug #645711. This is clearly a script bug, as this script - // excerpt shows nicely: - // ... - // [03A7] (5D) if (isAnyOf(array-447[localvar13][localvar14],[0,4])) { - // [03BD] (5D) if ((localvar13 != -1) && (localvar14 != -1)) { - // [03CF] (B6) printDebug.begin() - // ... - if (_gameId == GID_FT && array == 447 && _currentRoom == 95 && vm.slot[_currentScript].number == 2010 && idx == -1 && base == -1) { - return 0; - } - - const int offset = base + idx * FROM_LE_16(ah->dim1); - - if (offset < 0 || offset >= FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2)) { - error("readArray: array %d out of bounds: [%d,%d] exceeds [%d,%d]", - array, base, idx, FROM_LE_16(ah->dim1), FROM_LE_16(ah->dim2)); - } - - int val; - if (FROM_LE_16(ah->type) != kIntArray) { - val = ah->data[offset]; - } else if (_version == 8) { - val = (int32)READ_LE_UINT32(ah->data + offset * 4); - } else { - val = (int16)READ_LE_UINT16(ah->data + offset * 2); - } - return val; -} - -void ScummEngine_v6::writeArray(int array, int idx, int base, int value) { - ArrayHeader *ah = getArray(array); - if (!ah) - return; - - const int offset = base + idx * FROM_LE_16(ah->dim1); - - if (offset < 0 || offset >= FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2)) { - error("writeArray: array %d out of bounds: [%d,%d] exceeds [%d,%d]", - array, base, idx, FROM_LE_16(ah->dim1), FROM_LE_16(ah->dim2)); - } - - if (FROM_LE_16(ah->type) != kIntArray) { - ah->data[offset] = value; - } else if (_version == 8) { - WRITE_LE_UINT32(ah->data + offset * 4, value); - } else { - WRITE_LE_UINT16(ah->data + offset * 2, value); - } -} - -void ScummEngine_v6::readArrayFromIndexFile() { - int num; - int a, b, c; - - while ((num = _fileHandle->readUint16LE()) != 0) { - a = _fileHandle->readUint16LE(); - b = _fileHandle->readUint16LE(); - c = _fileHandle->readUint16LE(); - if (c == kBitArray) - defineArray(num, kBitArray, a, b); - else - defineArray(num, kIntArray, a, b); - } -} - -int ScummEngine_v6::getStackList(int *args, uint maxnum) { - uint num, i; - - for (i = 0; i < maxnum; i++) - args[i] = 0; - - num = pop(); - - if (num > maxnum) - error("Too many items %d in stack list, max %d", num, maxnum); - - i = num; - while (i--) { - args[i] = pop(); - } - - return num; -} - -void ScummEngine_v6::o6_pushByte() { - push(fetchScriptByte()); -} - -void ScummEngine_v6::o6_pushWord() { - push(fetchScriptWordSigned()); -} - -void ScummEngine_v6::o6_pushByteVar() { - push(readVar(fetchScriptByte())); -} - -void ScummEngine_v6::o6_pushWordVar() { - push(readVar(fetchScriptWord())); -} - -void ScummEngine_v6::o6_invalid() { - error("Invalid opcode '%x' at %x", _opcode, _scriptPointer - _scriptOrgPointer); -} - -void ScummEngine_v6::o6_byteArrayRead() { - int base = pop(); - push(readArray(fetchScriptByte(), 0, base)); -} - -void ScummEngine_v6::o6_wordArrayRead() { - int base = pop(); - push(readArray(fetchScriptWord(), 0, base)); -} - -void ScummEngine_v6::o6_byteArrayIndexedRead() { - int base = pop(); - int idx = pop(); - push(readArray(fetchScriptByte(), idx, base)); -} - -void ScummEngine_v6::o6_wordArrayIndexedRead() { - int base = pop(); - int idx = pop(); - push(readArray(fetchScriptWord(), idx, base)); -} - -void ScummEngine_v6::o6_dup() { - int a = pop(); - push(a); - push(a); -} - -void ScummEngine_v6::o6_not() { - push(pop() == 0); -} - -void ScummEngine_v6::o6_eq() { - push(pop() == pop()); -} - -void ScummEngine_v6::o6_neq() { - push(pop() != pop()); -} - -void ScummEngine_v6::o6_gt() { - int a = pop(); - push(pop() > a); -} - -void ScummEngine_v6::o6_lt() { - int a = pop(); - push(pop() < a); -} - -void ScummEngine_v6::o6_le() { - int a = pop(); - push(pop() <= a); -} - -void ScummEngine_v6::o6_ge() { - int a = pop(); - push(pop() >= a); -} - -void ScummEngine_v6::o6_add() { - int a = pop(); - push(pop() + a); -} - -void ScummEngine_v6::o6_sub() { - int a = pop(); - push(pop() - a); -} - -void ScummEngine_v6::o6_mul() { - int a = pop(); - push(pop() * a); -} - -void ScummEngine_v6::o6_div() { - int a = pop(); - if (a == 0) - error("division by zero"); - push(pop() / a); -} - -void ScummEngine_v6::o6_land() { - int a = pop(); - push(pop() && a); -} - -void ScummEngine_v6::o6_lor() { - int a = pop(); - push(pop() || a); -} - -void ScummEngine_v6::o6_bor() { - int a = pop(); - push(pop() | a); -} - -void ScummEngine_v6::o6_band() { - int a = pop(); - push(pop() & a); -} - -void ScummEngine_v6::o6_pop() { - pop(); -} - -void ScummEngine_v6::o6_writeByteVar() { - writeVar(fetchScriptByte(), pop()); -} - -void ScummEngine_v6::o6_writeWordVar() { - writeVar(fetchScriptWord(), pop()); -} - -void ScummEngine_v6::o6_byteArrayWrite() { - int a = pop(); - writeArray(fetchScriptByte(), 0, pop(), a); -} - -void ScummEngine_v6::o6_wordArrayWrite() { - int a = pop(); - writeArray(fetchScriptWord(), 0, pop(), a); -} - -void ScummEngine_v6::o6_byteArrayIndexedWrite() { - int val = pop(); - int base = pop(); - writeArray(fetchScriptByte(), pop(), base, val); -} - -void ScummEngine_v6::o6_wordArrayIndexedWrite() { - int val = pop(); - int base = pop(); - writeArray(fetchScriptWord(), pop(), base, val); -} - -void ScummEngine_v6::o6_byteVarInc() { - int var = fetchScriptByte(); - writeVar(var, readVar(var) + 1); -} - -void ScummEngine_v6::o6_wordVarInc() { - int var = fetchScriptWord(); - writeVar(var, readVar(var) + 1); -} - -void ScummEngine_v6::o6_byteArrayInc() { - int var = fetchScriptByte(); - int base = pop(); - writeArray(var, 0, base, readArray(var, 0, base) + 1); -} - -void ScummEngine_v6::o6_wordArrayInc() { - int var = fetchScriptWord(); - int base = pop(); - writeArray(var, 0, base, readArray(var, 0, base) + 1); -} - -void ScummEngine_v6::o6_byteVarDec() { - int var = fetchScriptByte(); - writeVar(var, readVar(var) - 1); -} - -void ScummEngine_v6::o6_wordVarDec() { - int var = fetchScriptWord(); - writeVar(var, readVar(var) - 1); -} - -void ScummEngine_v6::o6_byteArrayDec() { - int var = fetchScriptByte(); - int base = pop(); - writeArray(var, 0, base, readArray(var, 0, base) - 1); -} - -void ScummEngine_v6::o6_wordArrayDec() { - int var = fetchScriptWord(); - int base = pop(); - writeArray(var, 0, base, readArray(var, 0, base) - 1); -} - -void ScummEngine_v6::o6_if() { - if (pop()) - o6_jump(); - else - fetchScriptWord(); -} - -void ScummEngine_v6::o6_ifNot() { - if (!pop()) - o6_jump(); - else - fetchScriptWord(); -} - -void ScummEngine_v6::o6_jump() { - int offset = fetchScriptWordSigned(); - _scriptPointer += offset; -} - -void ScummEngine_v6::o6_startScript() { - int args[25]; - int script, flags; - - getStackList(args, ARRAYSIZE(args)); - script = pop(); - flags = pop(); - - // WORKAROUND bug #556558: At Dino Bungee National Memorial, the buttons for - // the Wally and Rex dinosaurs will always restart their speech, instead of - // stopping and starting their speech. This was a script bug in the original - // game. - if (_gameId == GID_SAMNMAX && _roomResource == 59 && - vm.slot[_currentScript].number == 201 && script == 48) { - o6_breakHere(); - } - - // WORKAROUND bug #903223: In Puerto Pollo, if you have Guybrush examine - // the church clock, he'll read out the current time. Nice touch, only that - // it sounds crap in the german version (and maybe others, too). It seems - // the original engine of the german version played just a simple fixed - // text in this spot, for the above reason. Since the data files are - // unchanged, it must have been an engine hack job. No idea how they did - // it exactly, but this here is how we do it :-) - if (_gameId == GID_CMI && script == 204 && - _currentRoom == 15 && vm.slot[_currentScript].number == 421 && - _language == Common::DE_DEU) { - - _actorToPrintStrFor = 1; - _string[0].loadDefault(); - actorTalk((const byte *)"/VDSO325/Whoa! Look at the time. Gotta scoot."); - - return; - } - - runScript(script, (flags & 1) != 0, (flags & 2) != 0, args); -} - -void ScummEngine_v6::o6_jumpToScript() { - int args[25]; - int script, flags; - - getStackList(args, ARRAYSIZE(args)); - script = pop(); - flags = pop(); - stopObjectCode(); - runScript(script, (flags & 1) != 0, (flags & 2) != 0, args); -} - -void ScummEngine_v6::o6_startScriptQuick() { - int args[25]; - int script; - getStackList(args, ARRAYSIZE(args)); - script = pop(); - runScript(script, 0, 0, args); -} - -void ScummEngine_v6::o6_startScriptQuick2() { - int args[25]; - int script; - getStackList(args, ARRAYSIZE(args)); - script = pop(); - runScript(script, 0, 1, args); -} - -void ScummEngine_v6::o6_startObject() { - int args[25]; - int script, entryp; - int flags; - getStackList(args, ARRAYSIZE(args)); - entryp = pop(); - script = pop(); - flags = pop(); - runObjectScript(script, entryp, (flags & 1) != 0, (flags & 2) != 0, args); -} - -void ScummEngine_v6::o6_startObjectQuick() { - int args[25]; - int script, entryp; - getStackList(args, ARRAYSIZE(args)); - entryp = pop(); - script = pop(); - runObjectScript(script, entryp, 0, 1, args); -} - -void ScummEngine_v6::o6_drawObject() { - int state = pop(); - int obj = pop(); - - // This is based on disassembly - if (state == 0) - state = 1; - - setObjectState(obj, state, -1, -1); -} - -void ScummEngine_v6::o6_drawObjectAt() { - int y = pop(); - int x = pop(); - int obj = pop(); - setObjectState(obj, 1, x, y); -} - -void ScummEngine_v6::o6_stopObjectCode() { - stopObjectCode(); -} - -void ScummEngine_v6::o6_endCutscene() { - endCutscene(); -} - -void ScummEngine_v6::o6_cutscene() { - int args[25]; - getStackList(args, ARRAYSIZE(args)); - beginCutscene(args); -} - -void ScummEngine_v6::o6_stopMusic() { - _sound->stopAllSounds(); -} - -void ScummEngine_v6::o6_freezeUnfreeze() { - int a = pop(); - - if (a) - freezeScripts(a); - else - unfreezeScripts(); -} - -void ScummEngine_v6::o6_cursorCommand() { - int a, i; - int args[16]; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 0x90: // SO_CURSOR_ON Turn cursor on - _cursor.state = 1; - verbMouseOver(0); - break; - case 0x91: // SO_CURSOR_OFF Turn cursor off - _cursor.state = 0; - verbMouseOver(0); - break; - case 0x92: // SO_USERPUT_ON - _userPut = 1; - break; - case 0x93: // SO_USERPUT_OFF - _userPut = 0; - break; - case 0x94: // SO_CURSOR_SOFT_ON Turn soft cursor on - _cursor.state++; - if (_cursor.state > 1) - error("Cursor state greater than 1 in script"); - verbMouseOver(0); - break; - case 0x95: // SO_CURSOR_SOFT_OFF Turn soft cursor off - _cursor.state--; - verbMouseOver(0); - break; - case 0x96: // SO_USERPUT_SOFT_ON - _userPut++; - break; - case 0x97: // SO_USERPUT_SOFT_OFF - _userPut--; - break; - case 0x99: // SO_CURSOR_IMAGE Set cursor image - { - int room, obj; - if (_heversion >= 70) { - obj = pop(); - room = getObjectRoom(obj); - } else { - obj = popRoomAndObj(&room); - } - setCursorFromImg(obj, room, 1); - break; - } - case 0x9A: // SO_CURSOR_HOTSPOT Set cursor hotspot - a = pop(); - setCursorHotspot(pop(), a); - break; - case 0x9C: // SO_CHARSET_SET - initCharset(pop()); - break; - case 0x9D: // SO_CHARSET_COLOR - getStackList(args, ARRAYSIZE(args)); - for (i = 0; i < 16; i++) - _charsetColorMap[i] = _charsetData[_string[1]._default.charset][i] = (unsigned char)args[i]; - break; - case 0xD6: // SO_CURSOR_TRANSPARENT Set cursor transparent color - setCursorTransparency(pop()); - break; - default: - error("o6_cursorCommand: default case %x", subOp); - } - - VAR(VAR_CURSORSTATE) = _cursor.state; - VAR(VAR_USERPUT) = _userPut; -} - -void ScummEngine_v6::o6_breakHere() { - updateScriptPtr(); - _currentScript = 0xFF; -} - -void ScummEngine_v6::o6_ifClassOfIs() { - int args[16]; - int num, obj, cls; - bool b; - int cond = 1; - - num = getStackList(args, ARRAYSIZE(args)); - obj = pop(); - - if (_heversion >= 80 && num == 0) { - push(_classData[obj]); - return; - } - - while (--num >= 0) { - cls = args[num]; - b = getClass(obj, cls); - if ((cls & 0x80 && !b) || (!(cls & 0x80) && b)) - cond = 0; - } - push(cond); -} - -void ScummEngine_v6::o6_setClass() { - int args[16]; - int num, obj, cls; - - num = getStackList(args, ARRAYSIZE(args)); - obj = pop(); - - while (--num >= 0) { - cls = args[num]; - if (cls == 0) - _classData[num] = 0; - else if (cls & 0x80) - putClass(obj, cls, 1); - else - putClass(obj, cls, 0); - } -} - -void ScummEngine_v6::o6_getState() { - push(getState(pop())); -} - -void ScummEngine_v6::o6_setState() { - int state = pop(); - int obj = pop(); - - putState(obj, state); - markObjectRectAsDirty(obj); - if (_bgNeedsRedraw) - clearDrawObjectQueue(); -} - -void ScummEngine_v6::o6_setOwner() { - int owner = pop(); - int obj = pop(); - setOwnerOf(obj, owner); -} - -void ScummEngine_v6::o6_getOwner() { - push(getOwner(pop())); -} - -void ScummEngine_v6::o6_startSound() { - int offset = 0; - - // In Fatty Bear's Birthday Surprise the piano uses offsets 1 - 23 to - // indicate which note to play, but only when using the standard piano - // sound. See also o60_soundOps() - if (_heversion >= 60 && (_gameId != GID_PUTTDEMO)) - offset = pop(); - -#ifndef DISABLE_SCUMM_7_8 - if (_features & GF_DIGI_IMUSE) - _imuseDigital->startSfx(pop(), 64); - else -#endif - _sound->addSoundToQueue(pop(), offset); -} - -void ScummEngine_v6::o6_stopSound() { - _sound->stopSound(pop()); -} - -void ScummEngine_v6::o6_startMusic() { - if (_features & GF_DIGI_IMUSE) - error("o6_startMusic() It shouldn't be called here for imuse digital"); - - _sound->addSoundToQueue(pop()); -} - -void ScummEngine_v6::o6_stopObjectScript() { - stopObjectScript(pop()); -} - -void ScummEngine_v6::o6_panCameraTo() { - if (_version >= 7) { - int y = pop(); - int x = pop(); - panCameraTo(x, y); - } else { - panCameraTo(pop(), 0); - } -} - -void ScummEngine_v6::o6_actorFollowCamera() { - if (_version >= 7) - setCameraFollows(derefActor(pop(), "actorFollowCamera")); - else - actorFollowCamera(pop()); -} - -void ScummEngine_v6::o6_setCameraAt() { - if (_version >= 7) { - int x, y; - - camera._follows = 0; - VAR(VAR_CAMERA_FOLLOWED_ACTOR) = 0; - - y = pop(); - x = pop(); - - setCameraAt(x, y); - } else { - setCameraAtEx(pop()); - } -} - -void ScummEngine_v6::o6_loadRoom() { - int room = pop(); - startScene(room, 0, 0); - if (_heversion >= 61) { - setCameraAt(camera._cur.x, 0); - } - _fullRedraw = true; -} - -void ScummEngine_v6::o6_stopScript() { - int script = pop(); - if (script == 0) - stopObjectCode(); - else - stopScript(script); -} - -void ScummEngine_v6::o6_walkActorToObj() { - int act, obj, dist; - Actor *a, *a2; - int x, y; - - dist = pop(); - obj = pop(); - act = pop(); - a = derefActor(act, "o6_walkActorToObj"); - - if (obj >= _numActors) { - int wio = whereIsObject(obj); - - if (wio != WIO_FLOBJECT && wio != WIO_ROOM) - return; - - int dir; - getObjectXYPos(obj, x, y, dir); - a->startWalkActor(x, y, dir); - } else { - a2 = derefActorSafe(obj, "o6_walkActorToObj(2)"); - if (_gameId == GID_SAMNMAX && a2 == 0) { - // WORKAROUND bug #742676 SAM: Fish Farm. Note quite sure why it - // happens, whether it's normal or due to a bug in the ScummVM code. - debug(0, "o6_walkActorToObj: invalid actor %d", obj); - return; - } - if (!a->isInCurrentRoom() || !a2->isInCurrentRoom()) - return; - if (dist == 0) { - dist = a2->_scalex * a2->_width / 0xFF; - dist += dist / 2; - } - x = a2->_pos.x; - y = a2->_pos.y; - if (x < a->_pos.x) - x += dist; - else - x -= dist; - a->startWalkActor(x, y, -1); - } -} - -void ScummEngine_v6::o6_walkActorTo() { - int x, y; - y = pop(); - x = pop(); - Actor *a = derefActor(pop(), "o6_walkActorTo"); - a->startWalkActor(x, y, -1); -} - -void ScummEngine_v6::o6_putActorAtXY() { - int room, x, y, act; - Actor *a; - - room = pop(); - y = pop(); - x = pop(); - act = pop(); - a = derefActor(act, "o6_putActorAtXY"); - - if (room == 0xFF || room == 0x7FFFFFFF) { - room = a->_room; - } else { - if (a->_visible && _currentRoom != room && getTalkingActor() == a->_number) { - stopTalk(); - } - if (room != 0) - a->_room = room; - } - a->putActor(x, y, room); -} - - -void ScummEngine_v6::o6_putActorAtObject() { - int room, obj, x, y; - Actor *a; - - obj = popRoomAndObj(&room); - - a = derefActor(pop(), "o6_putActorAtObject"); - if (whereIsObject(obj) != WIO_NOT_FOUND) { - getObjectXYPos(obj, x, y); - } else { - x = 160; - y = 120; - } - if (room == 0xFF) - room = a->_room; - a->putActor(x, y, room); -} - -void ScummEngine_v6::o6_faceActor() { - int obj = pop(); - Actor *a = derefActor(pop(), "o6_faceActor"); - a->faceToObject(obj); -} - -void ScummEngine_v6::o6_animateActor() { - int anim = pop(); - int act = pop(); - if (_gameId == GID_TENTACLE && _roomResource == 57 && - vm.slot[_currentScript].number == 19 && act == 593) { - // WORKAROUND bug #743363: This very odd case (animateActor(593,250)) - // occurs in DOTT, in the cutscene after George cuts down the "cherry - // tree" and the tree Laverne is trapped in vanishes... - // Not sure if this means animateActor somehow also must work for objects - // (593 is the time machine in room 57), or if this is simply a script bug. - act = 6; - } - if (_gameId == GID_SAMNMAX && _roomResource == 35 && - vm.slot[_currentScript].number == 202 && act == 4 && anim == 14) { - // WORKAROUND bug #1223621 (Animation glitch at World of Fish). - // Before starting animation 14 of the fisherman, make sure he isn't - // talking anymore. This appears to be a bug in the original game as well. - if (getTalkingActor() == 4) { - stopTalk(); - } - } - Actor *a = derefActor(act, "o6_animateActor"); - a->animateActor(anim); -} - -void ScummEngine_v6::o6_doSentence() { - int verb, objectA, objectB, dummy = 0; - - objectB = pop(); - if (_version < 8) - dummy = pop(); // dummy pop (in Sam&Max, seems to be always 0 or 130) - objectA = pop(); - verb = pop(); - - doSentence(verb, objectA, objectB); -} - -void ScummEngine_v6::o6_pickupObject() { - int obj, room; - int i; - - obj = popRoomAndObj(&room); - if (room == 0) - room = _roomResource; - - for (i = 0; i < _numInventory; i++) { - if (_inventory[i] == (uint16)obj) { - putOwner(obj, VAR(VAR_EGO)); - runInventoryScript(obj); - return; - } - } - - addObjectToInventory(obj, room); - putOwner(obj, VAR(VAR_EGO)); - putClass(obj, kObjectClassUntouchable, 1); - putState(obj, 1); - markObjectRectAsDirty(obj); - clearDrawObjectQueue(); - runInventoryScript(obj); -} - -void ScummEngine_v6::o6_loadRoomWithEgo() { - Actor *a; - int obj, room, x, y; - - y = pop(); - x = pop(); - - obj = popRoomAndObj(&room); - - a = derefActor(VAR(VAR_EGO), "o6_loadRoomWithEgo"); - a->putActor(0, 0, room); - _egoPositioned = false; - - VAR(VAR_WALKTO_OBJ) = obj; - startScene(a->_room, a, obj); - VAR(VAR_WALKTO_OBJ) = 0; - - if (_version == 6) { - camera._cur.x = camera._dest.x = a->_pos.x; - setCameraFollows(a); - } - - _fullRedraw = true; - - if (x != -1 && x != 0x7FFFFFFF) { - a->startWalkActor(x, y, -1); - } -} - -void ScummEngine_v6::o6_getRandomNumber() { - int rnd; - rnd = _rnd.getRandomNumber(pop()); - if (VAR_RANDOM_NR != 0xFF) - VAR(VAR_RANDOM_NR) = rnd; - push(rnd); -} - -void ScummEngine_v6::o6_getRandomNumberRange() { - int max = pop(); - int min = pop(); - int rnd = _rnd.getRandomNumberRng(min, max); - if (VAR_RANDOM_NR != 0xFF) - VAR(VAR_RANDOM_NR) = rnd; - push(rnd); -} - -void ScummEngine_v6::o6_isScriptRunning() { - push(isScriptRunning(pop())); -} - -void ScummEngine_v6::o6_isRoomScriptRunning() { - push(isRoomScriptRunning(pop())); -} - -void ScummEngine_v6::o6_getActorMoving() { - Actor *a = derefActor(pop(), "o6_getActorMoving"); - push(a->_moving); -} - -void ScummEngine_v6::o6_getActorRoom() { - int act = pop(); - - if (act == 0) { - // This case occurs at the very least in COMI. That's because in COMI's script 28, - // there is a check which looks as follows: - // if (((VAR_TALK_ACTOR != 0) && (VAR_HAVE_MSG == 1)) && - // (getActorRoom(VAR_TALK_ACTOR) == VAR_ROOM)) - // Due to the way this is represented in bytecode, the engine cannot - // short circuit. Hence, even though this would be perfectly fine code - // in C/C++, here it can (and does) lead to getActorRoom(0) being - // invoked. We silently ignore this. - push(0); - return; - } - - if (act == 255) { - // This case also occurs in COMI... - push(0); - return; - } - - Actor *a = derefActor(act, "o6_getActorRoom"); - push(a->_room); -} - -void ScummEngine_v6::o6_getActorWalkBox() { - Actor *a = derefActor(pop(), "o6_getActorWalkBox"); - push(a->_ignoreBoxes ? 0 : a->_walkbox); -} - -void ScummEngine_v6::o6_getActorCostume() { - Actor *a = derefActor(pop(), "o6_getActorCostume"); - push(a->_costume); -} - -void ScummEngine_v6::o6_getActorElevation() { - Actor *a = derefActor(pop(), "o6_getActorElevation"); - push(a->getElevation()); -} - -void ScummEngine_v6::o6_getActorWidth() { - Actor *a = derefActor(pop(), "o6_getActorWidth"); - push(a->_width); -} - -void ScummEngine_v6::o6_getActorScaleX() { - Actor *a = derefActor(pop(), "o6_getActorScale"); - push(a->_scalex); -} - -void ScummEngine_v6::o6_getActorAnimCounter1() { - Actor *a = derefActor(pop(), "o6_getActorAnimCounter"); - push(a->_cost.animCounter); -} - -void ScummEngine_v6::o6_getAnimateVariable() { - int var = pop(); - Actor *a = derefActor(pop(), "o6_getAnimateVariable"); - push(a->getAnimVar(var)); -} - -void ScummEngine_v6::o6_isActorInBox() { - int box = pop(); - Actor *a = derefActor(pop(), "o6_isActorInBox"); - push(checkXYInBoxBounds(box, a->_pos.x, a->_pos.y)); -} - -void ScummEngine_v6::o6_getActorLayer() { - Actor *a = derefActor(pop(), "getActorLayer"); - push(a->_layer); -} - -void ScummEngine_v6::o6_getObjectX() { - push(getObjX(pop())); -} - -void ScummEngine_v6::o6_getObjectY() { - push(getObjY(pop())); -} - -void ScummEngine_v6::o6_getObjectOldDir() { - push(getObjOldDir(pop())); -} - -void ScummEngine_v6::o6_getObjectNewDir() { - push(getObjNewDir(pop())); -} - -void ScummEngine_v6::o6_findInventory() { - int idx = pop(); - int owner = pop(); - push(findInventory(owner, idx)); -} - -void ScummEngine_v6::o6_getInventoryCount() { - push(getInventoryCount(pop())); -} - -void ScummEngine_v6::o6_getVerbFromXY() { - int y = pop(); - int x = pop(); - int over = findVerbAtPos(x, y); - if (over) - over = _verbs[over].verbid; - push(over); -} - -void ScummEngine_v6::o6_beginOverride() { - beginOverride(); -} - -void ScummEngine_v6::o6_endOverride() { - endOverride(); -} - -void ScummEngine_v6::o6_setObjectName() { - int obj = pop(); - setObjectName(obj); -} - -void ScummEngine_v6::o6_isSoundRunning() { - int snd = pop(); - - if (snd) - snd = _sound->isSoundRunning(snd); - - push(snd); -} - -void ScummEngine_v6::o6_setBoxFlags() { - int table[65]; - int num, value; - - value = pop(); - num = getStackList(table, ARRAYSIZE(table)); - - while (--num >= 0) { - setBoxFlags(table[num], value); - } -} - -void ScummEngine_v6::o6_createBoxMatrix() { - createBoxMatrix(); - - if ((_gameId == GID_DIG) || (_gameId == GID_CMI)) - putActors(); -} - -void ScummEngine_v6::o6_resourceRoutines() { - int resid; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 100: // SO_LOAD_SCRIPT - resid = pop(); - if (_version >= 7) - if (resid >= _numGlobalScripts) - break; - ensureResourceLoaded(rtScript, resid); - break; - case 101: // SO_LOAD_SOUND - resid = pop(); - ensureResourceLoaded(rtSound, resid); - break; - case 102: // SO_LOAD_COSTUME - resid = pop(); - ensureResourceLoaded(rtCostume, resid); - break; - case 103: // SO_LOAD_ROOM - resid = pop(); - ensureResourceLoaded(rtRoom, resid); - break; - case 104: // SO_NUKE_SCRIPT - resid = pop(); - if (_version >= 7) - if (resid >= _numGlobalScripts) - break; - res.setResourceCounter(rtScript, resid, 0x7F); - break; - case 105: // SO_NUKE_SOUND - resid = pop(); - res.setResourceCounter(rtSound, resid, 0x7F); - break; - case 106: // SO_NUKE_COSTUME - resid = pop(); - res.setResourceCounter(rtCostume, resid, 0x7F); - break; - case 107: // SO_NUKE_ROOM - resid = pop(); - res.setResourceCounter(rtRoom, resid, 0x7F); - break; - case 108: // SO_LOCK_SCRIPT - resid = pop(); - if (resid >= _numGlobalScripts) - break; - res.lock(rtScript, resid); - break; - case 109: // SO_LOCK_SOUND - resid = pop(); - res.lock(rtSound, resid); - break; - case 110: // SO_LOCK_COSTUME - resid = pop(); - res.lock(rtCostume, resid); - break; - case 111: // SO_LOCK_ROOM - resid = pop(); - if (resid > 0x7F) - resid = _resourceMapper[resid & 0x7F]; - res.lock(rtRoom, resid); - break; - case 112: // SO_UNLOCK_SCRIPT - resid = pop(); - if (resid >= _numGlobalScripts) - break; - res.unlock(rtScript, resid); - break; - case 113: // SO_UNLOCK_SOUND - resid = pop(); - res.unlock(rtSound, resid); - break; - case 114: // SO_UNLOCK_COSTUME - resid = pop(); - res.unlock(rtCostume, resid); - break; - case 115: // SO_UNLOCK_ROOM - resid = pop(); - if (resid > 0x7F) - resid = _resourceMapper[resid & 0x7F]; - res.unlock(rtRoom, resid); - break; - case 116: // SO_CLEAR_HEAP - /* this is actually a scumm message */ - error("clear heap not working yet"); - break; - case 117: // SO_LOAD_CHARSET - resid = pop(); - loadCharset(resid); - break; - case 118: // SO_NUKE_CHARSET - resid = pop(); - nukeCharset(resid); - break; - case 119: // SO_LOAD_OBJECT - { - int room, obj = popRoomAndObj(&room); - loadFlObject(obj, room); - break; - } - default: - error("o6_resourceRoutines: default case %d", subOp); - } -} - - -void ScummEngine_v6::o6_roomOps() { - int a, b, c, d, e; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 172: // SO_ROOM_SCROLL - b = pop(); - a = pop(); - 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); - VAR(VAR_CAMERA_MIN_X) = a; - VAR(VAR_CAMERA_MAX_X) = b; - break; - - case 174: // SO_ROOM_SCREEN - b = pop(); - a = pop(); - initScreens(a, b); - break; - - case 175: // SO_ROOM_PALETTE - d = pop(); - c = pop(); - b = pop(); - a = pop(); - setPalColor(d, a, b, c); - break; - - case 176: // SO_ROOM_SHAKE_ON - setShake(1); - break; - - case 177: // SO_ROOM_SHAKE_OFF - setShake(0); - break; - - case 179: // SO_ROOM_INTENSITY - c = pop(); - b = pop(); - a = pop(); - darkenPalette(a, a, a, b, c); - break; - - case 180: // SO_ROOM_SAVEGAME - _saveTemporaryState = true; - _saveLoadSlot = pop(); - _saveLoadFlag = pop(); - if (_gameId == GID_TENTACLE) - _saveSound = (_saveLoadSlot != 0); - break; - - case 181: // SO_ROOM_FADE - a = pop(); - if (a) { - _switchRoomEffect = (byte)(a & 0xFF); - _switchRoomEffect2 = (byte)(a >> 8); - } else { - fadeIn(_newEffect); - } - break; - - case 182: // SO_RGB_ROOM_INTENSITY - e = pop(); - d = pop(); - c = pop(); - b = pop(); - a = pop(); - darkenPalette(a, b, c, d, e); - break; - - case 183: // SO_ROOM_SHADOW - e = pop(); - d = pop(); - c = pop(); - b = pop(); - a = pop(); - setupShadowPalette(a, b, c, d, e, 0, 256); - break; - - case 184: // SO_SAVE_STRING - error("save string not implemented"); - break; - - case 185: // SO_LOAD_STRING - error("load string not implemented"); - break; - - case 186: // SO_ROOM_TRANSFORM - d = pop(); - c = pop(); - b = pop(); - a = pop(); - palManipulateInit(a, b, c, d); - break; - - case 187: // SO_CYCLE_SPEED - b = pop(); - a = pop(); - checkRange(16, 1, a, "o6_roomOps: 187: color cycle out of range (%d)"); - _colorCycle[a - 1].delay = (b != 0) ? 0x4000 / (b * 0x4C) : 0; - break; - - case 213: // SO_ROOM_NEW_PALETTE - a = pop(); - - // This opcode is used when turning off noir mode in Sam & Max, - // but since our implementation of this feature doesn't change - // the original palette there's no need to reload it. Doing it - // this way, we avoid some graphics glitches that the original - // interpreter had. - - if (_gameId == GID_SAMNMAX && vm.slot[_currentScript].number == 64) - setDirtyColors(0, 255); - else - setPalette(a); - break; - default: - error("o6_roomOps: default case %d", subOp); - } -} - -void ScummEngine_v6::o6_actorOps() { - Actor *a; - int i, j, k; - int args[8]; - - byte subOp = fetchScriptByte(); - if (subOp == 197) { - _curActor = pop(); - return; - } - - a = derefActorSafe(_curActor, "o6_actorOps"); - if (!a) - return; - - switch (subOp) { - case 76: // SO_COSTUME - a->setActorCostume(pop()); - break; - case 77: // SO_STEP_DIST - j = pop(); - i = pop(); - a->setActorWalkSpeed(i, j); - break; - case 78: // SO_SOUND - k = getStackList(args, ARRAYSIZE(args)); - for (i = 0; i < k; i++) - a->_sound[i] = args[i]; - break; - case 79: // SO_WALK_ANIMATION - a->_walkFrame = pop(); - break; - case 80: // SO_TALK_ANIMATION - a->_talkStopFrame = pop(); - a->_talkStartFrame = pop(); - break; - case 81: // SO_STAND_ANIMATION - a->_standFrame = pop(); - break; - case 82: // SO_ANIMATION - // dummy case in scumm6 - pop(); - pop(); - pop(); - break; - case 83: // SO_DEFAULT - a->initActor(0); - break; - case 84: // SO_ELEVATION - a->setElevation(pop()); - break; - case 85: // SO_ANIMATION_DEFAULT - a->_initFrame = 1; - a->_walkFrame = 2; - a->_standFrame = 3; - a->_talkStartFrame = 4; - a->_talkStopFrame = 5; - break; - case 86: // SO_PALETTE - j = pop(); - i = pop(); - checkRange(255, 0, i, "Illegal palette slot %d"); - a->setPalette(i, j); - break; - case 87: // SO_TALK_COLOR - a->_talkColor = pop(); - break; - case 88: // SO_ACTOR_NAME - loadPtrToResource(rtActorName, a->_number, NULL); - break; - case 89: // SO_INIT_ANIMATION - a->_initFrame = pop(); - break; - case 91: // SO_ACTOR_WIDTH - a->_width = pop(); - break; - case 92: // SO_SCALE - i = pop(); - a->setScale(i, i); - break; - case 93: // SO_NEVER_ZCLIP - a->_forceClip = 0; - break; - case 225: // SO_ALWAYS_ZCLIP - case 94: // SO_ALWAYS_ZCLIP - a->_forceClip = pop(); - break; - case 95: // SO_IGNORE_BOXES - a->_ignoreBoxes = 1; - a->_forceClip = (_version >= 7) ? 100 : 0; - if (a->isInCurrentRoom()) - a->putActor(a->_pos.x, a->_pos.y, a->_room); - break; - case 96: // SO_FOLLOW_BOXES - a->_ignoreBoxes = 0; - a->_forceClip = (_version >= 7) ? 100 : 0; - if (a->isInCurrentRoom()) - a->putActor(a->_pos.x, a->_pos.y, a->_room); - break; - case 97: // SO_ANIMATION_SPEED - a->setAnimSpeed(pop()); - break; - case 98: // SO_SHADOW - a->_shadowMode = pop(); - break; - case 99: // SO_TEXT_OFFSET - a->_talkPosY = pop(); - a->_talkPosX = pop(); - break; - case 198: // SO_ACTOR_VARIABLE - i = pop(); - a->setAnimVar(pop(), i); - break; - case 215: // SO_ACTOR_IGNORE_TURNS_ON - a->_ignoreTurns = true; - break; - case 216: // SO_ACTOR_IGNORE_TURNS_OFF - a->_ignoreTurns = false; - break; - case 217: // SO_ACTOR_NEW - a->initActor(2); - break; - case 227: // SO_ACTOR_DEPTH - a->_layer = pop(); - break; - case 228: // SO_ACTOR_WALK_SCRIPT - a->_walkScript = pop(); - break; - case 229: // SO_ACTOR_STOP - a->stopActorMoving(); - a->startAnimActor(a->_standFrame); - break; - case 230: /* set direction */ - a->_moving &= ~MF_TURN; - a->setDirection(pop()); - break; - case 231: /* turn to direction */ - a->turnToDirection(pop()); - break; - case 233: // SO_ACTOR_WALK_PAUSE - a->_moving |= MF_FROZEN; - break; - case 234: // SO_ACTOR_WALK_RESUME - a->_moving &= ~MF_FROZEN; - break; - case 235: // SO_ACTOR_TALK_SCRIPT - a->_talkScript = pop(); - break; - default: - error("o6_actorOps: default case %d", subOp); - } -} - -void ScummEngine_v6::o6_verbOps() { - int slot, a, b; - VerbSlot *vs; - - byte subOp = fetchScriptByte(); - if (subOp == 196) { - _curVerb = pop(); - _curVerbSlot = getVerbSlot(_curVerb, 0); - checkRange(_numVerbs - 1, 0, _curVerbSlot, "Illegal new verb slot %d"); - return; - } - vs = &_verbs[_curVerbSlot]; - slot = _curVerbSlot; - switch (subOp) { - case 124: // SO_VERB_IMAGE - a = pop(); - if (_curVerbSlot) { - setVerbObject(_roomResource, a, slot); - vs->type = kImageVerbType; - if (_heversion >= 61) - vs->imgindex = a; - } - break; - case 125: // SO_VERB_NAME - loadPtrToResource(rtVerb, slot, NULL); - vs->type = kTextVerbType; - vs->imgindex = 0; - break; - case 126: // SO_VERB_COLOR - vs->color = pop(); - break; - case 127: // SO_VERB_HICOLOR - vs->hicolor = pop(); - break; - case 128: // SO_VERB_AT - vs->curRect.top = pop(); - vs->curRect.left = pop(); - break; - case 129: // SO_VERB_ON - vs->curmode = 1; - break; - case 130: // SO_VERB_OFF - vs->curmode = 0; - break; - case 131: // SO_VERB_DELETE - if (_heversion >= 60) { - slot = getVerbSlot(pop(), 0); - } - killVerb(slot); - break; - case 132: // SO_VERB_NEW - slot = getVerbSlot(_curVerb, 0); - if (slot == 0) { - for (slot = 1; slot < _numVerbs; slot++) { - if (_verbs[slot].verbid == 0) - break; - } - if (slot == _numVerbs) - error("Too many verbs"); - _curVerbSlot = slot; - } - vs = &_verbs[slot]; - vs->verbid = _curVerb; - vs->color = 2; - vs->hicolor = 0; - vs->dimcolor = 8; - vs->type = kTextVerbType; - vs->charset_nr = _string[0]._default.charset; - vs->curmode = 0; - vs->saveid = 0; - vs->key = 0; - vs->center = 0; - vs->imgindex = 0; - break; - case 133: // SO_VERB_DIMCOLOR - vs->dimcolor = pop(); - break; - case 134: // SO_VERB_DIM - vs->curmode = 2; - break; - case 135: // SO_VERB_KEY - vs->key = pop(); - break; - case 136: // SO_VERB_CENTER - vs->center = 1; - break; - case 137: // SO_VERB_NAME_STR - a = pop(); - if (a == 0) { - loadPtrToResource(rtVerb, slot, (const byte *)""); - } else { - loadPtrToResource(rtVerb, slot, getStringAddress(a)); - } - vs->type = kTextVerbType; - vs->imgindex = 0; - break; - case 139: // SO_VERB_IMAGE_IN_ROOM - b = pop(); - a = pop(); - - if (slot && a != vs->imgindex) { - setVerbObject(b, a, slot); - vs->type = kImageVerbType; - vs->imgindex = a; - } - break; - case 140: // SO_VERB_BAKCOLOR - vs->bkcolor = pop(); - break; - case 255: - drawVerb(slot, 0); - verbMouseOver(0); - break; - default: - error("o6_verbops: default case %d", subOp); - } -} - -void ScummEngine_v6::o6_getActorFromXY() { - int y = pop(); - int x = pop(); - int r = getActorFromPos(x, y); - push(r); -} - -void ScummEngine_v6::o6_findObject() { - int y = pop(); - int x = pop(); - int r = findObject(x, y); - push(r); -} - -void ScummEngine_v6::o6_pseudoRoom() { - int list[100]; - int num, a, value; - - num = getStackList(list, ARRAYSIZE(list)); - value = pop(); - - while (--num >= 0) { - a = list[num]; - if (a > 0x7F) - _resourceMapper[a & 0x7F] = value; - } -} - -void ScummEngine_v6::o6_getVerbEntrypoint() { - int e = pop(); - int v = pop(); - push(getVerbEntrypoint(v, e)); -} - -void ScummEngine_v6::o6_arrayOps() { - byte subOp = fetchScriptByte(); - int array = fetchScriptWord(); - int b, c, d, len; - ArrayHeader *ah; - int list[128]; - - switch (subOp) { - case 205: // SO_ASSIGN_STRING - b = pop(); - len = resStrLen(_scriptPointer); - ah = defineArray(array, kStringArray, 0, len + 1); - copyScriptString(ah->data + b); - break; - case 208: // SO_ASSIGN_INT_LIST - b = pop(); - c = pop(); - d = readVar(array); - if (d == 0) { - defineArray(array, kIntArray, 0, b + c); - } - while (c--) { - writeArray(array, 0, b + c, pop()); - } - break; - case 212: // SO_ASSIGN_2DIM_LIST - b = pop(); - 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) { - writeArray(array, c, b + len, list[len]); - } - break; - default: - error("o6_arrayOps: default case %d (array %d)", subOp, array); - } -} - -void ScummEngine_v6::o6_saveRestoreVerbs() { - int a, b, c; - int slot, slot2; - - c = pop(); - b = pop(); - a = pop(); - - byte subOp = fetchScriptByte(); - if (_version == 8) { - subOp = (subOp - 141) + 0xB4; - } - - switch (subOp) { - case 141: // SO_SAVE_VERBS - while (a <= b) { - slot = getVerbSlot(a, 0); - if (slot && _verbs[slot].saveid == 0) { - _verbs[slot].saveid = c; - drawVerb(slot, 0); - verbMouseOver(0); - } - a++; - } - break; - case 142: // SO_RESTORE_VERBS - while (a <= b) { - slot = getVerbSlot(a, c); - if (slot) { - slot2 = getVerbSlot(a, 0); - if (slot2) - killVerb(slot2); - slot = getVerbSlot(a, c); - _verbs[slot].saveid = 0; - drawVerb(slot, 0); - verbMouseOver(0); - } - a++; - } - break; - case 143: // SO_DELETE_VERBS - while (a <= b) { - slot = getVerbSlot(a, c); - if (slot) - killVerb(slot); - a++; - } - break; - default: - error("o6_saveRestoreVerbs: default case"); - } -} - -void ScummEngine_v6::o6_drawBox() { - int x, y, x2, y2, color; - color = pop(); - y2 = pop(); - x2 = pop(); - y = pop(); - x = pop(); - drawBox(x, y, x2, y2, color); -} - -void ScummEngine_v6::o6_wait() { - int actnum; - int offs = -2; - Actor *a; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 168: // SO_WAIT_FOR_ACTOR Wait for actor - offs = fetchScriptWordSigned(); - actnum = pop(); - a = derefActor(actnum, "o6_wait:168"); - if (a->isInCurrentRoom() && a->_moving) - break; - return; - case 169: // SO_WAIT_FOR_MESSAGE Wait for message - if (VAR(VAR_HAVE_MSG)) - break; - return; - case 170: // SO_WAIT_FOR_CAMERA Wait for camera - if (_version >= 7) { - if (camera._dest != camera._cur) - break; - } else { - if (camera._cur.x / 8 != camera._dest.x / 8) - break; - } - - return; - case 171: // SO_WAIT_FOR_SENTENCE - if (_sentenceNum) { - if (_sentence[_sentenceNum - 1].freezeCount && !isScriptInUse(VAR(VAR_SENTENCE_SCRIPT))) - return; - break; - } - if (!isScriptInUse(VAR(VAR_SENTENCE_SCRIPT))) - return; - break; - case 226: // SO_WAIT_FOR_ANIMATION - offs = fetchScriptWordSigned(); - actnum = pop(); - a = derefActor(actnum, "o6_wait:226"); - if (a->isInCurrentRoom() && a->_needRedraw) - break; - return; - case 232: // SO_WAIT_FOR_TURN - // FIXME: This opcode is really odd. It's used a lot in The Dig. - // But sometimes it receives the actor ID as params, and sometimes an - // angle. However in (almost?) all cases, just before calling it, _curActor - // is set, so we can use it. I tried to add code that detects if an angle - // is passed, and if so, wait till that angle is reached, but that leads to hangs. - // It would be very good if somebody could disassmble the original code - // for this opcode so that we could figure out what's really going on here. - // - // For now, if the value passed in is divisible by 45, assume it is an - // angle, and use _curActor as the actor to wait for. - offs = fetchScriptWordSigned(); - actnum = pop(); - if (actnum % 45 == 0) { - actnum = _curActor; - } - a = derefActor(actnum, "o6_wait:232b"); - if (a->isInCurrentRoom() && a->_moving & MF_TURN) - break; - return; - default: - error("o6_wait: default case 0x%x", subOp); - } - - _scriptPointer += offs; - o6_breakHere(); -} - -void ScummEngine_v6::o6_soundKludge() { - int list[16]; - int num = getStackList(list, ARRAYSIZE(list)); - - _sound->soundKludge(list, num); - - // WORKAROUND for bug #1398195: The room-11-2016 script contains a - // slight bug causing it to busy-wait for a sound to finish. Even under - // the best of circumstances, this will cause the game to hang briefly. - // On platforms where threading is cooperative, it will cause the game - // to hang indefinitely. We identify the buggy part of the script by - // looking for a soundKludge() opcode immediately followed by a jump. - - if (_gameId == GID_CMI && _roomResource == 11 && vm.slot[_currentScript].number == 2016 && *_scriptPointer == 0x66) { - debug(3, "Working around script bug in room-11-2016"); - o6_breakHere(); - } -} - -void ScummEngine_v6::o6_isAnyOf() { - int list[100]; - int num; - int32 val; - - num = getStackList(list, ARRAYSIZE(list)); - val = pop(); - - while (--num >= 0) { - if (list[num] == val) { - push(1); - return; - } - } - - push(0); -} - -void ScummEngine_v6::o6_systemOps() { - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 158: // SO_RESTART - restart(); - break; - case 159: // SO_PAUSE - pauseGame(); - break; - case 160: // SO_QUIT - shutDown(); - break; - default: - error("o6_systemOps invalid case %d", subOp); - } -} - -void ScummEngine_v6::o6_delay() { - uint32 delay = (uint16)pop(); - vm.slot[_currentScript].delay = delay; - vm.slot[_currentScript].status = ssPaused; - o6_breakHere(); -} - -void ScummEngine_v6::o6_delaySeconds() { - uint32 delay = (uint32)pop(); - delay = delay * 60; - vm.slot[_currentScript].delay = delay; - vm.slot[_currentScript].status = ssPaused; - o6_breakHere(); -} - -void ScummEngine_v6::o6_delayMinutes() { - uint32 delay = (uint16)pop() * 3600; - vm.slot[_currentScript].delay = delay; - vm.slot[_currentScript].status = ssPaused; - o6_breakHere(); -} - -void ScummEngine_v6::o6_stopSentence() { - _sentenceNum = 0; - stopScript(VAR(VAR_SENTENCE_SCRIPT)); - clearClickedStatus(); -} - -void ScummEngine_v6::o6_printLine() { - _actorToPrintStrFor = 0xFF; - decodeParseString(0, 0); -} - -void ScummEngine_v6::o6_printText() { - decodeParseString(1, 0); -} - -void ScummEngine_v6::o6_printDebug() { - decodeParseString(2, 0); -} - -void ScummEngine_v6::o6_printSystem() { - decodeParseString(3, 0); -} - -void ScummEngine_v6::o6_printActor() { - decodeParseString(0, 1); -} - -void ScummEngine_v6::o6_printEgo() { - push(VAR(VAR_EGO)); - decodeParseString(0, 1); -} - -void ScummEngine_v6::o6_talkActor() { - _actorToPrintStrFor = pop(); - - _string[0].loadDefault(); - actorTalk(_scriptPointer); - - _scriptPointer += resStrLen(_scriptPointer) + 1; -} - -void ScummEngine_v6::o6_talkEgo() { - push(VAR(VAR_EGO)); - o6_talkActor(); -} - -void ScummEngine_v6::o6_dimArray() { - int data; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 199: // SO_INT_ARRAY - data = kIntArray; - break; - case 200: // SO_BIT_ARRAY - data = kBitArray; - break; - case 201: // SO_NIBBLE_ARRAY - data = kNibbleArray; - break; - case 202: // SO_BYTE_ARRAY - data = kByteArray; - break; - case 203: // SO_STRING_ARRAY - data = kStringArray; - break; - case 204: // SO_UNDIM_ARRAY - nukeArray(fetchScriptWord()); - return; - default: - error("o6_dimArray: default case %d", subOp); - } - - defineArray(fetchScriptWord(), data, 0, pop()); -} - -void ScummEngine_v6::o6_dummy() { - if (_heversion >= 60) { - stopObjectCode(); - } -} - -void ScummEngine_v6::o6_dim2dimArray() { - int a, b, data; - - byte subOp = fetchScriptByte(); - - switch (subOp) { - case 199: // SO_INT_ARRAY - data = kIntArray; - break; - case 200: // SO_BIT_ARRAY - data = kBitArray; - break; - case 201: // SO_NIBBLE_ARRAY - data = kNibbleArray; - break; - case 202: // SO_BYTE_ARRAY - data = kByteArray; - break; - case 203: // SO_STRING_ARRAY - data = kStringArray; - break; - default: - error("o6_dim2dimArray: default case %d", subOp); - } - - b = pop(); - a = pop(); - defineArray(fetchScriptWord(), data, a, b); -} - -void ScummEngine_v6::o6_abs() { - int a = pop(); - push(ABS(a)); -} - -void ScummEngine_v6::o6_distObjectObject() { - int a, b; - b = pop(); - a = pop(); - push(getDistanceBetween(true, a, 0, true, b, 0)); -} - -void ScummEngine_v6::o6_distObjectPt() { - int a, b, c; - c = pop(); - b = pop(); - a = pop(); - push(getDistanceBetween(true, a, 0, false, b, c)); -} - -void ScummEngine_v6::o6_distPtPt() { - int a, b, c, d; - d = pop(); - c = pop(); - b = pop(); - a = pop(); - push(getDistanceBetween(false, a, b, false, c, d)); -} - -void ScummEngine_v6::o6_drawBlastObject() { - int args[16]; - int a, b, c, d, e; - - getStackList(args, ARRAYSIZE(args)); - e = pop(); - d = pop(); - c = pop(); - b = pop(); - a = pop(); - enqueueObject(a, b, c, d, e, 0xFF, 0xFF, 1, 0); -} - -// Set BOMP processing window -void ScummEngine_v6::o6_setBlastObjectWindow() { - pop(); - pop(); - pop(); - pop(); - - // None of the scripts of The Dig and Full Throttle use this opcode. - // Sam & Max only uses it at the beginning of the highway subgame. In - // the original interpreter pop'ed arguments are just ignored and the - // clipping blastObject window is defined with (0, 0, 320, 200)... - // which matches the screen dimensions and thus, doesn't require - // another clipping operation. - // So, we just handle this as no-op opcode. -} - -void ScummEngine_v6::o6_kernelSetFunctions() { - int args[30]; - int num; - Actor *a; - - num = getStackList(args, ARRAYSIZE(args)); - - if (_version >= 7) { - switch (args[0]) { - case 4: - grabCursor(args[1], args[2], args[3], args[4]); - break; -#ifndef DISABLE_SCUMM_7_8 - case 6: { - if (_smushFrameRate == 0) - _smushFrameRate = 14; - - // SMUSH movie playback - if (args[1] == 0) { - assert(getStringAddressVar(VAR_VIDEONAME)); - if (strcmp((char *)getStringAddressVar(VAR_VIDEONAME), "sq3.san") == 0) - _smushFrameRate = 14; - - SmushPlayer *sp = new SmushPlayer(this, _smushFrameRate); - - // Correct incorrect smush filename in Macintosh FT demo - if ((_gameId == GID_FT) && (_features & GF_DEMO) && (_platform == Common::kPlatformMacintosh) && - (strcmp((char *)getStringAddressVar(VAR_VIDEONAME), "jumpgorge.san") == 0)) - sp->play("jumpgorg.san"); - else - sp->play((char *)getStringAddressVar(VAR_VIDEONAME)); - delete sp; - } else if (_gameId == GID_FT) { - const int insaneVarNum = ((_features & GF_DEMO) && (_platform == Common::kPlatformPC)) - ? 232 : 233; - - _insaneRunning = true; - _insane->setSmushParams(_smushFrameRate); - _insane->runScene(insaneVarNum); - _insaneRunning = false; - } - } - break; -#endif - case 12: - setCursorFromImg(args[1], (uint) - 1, args[2]); - break; - case 13: - derefActor(args[1], "o6_kernelSetFunctions:13")->remapActorPalette(args[2], args[3], args[4], -1); - break; - case 14: - derefActor(args[1], "o6_kernelSetFunctions:14")->remapActorPalette(args[2], args[3], args[4], args[5]); - break; - case 15: - _smushFrameRate = args[1]; - break; - case 16: - case 17: - enqueueText(getStringAddressVar(VAR_STRING2DRAW), args[3], args[4], args[2], args[1], (args[0] == 16)); - break; - case 20: - // it's used for turn on/off 'RadioChatter' effect for voice in the dig, but i's not needed - break; - case 107: - a = derefActor(args[1], "o6_kernelSetFunctions: 107"); - a->setScale((unsigned char)args[2], -1); - break; - case 108: - setupShadowPalette(args[1], args[2], args[3], args[4], args[5], args[6]); - break; - case 109: - setupShadowPalette(0, args[1], args[2], args[3], args[4], args[5]); - break; - case 114: - error("o6_kernelSetFunctions: stub114()"); - break; - case 117: - freezeScripts(2); - break; - case 118: - enqueueObject(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], 3); - break; - case 119: - enqueueObject(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], 0); - break; - case 124: - _saveSound = args[1]; - break; - case 215: - ConfMan.set("subtitles", args[1] != 0); - break; - default: - error("o6_kernelSetFunctions: default case %d (param count %d)", args[0], num); - break; - } - } else { - switch (args[0]) { - case 3: - // Dummy case - break; - case 4: - grabCursor(args[1], args[2], args[3], args[4]); - break; - case 5: - fadeOut(args[1]); - break; - case 6: - _fullRedraw = true; - redrawBGAreas(); - setActorRedrawFlags(); - processActors(); - fadeIn(args[1]); - break; - case 8: - startManiac(); - break; - case 9: - killAllScriptsExceptCurrent(); - break; - case 104: /* samnmax */ - nukeFlObjects(args[2], args[3]); - break; - case 107: /* set actor scale */ - a = derefActor(args[1], "o6_kernelSetFunctions: 107"); - a->setScale((unsigned char)args[2], -1); - break; - case 108: /* create proc_special_palette */ - case 109: - // Case 108 and 109 share the same function - if (num != 6) - error("o6_kernelSetFunctions sub op %d: expected 6 params but got %d", args[0], num); - setupShadowPalette(args[3], args[4], args[5], args[1], args[2], 0, 256); - break; - case 110: - _charset->clearCharsetMask(); - break; - case 111: - a = derefActor(args[1], "o6_kernelSetFunctions: 111"); - a->_shadowMode = args[2] + args[3]; - break; - case 112: /* palette shift? */ - setupShadowPalette(args[3], args[4], args[5], args[1], args[2], args[6], args[7]); - break; - case 114: - // Sam & Max film noir mode - if (_gameId == GID_SAMNMAX) { - // At this point ScummVM will already have set - // variable 0x8000 to indicate that the game is - // in film noir mode. All we have to do here is - // to mark the palette as "dirty", because - // updatePalette() will desaturate the colors - // as they are uploaded to the backend. - // - // This actually works better than the original - // interpreter, where actors would sometimes - // still be drawn in color. - setDirtyColors(0, 255); - } else - error("stub o6_kernelSetFunctions_114()"); - break; - case 117: - // Sam & Max uses this opcode in script-43, right - // before a screensaver is selected. - // - // Sam & Max uses variable 132 to specify the number of - // minutes of inactivity (no mouse movements) before - // starting the screensaver, so setting it to 0 will - // help in debugging. - freezeScripts(0x80); - break; - case 119: - enqueueObject(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], 0); - break; - case 120: - swapPalColors(args[1], args[2]); - break; - case 122: - VAR(VAR_SOUNDRESULT) = - (short)_imuse->doCommand (num - 1, &args[1]); - break; - case 123: - copyPalColor(args[2], args[1]); - break; - case 124: - _saveSound = args[1]; - break; - default: - error("o6_kernelSetFunctions: default case %d (param count %d)", args[0], num); - break; - } - } -} - -void ScummEngine_v6::o6_kernelGetFunctions() { - int args[30]; - int i; - int slot; - Actor *a; - - getStackList(args, ARRAYSIZE(args)); - - switch (args[0]) { - case 113: - // This is used for the Sam & Max paint-by-numbers mini-game - // to find out what color to change. I think that what we have - // the virtual mouse coordinates, because that's what used - // everywhere else in the script. - - { - VirtScreen *vs = &virtscr[0]; - if (args[1] < 0 || args[1] >= vs->w || args[2] < 0 || args[2] >= vs->h) { - // FIXME: Until we know what to do in this case... - debug(0, "o6_kernelGetFunctions:113: asking for pixel (%d, %d) outside of %dx%d screen", args[1], args[2], vs->w, vs->h); - push(0); - } else - push(*((byte *)vs->pixels + args[1] + args[2] * vs->pitch)); - } - break; - case 115: - push(getSpecialBox(args[1], args[2])); - break; - case 116: - push(checkXYInBoxBounds(args[3], args[1], args[2])); - break; - case 206: - push(remapPaletteColor(args[1], args[2], args[3], -1)); - break; - case 207: - i = getObjectIndex(args[1]); - assert(i); - push(_objs[i].x_pos); - break; - case 208: - i = getObjectIndex(args[1]); - assert(i); - push(_objs[i].y_pos); - break; - case 209: - i = getObjectIndex(args[1]); - assert(i); - push(_objs[i].width); - break; - case 210: - i = getObjectIndex(args[1]); - assert(i); - push(_objs[i].height); - break; - case 211: - /* - 13 = thrust - 336 = thrust - 328 = thrust - 27 = abort - 97 = left - 331 = left - 115 = right - 333 = right - */ - - push(getKeyState(args[1])); - break; - case 212: - a = derefActor(args[1], "o6_kernelGetFunctions:212"); - // This is used by walk scripts - push(a->_frame); - break; - case 213: - slot = getVerbSlot(args[1], 0); - push(_verbs[slot].curRect.left); - break; - case 214: - slot = getVerbSlot(args[1], 0); - push(_verbs[slot].curRect.top); - break; - case 215: - if ((_extraBoxFlags[args[1]] & 0x00FF) == 0x00C0) { - push(_extraBoxFlags[args[1]]); - } else { - push(getBoxFlags(args[1])); - } - break; - default: - error("o6_kernelGetFunctions: default case %d", args[0]); - } -} - -// FIXME: check either some warning will trigger. I am not sure that those -// keys are queried in scripts at all -int ScummEngine::getKeyState(int key) { - switch (key) { - case 0x145: - warning("ScummEngine::getKeyState(%x) 'numlock' is probed", key); - return 0; - break; - case 0x164: - warning("ScummEngine::getKeyState(%x) 'left shift' is probed", key); - return 0; - break; - case 0x165: - warning("ScummEngine::getKeyState(%x) 'right shift' is probed", key); - return 0; - break; - case 0x166: - case 0x167: - warning("ScummEngine::getKeyState(%x) 'alt' is probed", key); - return 0; - break; - case 0x168: - warning("ScummEngine::getKeyState(%x) 'left ctrl' is probed", key); - return 0; - break; - case 0x202a: - warning("ScummEngine::getKeyState(%x) 'gray *' is probed", key); - return 0; - break; - case 0x202d: - warning("ScummEngine::getKeyState(%x) 'gray -' is probed", key); - return 0; - break; - case 0x147: // Home - return (_keyDownMap[0x107] || _keyDownMap[0x115]) ? 1 : 0; - break; - case 0x148: // Up - return (_keyDownMap[0x108] || _keyDownMap[0x111] || - _keyDownMap[0x38]) ? 1 : 0; - break; - case 0x149: // PgUp - return (_keyDownMap[0x109] || _keyDownMap[0x118]) ? 1 : 0; - break; - case 0x14A: // Gray- - return (_keyDownMap[0x10d] || _keyDownMap[0x2d]) ? 1 : 0; - break; - case 0x14B: // Left - return (_keyDownMap[0x104] || _keyDownMap[0x114] || - _keyDownMap[0x34]) ? 1 : 0; - break; - case 0x14C: // 5 - return (_keyDownMap[0x105]) ? 1 : 0; - break; - case 0x14D: // Right - return (_keyDownMap[0x106] || _keyDownMap[0x113] || - _keyDownMap[0x36]) ? 1 : 0; - break; - case 0x14E: // Gray+ - return (_keyDownMap[0x10e] || - (_keyDownMap[0x13d] && _keyDownMap[0x12f])) ? 1 : 0; - break; - case 0x14F: // End - return (_keyDownMap[0x101] || _keyDownMap[0x117]) ? 1 : 0; - break; - case 0x150: // Down - return (_keyDownMap[0x102] || _keyDownMap[0x112] || - _keyDownMap[0x32]) ? 1 : 0; - break; - case 0x151: // PgDn - return (_keyDownMap[0x103] || _keyDownMap[0x119]) ? 1 : 0; - break; - case 0x152: // Ins - return (_keyDownMap[0x100] || _keyDownMap[0x115]) ? 1 : 0; - break; - case 0x153: // Del - return (_keyDownMap[0x10a] || _keyDownMap[0x7f]) ? 1 : 0; - break; - default: - break; - } - - if (key >= 0x13b && key <= 0x144) { // F1-F10 - key -= 0x13b - 0x11a; - } else if (key >= 0x154 && key <= 0x15d) { // Shift+F1-F10 - key -= 0x154 - 0x11a; // map it to just F1-F10 - - warning("ScummEngine::getKeyState(%x) 'Shift-F%d' is probed", key, key-0x153); - } else if (key > 0x8000) { // Alt - key -= 0x8000; - key += 154; // see ScummEngine::parseEvents() - } else if (key > 0x4000) { // Ctrl - key -= 0x4000; - key -= 0x40; - } else if (key > 0x2000) { // Gray keys - key -= 0x2000; - warning("ScummEngine::getKeyState(%x) 'gray key' is probed", key); - } - - return (_keyDownMap[key]) ? 1 : 0; -} - -void ScummEngine_v6::o6_delayFrames() { - ScriptSlot *ss = &vm.slot[_currentScript]; - if (ss->delayFrameCount == 0) { - ss->delayFrameCount = pop(); - } else { - ss->delayFrameCount--; - } - if (ss->delayFrameCount) { - _scriptPointer--; - o6_breakHere(); - } -} - -void ScummEngine_v6::o6_pickOneOf() { - int args[100]; - int i, num; - - num = getStackList(args, ARRAYSIZE(args)); - i = pop(); - if (i < 0 || i > num) - error("o6_pickOneOf: %d out of range (0, %d)", i, num - 1); - push(args[i]); -} - -void ScummEngine_v6::o6_pickOneOfDefault() { - int args[100]; - int i, num, def; - - def = pop(); - num = getStackList(args, ARRAYSIZE(args)); - i = pop(); - if (i < 0 || i >= num) - i = def; - else - i = args[i]; - push(i); -} - -void ScummEngine_v6::o6_stampObject() { - int object, x, y, state; - - state = pop(); - y = pop(); - x = pop(); - object = pop(); - if (_version >= 7 && object < 30) { - if (state == 0) - state = 255; - - Actor *a = derefActor(object, "o6_stampObject"); - a->_scalex = state; - a->_scaley = state; - a->putActor(x, y, _currentRoom); - a->_drawToBackBuf = true; - a->drawActorCostume(); - a->_drawToBackBuf = false; - a->drawActorCostume(); - return; - } - - if (state == 0) - state = 1; - - int objnum = getObjectIndex(object); - if (objnum == -1) - return; - - if (x != -1) { - _objs[objnum].x_pos = x * 8; - _objs[objnum].y_pos = y * 8; - } - - putState(object, state); - drawObject(objnum, 0); -} - -void ScummEngine_v6::o6_stopTalking() { - stopTalk(); -} - -void ScummEngine_v6::o6_findAllObjects() { - int room = pop(); - int i = 1; - - if (room != _currentRoom) - error("o6_findAllObjects: current room is not %d", room); - writeVar(0, 0); - defineArray(0, kIntArray, 0, _numLocalObjects + 1); - writeArray(0, 0, 0, _numLocalObjects); - - while (i < _numLocalObjects) { - writeArray(0, 0, i, _objs[i].obj_nr); - i++; - } - - push(readVar(0)); -} - -void ScummEngine_v6::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_v6::o6_shuffle() { - int b = pop(); - int a = pop(); - shuffleArray(fetchScriptWord(), a, b); -} - -void ScummEngine_v6::o6_pickVarRandom() { - int num; - int args[100]; - int dim1; - - num = getStackList(args, ARRAYSIZE(args)); - int value = fetchScriptWord(); - - if (readVar(value) == 0) { - defineArray(value, kIntArray, 0, num); - if (num > 0) { - int16 counter = 0; - do { - writeArray(value, 0, counter + 1, args[counter]); - } while (++counter < num); - } - - shuffleArray(value, 1, num); - writeArray(value, 0, 0, 2); - push(readArray(value, 0, 1)); - return; - } - - num = readArray(value, 0, 0); - - ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(value)); - dim1 = FROM_LE_16(ah->dim1) - 1; - - if (dim1 < num) { - int16 var_2 = readArray(value, 0, num - 1); - shuffleArray(value, 1, dim1); - 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_v6::o6_getDateTime() { - struct tm *t; - time_t now = time(NULL); - - t = localtime(&now); - - VAR(VAR_TIMEDATE_YEAR) = t->tm_year; - VAR(VAR_TIMEDATE_MONTH) = t->tm_mon; - VAR(VAR_TIMEDATE_DAY) = t->tm_mday; - VAR(VAR_TIMEDATE_HOUR) = t->tm_hour; - VAR(VAR_TIMEDATE_MINUTE) = t->tm_min; - - if (_version == 8) - VAR(VAR_TIMEDATE_SECOND) = t->tm_sec; -} - -void ScummEngine_v6::o6_getPixel() { - // This opcode is used to check fir ground area in the "Asteroid Lander" - // minigame in "The Dig" - int x, y; - - if (_heversion == 61) { - x = pop(); - y = pop(); - } else { - y = pop(); - x = pop(); - } - - VirtScreen *vs = findVirtScreen(y); - - if (vs == NULL || x > _screenWidth - 1 || x < 0) { - push(-1); - return; - } - - byte area = *vs->getPixels(x, y - vs->topline); - push(area); -} - -void ScummEngine_v6::o6_setBoxSet() { - int arg = pop() - 1; - - const byte *room = getResourceAddress(rtRoom, _roomResource); - const byte *boxd = NULL, *boxm = NULL; - int32 dboxSize, mboxSize; - int i; - - ResourceIterator boxds(room, false); - for (i = 0; i < arg; i++) - boxd = boxds.findNext(MKID('BOXD')); - - if (!boxd) - error("ScummEngine_v6::o6_setBoxSet: Can't find dboxes for set %d", arg); - - dboxSize = READ_BE_UINT32(boxd + 4) - 8; - byte *matrix = res.createResource(rtMatrix, 2, dboxSize); - - assert(matrix); - memcpy(matrix, boxd + 8, dboxSize); - - ResourceIterator boxms(room, false); - for (i = 0; i < arg; i++) - boxm = boxms.findNext(MKID('BOXM')); - - if (!boxm) - error("ScummEngine_v6::o6_setBoxSet: Can't find mboxes for set %d", arg); - - mboxSize = READ_BE_UINT32(boxm + 4) - 8; - matrix = res.createResource(rtMatrix, 1, mboxSize); - - assert(matrix); - memcpy(matrix, boxm + 8, mboxSize); - - if (_version == 7) - putActors(); -} - -void ScummEngine_v6::decodeParseString(int m, int n) { - byte b = fetchScriptByte(); - - switch (b) { - case 65: // SO_AT - _string[m].ypos = pop(); - _string[m].xpos = pop(); - _string[m].overhead = false; - break; - case 66: // SO_COLOR - _string[m].color = pop(); - break; - case 67: // SO_CLIPPED - _string[m].right = pop(); - break; - case 69: // SO_CENTER - _string[m].center = true; - _string[m].overhead = false; - break; - case 71: // SO_LEFT - _string[m].center = false; - _string[m].overhead = false; - break; - case 72: // SO_OVERHEAD - _string[m].overhead = true; - _string[m].no_talk_anim = false; - break; - case 73: // SO_SAY_VOICE - error("decodeParseString: case 73"); - break; - case 74: // SO_MUMBLE - _string[m].no_talk_anim = true; - break; - case 75: // SO_TEXTSTRING - printString(m, _scriptPointer); - _scriptPointer += resStrLen(_scriptPointer) + 1; - break; - case 0xFE: - _string[m].loadDefault(); - if (n) - _actorToPrintStrFor = pop(); - break; - case 0xFF: - _string[m].saveDefault(); - break; - default: - error("decodeParseString: default case 0x%x", b); - } -} - -} // End of namespace Scumm |
