scummvm/engines/cine/script_os.cpp
2021-12-26 18:48:43 +01:00

883 lines
25 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
/** \file
* Operation Stealth script interpreter file
*/
#include "common/endian.h"
#include "common/textconsole.h"
#include "cine/cine.h"
#include "cine/bg_list.h"
#include "cine/object.h"
#include "cine/sound.h"
#include "cine/various.h"
#include "cine/script.h"
namespace Cine {
const Opcode *OSScript::_opcodeTable = nullptr;
unsigned int OSScript::_numOpcodes = 0;
void OSScript::setupTable() {
static const Opcode opcodeTable[] = {
/* 00 */
{ &FWScript::o1_modifyObjectParam, "bbw" },
{ &FWScript::o1_getObjectParam, "bbb" },
{ &FWScript::o1_addObjectParam, "bbw" },
{ &FWScript::o1_subObjectParam, "bbw" },
/* 04 */
{ &FWScript::o1_mulObjectParam, "bbw" },
{ &FWScript::o1_divObjectParam, "bbw" },
{ &FWScript::o1_compareObjectParam, "bbw" },
{ &FWScript::o1_setupObject, "bwwww" },
/* 08 */
{ &FWScript::o1_checkCollision, "bwwww" },
{ &FWScript::o1_loadVar, "bc" },
{ &FWScript::o1_addVar, "bc" },
{ &FWScript::o1_subVar, "bc" },
/* 0C */
{ &FWScript::o1_mulVar, "bc" },
{ &FWScript::o1_divVar, "bc" },
{ &FWScript::o1_compareVar, "bc" },
{ &FWScript::o1_modifyObjectParam2, "bbb" },
/* 10 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o1_loadMask0, "b" },
/* 14 */
{ &FWScript::o1_unloadMask0, "b" },
{ &FWScript::o1_addToBgList, "b" },
{ &FWScript::o1_loadMask1, "b" },
{ &FWScript::o1_unloadMask1, "b" },
/* 18 */
{ &FWScript::o1_loadMask4, "b" },
{ &FWScript::o1_unloadMask4, "b" },
{ &FWScript::o1_addSpriteFilledToBgList, "b" },
{ &FWScript::o1_clearBgIncrustList, "" },
/* 1C */
{ nullptr, nullptr },
{ &FWScript::o1_label, "l" },
{ &FWScript::o1_goto, "b" },
{ &FWScript::o1_gotoIfSup, "b" },
/* 20 */
{ &FWScript::o1_gotoIfSupEqu, "b" },
{ &FWScript::o1_gotoIfInf, "b" },
{ &FWScript::o1_gotoIfInfEqu, "b" },
{ &FWScript::o1_gotoIfEqu, "b" },
/* 24 */
{ &FWScript::o1_gotoIfDiff, "b" },
{ &FWScript::o1_removeLabel, "b" },
{ &FWScript::o1_loop, "bb" },
{ nullptr, nullptr },
/* 28 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 2C */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 30 */
{ nullptr, nullptr },
{ &FWScript::o1_startGlobalScript, "b" },
{ &FWScript::o1_endGlobalScript, "b" },
{ nullptr, nullptr },
/* 34 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 38 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o1_loadAnim, "s" },
/* 3C */
{ &FWScript::o1_loadBg, "s" },
{ &FWScript::o2_loadCt, "s" },
{ nullptr, nullptr },
{ &FWScript::o2_loadPart, "s" },
/* 40 */
{ &FWScript::o1_closePart, "" },
{ &FWScript::o1_loadNewPrcName, "bs" },
{ &FWScript::o1_requestCheckPendingDataLoad, "" },
{ nullptr, nullptr },
/* 44 */
{ nullptr, nullptr },
{ &FWScript::o1_blitAndFade, "" },
{ &FWScript::o1_fadeToBlack, "" },
{ &FWScript::o1_transformPaletteRange, "bbwww" },
/* 48 */
{ nullptr, nullptr },
{ &FWScript::o1_setDefaultMenuBgColor, "b" },
{ &FWScript::o1_palRotate, "bbb" },
{ nullptr, nullptr },
/* 4C */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o1_break, "" },
/* 50 */
{ &FWScript::o1_endScript, "x" },
{ &FWScript::o1_message, "bwwww" },
{ &FWScript::o1_loadGlobalVar, "bc" },
{ &FWScript::o1_compareGlobalVar, "bc" },
/* 54 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 58 */
{ nullptr, nullptr },
{ &FWScript::o1_declareFunctionName, "s" },
{ &FWScript::o1_freePartRange, "bb" },
{ &FWScript::o1_unloadAllMasks, "" },
/* 5C */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 60 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o1_setScreenDimensions, "wwww" },
/* 64 */
{ &FWScript::o1_displayBackground, "" },
{ &FWScript::o1_initializeZoneData, "" },
{ &FWScript::o1_setZoneDataEntry, "bw" },
{ &FWScript::o1_getZoneDataEntry, "bb" },
/* 68 */
{ &FWScript::o1_setPlayerCommandPosY, "b" },
{ &FWScript::o1_allowPlayerInput, "" },
{ &FWScript::o1_disallowPlayerInput, "" },
{ &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x95 and 0xA9. */
/* 6C */
{ nullptr, nullptr },
{ &FWScript::o1_loadMusic, "s" },
{ &FWScript::o1_playMusic, "" },
{ &FWScript::o1_fadeOutMusic, "" },
/* 70 */
{ &FWScript::o1_stopSample, "" },
{ &FWScript::o1_op71, "bw" }, /* TODO: Name this opcode properly. */
{ &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x73. TODO: Name this opcode properly. */
{ &FWScript::o1_op72, "wbw" }, /* Same as opcode 0x72. */
/* 74 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o2_playSample, "bbwbww" },
/* 78 */
{ &FWScript::o2_playSampleAlt, "bbwbww" },
{ &FWScript::o1_disableSystemMenu, "b" },
{ &FWScript::o1_loadMask5, "b" },
{ &FWScript::o1_unloadMask5, "b" }, /* Last opcode used by Future Wars. */
/* 7C */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o2_addSeqListElement, "bbbbwww" },
/* 80 */
{ &FWScript::o2_removeSeq, "bb" },
{ &FWScript::o2_clearSeqList, "" },
{ &FWScript::o2_modifySeqListElement, "bbwwb" },
{ &FWScript::o2_isSeqRunning, "bb" },
/* 84 */
{ &FWScript::o2_gotoIfSupNearest, "b" },
{ &FWScript::o2_gotoIfSupEquNearest, "b" },
{ &FWScript::o2_gotoIfInfNearest, "b" },
{ &FWScript::o2_gotoIfInfEquNearest, "b" },
/* 88 */
{ &FWScript::o2_gotoIfEquNearest, "b" },
{ &FWScript::o2_gotoIfDiffNearest, "b" },
{ nullptr, nullptr },
{ &FWScript::o2_startObjectScript, "b" },
/* 8C */
{ &FWScript::o2_stopObjectScript, "b" },
{ &FWScript::o2_op8D, "wwwwwwww" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_addBackground, "bs" },
{ &FWScript::o2_removeBackground, "b" },
/* 90 */
{ &FWScript::o2_loadAbs, "bs" },
{ &FWScript::o2_loadBg, "b" },
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 94 */
{ nullptr, nullptr },
{ &FWScript::o1_changeDataDisk, "b" }, /* Same as opcodes 0x6B and 0xA9. */
{ nullptr, nullptr },
{ nullptr, nullptr },
/* 98 */
{ nullptr, nullptr },
{ nullptr, nullptr },
{ &FWScript::o2_wasZoneChecked, "b" },
{ &FWScript::o2_op9B, "wwwwwwww" }, /* TODO: Name this opcode properly. */
/* 9C */
{ &FWScript::o2_op9C, "wwww" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_useBgScroll, "b" },
{ &FWScript::o2_setAdditionalBgVScroll, "c" },
{ &FWScript::o2_op9F, "ww" }, /* TODO: Name this opcode properly. */
/* A0 */
{ &FWScript::o2_addGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_removeGfxElementType20, "ww" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_addGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_removeGfxElementType21, "ww" }, /* TODO: Name this opcode properly. */
/* A4 */
{ &FWScript::o2_loadMask22, "b" }, /* TODO: Name this opcode properly. */
{ &FWScript::o2_unloadMask22, "b" }, /* TODO: Name this opcode properly. */
{ nullptr, nullptr },
{ nullptr, nullptr },
/* A8 */
{ nullptr, nullptr },
{ &FWScript::o1_changeDataDisk, "b" } /* Same as opcodes 0x6B and 0x95. */
};
OSScript::_opcodeTable = (const Opcode *)opcodeTable;
OSScript::_numOpcodes = ARRAYSIZE(opcodeTable);
}
/**
* Contructor for global scripts
* @param script Script bytecode reference
* @param idx Script bytecode index
*/
OSScript::OSScript(const RawScript &script, int16 idx) :
FWScript(script, idx, new OSScriptInfo) {}
/**
* Constructor for object scripts
* @param script Script bytecode reference
* @param idx Script bytecode index
*/
OSScript::OSScript(RawObjectScript &script, int16 idx) :
FWScript(script, idx, new OSScriptInfo) {}
/**
* Copy constructor
*/
OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
/**
* Restore script state from savefile
* @param labels Restored script labels
* @param local Restored local script variables
* @param compare Restored last comparison result
* @param pos Restored script position
*/
void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
FWScript::load(labels, local, compare, pos);
}
/**
* Get opcode info string
* @param opcode Opcode to look for in opcode table
*/
const char *OSScriptInfo::opcodeInfo(byte opcode) const {
if (opcode == 0 || opcode > OSScript::_numOpcodes) {
return nullptr;
}
if (!OSScript::_opcodeTable[opcode - 1].args) {
warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
return nullptr;
}
return OSScript::_opcodeTable[opcode - 1].args;
}
/**
* Get opcode handler pointer
* @param opcode Opcode to look for in opcode table
*/
OpFunc OSScriptInfo::opcodeHandler(byte opcode) const {
if (opcode == 0 || opcode > OSScript::_numOpcodes) {
return nullptr;
}
if (!OSScript::_opcodeTable[opcode - 1].proc) {
warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
return nullptr;
}
return OSScript::_opcodeTable[opcode - 1].proc;
}
/**
* Create new OSScript instance
* @param script Script bytecode
* @param index Bytecode index
*/
FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
return new OSScript(script, index);
}
/**
* Create new OSScript instance
* @param script Object script bytecode
* @param index Bytecode index
*/
FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
return new OSScript(script, index);
}
/**
* Load saved OSScript instance
* @param script Script bytecode
* @param index Bytecode index
* @param local Local variables
* @param labels Script labels
* @param compare Last compare result
* @param pos Position in script
*/
FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
OSScript *tmp = new OSScript(script, index);
assert(tmp);
tmp->load(labels, local, compare, pos);
return tmp;
}
/**
* Load saved OSScript instance
* @param script Object script bytecode
* @param index Bytecode index
* @param local Local variables
* @param labels Script labels
* @param compare Last compare result
* @param pos Position in script
*/
FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
OSScript *tmp = new OSScript(script, index);
assert(tmp);
tmp->load(labels, local, compare, pos);
return tmp;
}
// ------------------------------------------------------------------------
// OPERATION STEALTH opcodes
// ------------------------------------------------------------------------
/** Load collision table data */
int FWScript::o2_loadCt() {
const char *param = getNextString();
debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
loadCtOS(param);
removeBgIncrustsWithBgIdx(kCollisionPageBgIdxAlias);
return 0;
}
int FWScript::o2_loadPart() {
const char *param = getNextString();
debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
return 0;
}
int FWScript::o2_playSample() {
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
// no-op in these versions
getNextByte();
getNextByte();
getNextWord();
getNextByte();
getNextWord();
getNextWord();
return 0;
}
debugC(5, kCineDebugScript, "Line: %d: o2_playSample()", _line);
byte mode = getNextByte();
byte channel = getNextByte();
int16 param3 = getNextWord();
int16 param4 = getNextByte();
int16 param5 = getNextWord();
uint16 size = getNextWord();
if (mode == 2) {
switch (param4) {
case 0:
param4 = param5;
break;
case 1:
param4 = _localVars[param5];
break;
case 2:
param4 = _globalVars[param5];
break;
}
}
g_sound->playSound(mode, channel, param3, param4, param5, size);
return 0;
}
int FWScript::o2_playSampleAlt() {
byte num = getNextByte();
byte channel = getNextByte();
uint16 frequency = getNextWord();
/* byte param4 = */getNextByte();
/* uint16 param5 = */getNextWord();
uint16 size = getNextWord();
if (size == 0xFFFF) {
size = g_cine->_animDataTable[num]._width * g_cine->_animDataTable[num]._height;
}
if (g_cine->_animDataTable[num].data()) {
if (g_cine->getPlatform() == Common::kPlatformDOS) {
// if speaker output is available, play sound on it
// if it's another device, don't play anything
// TODO: implement this, it's used in the introduction for example
// on each letter displayed
} else {
g_sound->playSound(channel, frequency, g_cine->_animDataTable[num].data(), size, 0, 0, 63, 0);
}
}
return 0;
}
int FWScript::o2_addSeqListElement() {
byte param1 = getNextByte();
byte param2 = getNextByte();
byte param3 = getNextByte();
byte param4 = getNextByte();
uint16 param5 = getNextWord();
uint16 param6 = getNextWord();
uint16 param7 = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
return 0;
}
int FWScript::o2_removeSeq() {
byte a = getNextByte();
byte b = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d)", _line, a, b);
removeSeq(a, 0, b);
return 0;
}
/**
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
*/
int FWScript::o2_clearSeqList() {
debugC(5, kCineDebugScript, "Line: %d: clearSeqList()", _line);
g_cine->_seqList.clear();
return 0;
}
int FWScript::o2_modifySeqListElement() {
byte a = getNextByte();
byte b = getNextByte();
uint16 c = getNextWord();
uint16 d = getNextWord();
byte e = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: o2_modifySeqListElement(%d,%d,%d,%d,%d)", _line, a, b, c, d, e);
modifySeqListElement(a, 0, b, c, d, e);
return 0;
}
/**
* @todo Check whether this opcode's name is backwards (i.e. should it be o2_isSeqNotRunning?)
*/
int FWScript::o2_isSeqRunning() {
byte a = getNextByte();
byte b = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: o2_isSeqRunning(%d,%d)", _line, a, b);
if (isSeqRunning(a, 0, b)) {
_compare = 1;
} else {
_compare = 0;
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfSupNearest() {
byte labelIdx = getNextByte();
if (_compare == kCmpGT) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfSupEquNearest() {
byte labelIdx = getNextByte();
if (_compare & (kCmpGT | kCmpEQ)) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfInfNearest() {
byte labelIdx = getNextByte();
if (_compare == kCmpLT) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfInfEquNearest() {
byte labelIdx = getNextByte();
if (_compare & (kCmpLT | kCmpEQ)) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfEquNearest() {
byte labelIdx = getNextByte();
if (_compare == kCmpEQ) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
/**
* @todo The assert may produce false positives and requires testing
*/
int FWScript::o2_gotoIfDiffNearest() {
byte labelIdx = getNextByte();
if (_compare != kCmpEQ) {
assert(_labels[labelIdx] != -1);
debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
_pos = _script.getLabel(*_info, labelIdx, _pos);
} else {
debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
}
return 0;
}
int FWScript::o2_startObjectScript() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
runObjectScript(param);
return 0;
}
int FWScript::o2_stopObjectScript() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
ScriptList::iterator it = g_cine->_objectScripts.begin();
for (; it != g_cine->_objectScripts.end(); ++it) {
if ((*it)->_index == param) {
(*it)->_index = -1;
}
}
return 0;
}
int FWScript::o2_op8D() {
uint16 objIdx1 = getNextWord();
uint16 xAdd1 = getNextWord();
uint16 yAdd1 = getNextWord();
uint16 maskAdd1 = getNextWord();
uint16 objIdx2 = getNextWord();
uint16 xAdd2 = getNextWord();
uint16 yAdd2 = getNextWord();
uint16 maskAdd2 = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: o2_op8D(%d, %d, %d, %d, %d, %d, %d, %d)", _line, objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2);
_compare = compareObjectParamRanges(objIdx1, xAdd1, yAdd1, maskAdd1, objIdx2, xAdd2, yAdd2, maskAdd2);
return 0;
}
int FWScript::o2_addBackground() {
byte param1 = getNextByte();
const char *param2 = getNextString();
debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
renderer->addBackground(param2, param1);
removeBgIncrustsWithBgIdx(param1);
return 0;
}
int FWScript::o2_removeBackground() {
byte param = getNextByte();
assert(param);
debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
renderer->removeBg(param);
removeBgIncrustsWithBgIdx(param);
return 0;
}
int FWScript::o2_loadAbs() {
byte param1 = getNextByte();
const char *param2 = getNextString();
debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
// Load the resource to an absolute position
if (loadResource(param2, param1) == -1) { // Check if the loading failed
// WORKAROUND: In the 256 color PC version of Operation Stealth when
// walking out of the airport in Santa Paragua to the street the
// player character should be seen as a grey silhuette while walking
// behind the glass. But actually the player character is completely
// invisible when walking behind the glass because the animation files
// used are wrongly loaded. In AIRPORT.PRC's 6th script there are
// calls loadAbs("JOHN01.ANI", 73) and loadAbs("JOHN02.ANI", 37) to
// load the animations involved but no such files are found with the
// game. Corresponding SET-files are found though. As it worked and
// looked fine when I tried loading them instead of the missing ANI
// files I'm doing so here. NOTE: At least the German Amiga version
// of Operation Stealth seems to have all the files involved
// (JOHN01.ANI, JOHN02.ANI, JOHN01.SET and JOHN02.SET).
if (scumm_stricmp(param2, "JOHN01.ANI") == 0 && param1 == 73) {
loadResource("JOHN01.SET", param1);
} else if (scumm_stricmp(param2, "JOHN02.ANI") == 0 && param1 == 37) {
loadResource("JOHN02.SET", param1);
}
}
return 0;
}
int FWScript::o2_loadBg() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
if (param <= 8) {
renderer->selectBg(param);
}
return 0;
}
int FWScript::o2_wasZoneChecked() {
byte param = getNextByte();
_compare = (param < NUM_MAX_ZONE && g_cine->_zoneQuery[param]) ? 1 : 0;
debugC(5, kCineDebugScript, "Line: %d: o2_wasZoneChecked(%d)", _line, param);
return 0;
}
/**
* @todo Implement this instruction
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
*/
int FWScript::o2_op9B() {
uint16 a = getNextWord();
uint16 b = getNextWord();
uint16 c = getNextWord();
uint16 d = getNextWord();
uint16 e = getNextWord();
uint16 f = getNextWord();
uint16 g = getNextWord();
uint16 h = getNextWord();
warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
return 0;
}
/**
* @todo Implement this instruction
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
*/
int FWScript::o2_op9C() {
uint16 a = getNextWord();
uint16 b = getNextWord();
uint16 c = getNextWord();
uint16 d = getNextWord();
warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
return 0;
}
int FWScript::o2_useBgScroll() {
byte param = getNextByte();
assert(param < 9);
debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
if (param <= 8) {
renderer->selectScrollBg(param);
}
return 0;
}
int FWScript::o2_setAdditionalBgVScroll() {
uint16 mouseX, mouseY;
unsigned int scroll = renderer->getScroll();
byte param1 = getNextByte();
if (param1) {
byte param2 = getNextByte();
switch (param1) {
case 1:
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
scroll = _localVars[param2];
break;
case 2:
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = globalVar[%d]", _line, param2);
scroll = _globalVars[param2];
break;
case 3:
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = mouseX", _line);
getMouseData(mouseUpdateStatus, &dummyU16, &mouseX, &mouseY);
scroll = mouseX;
break;
case 4:
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = mouseY", _line);
getMouseData(mouseUpdateStatus, &dummyU16, &mouseX, &mouseY);
scroll = mouseY;
break;
case 5:
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = rand() %% %d", _line, param2);
scroll = ((param2 == 0) ? 0 : g_cine->_rnd.getRandomNumber(param2 - 1));
break;
}
} else {
uint16 param2 = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
scroll = param2;
}
renderer->setScroll(scroll);
return 0;
}
/**
* @todo Implement this instruction
* @note According to the scripts' opcode usage comparison this opcode isn't used at all.
* @note In Operation Stealth 16 color DOS version this calculates temporary values and discards them.
*/
int FWScript::o2_op9F() {
warning("o2_op9F()");
/* uint16 param1 = */getNextWord();
/* uint16 param2 = */getNextWord();
return 0;
}
int FWScript::o2_addGfxElementType20() {
uint16 param1 = getNextWord();
uint16 param2 = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType20(%d,%d)", _line, param1, param2);
addGfxElement(param1, param2, 20);
return 0;
}
int FWScript::o2_removeGfxElementType20() {
uint16 idx = getNextWord();
uint16 param = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType20(%d,%d)", _line, idx, param);
removeGfxElement(idx, param, 20);
return 0;
}
int FWScript::o2_addGfxElementType21() {
uint16 a = getNextWord();
uint16 b = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: o2_addGfxElementType21(%d,%d)", _line, a, b);
addGfxElement(a, b, 21);
return 0;
}
int FWScript::o2_removeGfxElementType21() {
uint16 a = getNextWord();
uint16 b = getNextWord();
debugC(5, kCineDebugScript, "Line: %d: o2_removeGfxElementType21(%d,%d)", _line, a, b);
removeGfxElement(a, b, 21);
return 0;
}
int FWScript::o2_loadMask22() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
addOverlay(param, 22);
return 0;
}
int FWScript::o2_unloadMask22() {
byte param = getNextByte();
debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
removeOverlay(param, 22);
return 0;
}
} // End of namespace Cine