aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/script_fw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/cine/script_fw.cpp')
-rw-r--r--engines/cine/script_fw.cpp2945
1 files changed, 2945 insertions, 0 deletions
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
new file mode 100644
index 0000000000..f833d7c30b
--- /dev/null
+++ b/engines/cine/script_fw.cpp
@@ -0,0 +1,2945 @@
+/* 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 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$
+ *
+ */
+
+/*! \file
+ * Future Wars script interpreter file
+ */
+
+#include "common/endian.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 {
+
+ScriptVars globalVars(NUM_MAX_VAR);
+
+uint16 compareVars(int16 a, int16 b);
+void palRotate(byte a, byte b, byte c);
+void removeSeq(uint16 param1, uint16 param2, uint16 param3);
+uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
+void addGfxElementA0(int16 param1, int16 param2);
+void removeGfxElementA0(int16 idx, int16 param);
+
+const Opcode FWScript::_opcodeTable[] = {
+ /* 00 */
+ { &FWScript::o1_modifyObjectParam, "bbw" },
+ { &FWScript::o1_getObjectParam, "bbb" },
+ { &FWScript::o1_addObjectParam, "bbw" },
+ { &FWScript::o1_subObjectParam, "bbw" },
+ /* 04 */
+ { &FWScript::o1_add2ObjectParam, "bbw" },
+ { &FWScript::o1_sub2ObjectParam, "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 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &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_op1B, "" },
+ /* 1C */
+ { 0, 0 },
+ { &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" },
+ { 0, 0 },
+ /* 28 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 2C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 30 */
+ { 0, 0 },
+ { &FWScript::o1_startGlobalScript, "b" },
+ { &FWScript::o1_endGlobalScript, "b" },
+ { 0, 0 },
+ /* 34 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 38 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_loadAnim, "s" },
+ /* 3C */
+ { &FWScript::o1_loadBg, "s" },
+ { &FWScript::o1_loadCt, "s" },
+ { 0, 0 },
+ { &FWScript::o1_loadPart, "s" },
+ /* 40 */
+ { &FWScript::o1_closePart, "" },
+ { &FWScript::o1_loadNewPrcName, "bs" },
+ { &FWScript::o1_requestCheckPendingDataLoad, "" },
+ { 0, 0 },
+ /* 44 */
+ { 0, 0 },
+ { &FWScript::o1_blitAndFade, "" },
+ { &FWScript::o1_fadeToBlack, "" },
+ { &FWScript::o1_transformPaletteRange, "bbwww" },
+ /* 48 */
+ { 0, 0 },
+ { &FWScript::o1_setDefaultMenuColor2, "b" },
+ { &FWScript::o1_palRotate, "bbb" },
+ { 0, 0 },
+ /* 4C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_break, "" },
+ /* 50 */
+ { &FWScript::o1_endScript, "x" },
+ { &FWScript::o1_message, "bwwww" },
+ { &FWScript::o1_loadGlobalVar, "bc" },
+ { &FWScript::o1_compareGlobalVar, "bc" },
+ /* 54 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 58 */
+ { 0, 0 },
+ { &FWScript::o1_declareFunctionName, "s" },
+ { &FWScript::o1_freePartRange, "bb" },
+ { &FWScript::o1_unloadAllMasks, "" },
+ /* 5C */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ /* 60 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_setScreenDimensions, "wwww" },
+ /* 64 */
+ { &FWScript::o1_displayBackground, "" },
+ { &FWScript::o1_initializeZoneData, "" },
+ { &FWScript::o1_setZoneDataEntry, "bw" },
+ { &FWScript::o1_getZoneDataEntry, "bb" },
+ /* 68 */
+ { &FWScript::o1_setDefaultMenuColor, "b" },
+ { &FWScript::o1_allowPlayerInput, "" },
+ { &FWScript::o1_disallowPlayerInput, "" },
+ { &FWScript::o1_changeDataDisk, "b" },
+ /* 6C */
+ { 0, 0 },
+ { &FWScript::o1_loadMusic, "s" },
+ { &FWScript::o1_playMusic, "" },
+ { &FWScript::o1_fadeOutMusic, "" },
+ /* 70 */
+ { &FWScript::o1_stopSample, "" },
+ { &FWScript::o1_op71, "bw" },
+ { &FWScript::o1_op72, "wbw" },
+ { &FWScript::o1_op73, "wbw" },
+ /* 74 */
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { &FWScript::o1_playSample, "bbwbww" },
+ /* 78 */
+ { &FWScript::o1_playSample, "bbwbww" },
+ { &FWScript::o1_disableSystemMenu, "b" },
+ { &FWScript::o1_loadMask5, "b" },
+ { &FWScript::o1_unloadMask5, "b" }
+};
+const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable);
+
+FWScriptInfo *scriptInfo; ///< Script factory
+RawScriptArray scriptTable; ///< Table of script bytecode
+
+/*! \todo: replace with script subsystem
+ */
+void setupOpcodes() {
+ static FWScriptInfo fw;
+ static OSScriptInfo os;
+ if (g_cine->getGameType() == Cine::GType_FW) {
+ scriptInfo = &fw;
+ } else {
+ scriptInfo = &os;
+ }
+}
+
+/*! \brief Allocate empty array
+ * \param len Size of array
+ *
+ * Explicit to prevent var=0 instead of var[i]=0 typos.
+ */
+ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) {
+ assert(_vars);
+ reset();
+}
+
+/*! \brief Allocate array and read contents from savefile
+ * \param fHandle Savefile open for reading
+ * \param len Size of array
+ */
+ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len)
+ : _size(len), _vars(new int16[len]) {
+
+ assert(_vars);
+
+ load(fHandle);
+}
+
+/*! \brief Copy constructor
+ */
+ScriptVars::ScriptVars(const ScriptVars &src) : _size(src._size), _vars(new int16[_size]) {
+ assert(_vars);
+ memcpy(_vars, src._vars, _size * sizeof(int16));
+}
+
+/*! \brief Destructor
+ */
+ScriptVars::~ScriptVars(void) {
+ delete[] _vars;
+}
+
+/*! \brief Assignment operator
+ */
+ScriptVars &ScriptVars::operator=(const ScriptVars &src) {
+ ScriptVars tmp(src);
+ int16 *tmpvars = _vars;
+
+ _vars = tmp._vars;
+ tmp._vars = tmpvars;
+ _size = src._size;
+
+ return *this;
+}
+
+/*! \brief Direct array item access
+ * \param idx Item index
+ * \return Reference to item
+ */
+int16 &ScriptVars::operator[](unsigned int idx) {
+ debug(6, "assert(%d < %d)", idx, _size);
+ assert(idx < _size);
+ return _vars[idx];
+}
+
+/*! \brief Direct read-only array item access
+ * \param idx Item index
+ * \return Copy of item
+ */
+int16 ScriptVars::operator[](unsigned int idx) const {
+ debug(6, "assert(%d < %d)", idx, _size);
+ assert(idx < _size);
+ return _vars[idx];
+}
+
+/*! \brief Savefile writer
+ * \param fHandle Savefile open for writing
+ */
+void ScriptVars::save(Common::OutSaveFile &fHandle) const {
+ save(fHandle, _size);
+}
+
+/*! \brief Savefile writer with data length limit
+ * \param fHandle Savefile open for writing
+ * \param len Length of data to be written (len <= _size)
+ */
+void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const {
+ debug(6, "assert(%d <= %d)", len, _size);
+ assert(len <= _size);
+ for (unsigned int i = 0; i < len; i++) {
+ fHandle.writeUint16BE(_vars[i]);
+ }
+}
+
+/*! \brief Restore array from savefile
+ * \param fHandle Savefile open for reading
+ */
+void ScriptVars::load(Common::InSaveFile &fHandle) {
+ load(fHandle, _size);
+}
+
+/*! \brief Restore part of array from savefile
+ * \param fHandle Savefile open for reading
+ * \param len Length of data to be read
+ */
+void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) {
+ debug(6, "assert(%d <= %d)", len, _size);
+ assert(len <= _size);
+ for (unsigned int i = 0; i < len; i++) {
+ _vars[i] = fHandle.readUint16BE();
+ }
+}
+
+/*! \brief Reset all values to 0
+ */
+void ScriptVars::reset(void) {
+ memset( _vars, 0, _size * sizeof(int16));
+}
+
+/*! \brief Constructor for partial loading
+ * \param s Size of bytecode which will be added later
+ *
+ * This constructor _MUST_ be followed by setdata() method call before the
+ * instance can be used. It leaves the instance in partially invalid state.
+ */
+RawScript::RawScript(uint16 s) : _size(s), _data(NULL),
+ _labels(SCRIPT_STACK_SIZE) { }
+
+/*! \brief Complete constructor
+ * \param data Script bytecode
+ * \param s Bytecode length
+ */
+RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) :
+ _size(s), _data(NULL), _labels(SCRIPT_STACK_SIZE) {
+
+ setData(info, data);
+}
+
+/*! \brief Copy constructor
+ */
+RawScript::RawScript(const RawScript &src) : _size(src._size),
+ _data(new byte[_size+1]), _labels(src._labels) {
+
+ assert(_data);
+ memcpy(_data, src._data, _size+1);
+}
+
+/*! \brief Destructor
+ */
+RawScript::~RawScript(void) {
+ delete[] _data;
+}
+
+/*! \brief Assignment operator
+ */
+RawScript &RawScript::operator=(const RawScript &src) {
+ assert(src._data);
+ byte *tmp = new byte[src._size+1];
+
+ assert(tmp);
+ _labels = src._labels;
+ _size = src._size;
+
+ delete[] _data;
+ _data = tmp;
+ memcpy(_data, src._data, _size);
+ _data[_size] = 0;
+
+ return *this;
+}
+
+/*! \brief Get the next label in bytecode
+ * \param info Script info instance
+ * \param offset Starting offset
+ * \return Index of the next label in bytecode or _size on end of bytecode
+ *
+ * computeScriptStackSub replacement
+ */
+int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const {
+ assert(_data);
+ int pos = offset;
+
+ assert(pos >= 0);
+
+ while (pos < _size) {
+ uint8 opcode = _data[pos++];
+ const char *ptr = info.opcodeInfo(opcode);
+
+ if (!ptr) {
+ continue;
+ }
+
+ for (; *ptr; ++ptr) {
+ switch (*ptr) {
+ case 'b': // byte
+ pos++;
+ break;
+ case 'w': // word
+ pos += 2;
+ break;
+ case 'c': { // byte != 0 ? byte : word
+ uint8 test = _data[pos];
+ pos++;
+ if (test) {
+ pos++;
+ } else {
+ pos += 2;
+ }
+ }
+ break;
+ case 'l': // label
+ return pos;
+ case 's': // string
+ while (_data[pos++] != 0);
+ break;
+ case 'x': // exit script
+ return -pos-1;
+ }
+ }
+ }
+ return _size;
+}
+
+/*! \brief Calculate initial script labels
+ * \param info Script info instance
+ *
+ * computeScriptStack replacement
+ */
+void RawScript::computeLabels(const FWScriptInfo &info) {
+ assert(_data);
+ int pos = 0;
+ int i;
+
+ // reset labels
+ for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
+ _labels[i] = -1;
+ }
+
+ // parse bytecode
+ while ((pos = getNextLabel(info, pos)) >= 0) {
+ i = _data[pos];
+ _labels[i] = ++pos;
+ }
+}
+
+/*! \brief find the next label from current position
+ * \param info Script info instance
+ * \param index Label index to look for
+ * \param offset Current position in script
+ * \return Position of next instruction following the label
+ *
+ * computeScriptStackFromScript replacement
+ */
+uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
+ const {
+
+ assert(_data);
+ int pos = offset;
+
+ while ((pos = getNextLabel(info, pos)) >= 0) {
+ if (_data[pos++] == index) {
+ return pos;
+ }
+ }
+
+ return -pos - 1;
+}
+
+/*! \brief Copy bytecode and calculate labels
+ * \param data Bytecode to copy, must be _size long
+ */
+void RawScript::setData(const FWScriptInfo &info, const byte *data) {
+ assert(!_data); // this function should be called only once per instance
+ _data = new byte[_size+1];
+
+ assert(data && _data);
+ memcpy(_data, data, _size * sizeof(byte));
+ _data[_size] = 0;
+
+ computeLabels(info);
+}
+
+/*! \brief Initial script labels
+ * \return Precalculated script labels
+ */
+const ScriptVars &RawScript::labels(void) const {
+ assert(_data);
+ return _labels;
+}
+
+/*! \brief One byte of bytecode
+ * \param pos Index in bytecode
+ * \return Byte from bytecode
+ */
+byte RawScript::getByte(unsigned int pos) const {
+ assert(_data && pos < _size);
+
+ return _data[pos];
+}
+
+/*! \brief One word of bytecode
+ * \param pos Index of the first byte in bytecode
+ * \return Word of bytecode
+ */
+uint16 RawScript::getWord(unsigned int pos) const {
+ assert(_data && pos+1 < _size);
+
+ return READ_BE_UINT16(_data + pos);
+}
+
+/*! \brief String in bytecode
+ * \param pos Index of the first char in string
+ * \return Pointer to part of bytecode
+ */
+const char *RawScript::getString(unsigned int pos) const {
+ assert(_data && pos < _size);
+
+ return (const char*)(_data+pos);
+}
+
+/*! \brief Constructor for partial loading
+ * \param size Size of bytecode which will be added later
+ * \param p1 First object script parameter
+ * \param p2 Second object script parameter
+ * \param p3 Third object script parameter
+ *
+ * This constructor _MUST_ be followed by setdata() method call before the
+ * instance can be used. It leaves the instance in partially invalid state.
+ */
+RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
+ : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
+{ }
+
+/*! \brief Complete constructor
+ * \param data Script bytecode
+ * \param s Bytecode length
+ * \param p1 First object script parameter
+ * \param p2 Second object script parameter
+ * \param p3 Third object script parameter
+ */
+RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
+ uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
+ _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
+
+/*! \brief Contructor for global scripts
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
+ _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(new FWScriptInfo) { }
+
+/*! \brief Copy constructor
+ */
+FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
+ _line(src._line), _compare(src._compare), _index(src._index),
+ _labels(src._labels), _localVars(src._localVars),
+ _globalVars(src._globalVars), _info(new FWScriptInfo) { }
+
+/*! \brief Contructor for global scripts in derived classes
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
+ _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(info) { }
+
+/*! \brief Constructor for object scripts in derived classes
+ * \param script Script bytecode reference
+ * \param idx Script bytecode index
+ */
+FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
+ _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+ _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
+ _globalVars(globalVars), _info(info) {
+
+ _localVars[0] = script.run();
+}
+
+/*! \brief Copy constructor for derived classes
+ */
+FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
+ _script(src._script), _pos(src._pos), _line(src._line),
+ _compare(src._compare), _index(src._index), _labels(src._labels),
+ _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
+
+FWScript::~FWScript(void) {
+ delete _info;
+}
+
+/*! \brief Read next byte from bytecode
+ * \return Byte from bytecode
+ */
+byte FWScript::getNextByte() {
+ byte val = _script.getByte(_pos);
+ _pos++;
+ return val;
+}
+
+/*! \brief Read next word from bytecode
+ * \return Word from bytecode
+ */
+uint16 FWScript::getNextWord() {
+ uint16 val = _script.getWord(_pos);
+ _pos += 2;
+ return val;
+}
+
+/*! \brief Read next string from bytecode
+ * \return Pointer to string
+ */
+const char *FWScript::getNextString() {
+ const char *val = _script.getString(_pos);
+ _pos += strlen(val) + 1;
+ return val;
+}
+
+/*! \brief 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 FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
+ assert(pos < _script._size);
+ _labels = labels;
+ _localVars = local;
+ _compare = compare;
+ _pos = _line = pos;
+}
+
+/*! \brief Execute script
+ * \return <0 on script termination, >0 on script pause
+ *
+ * executeScript replacement.
+ * Instruction handler must return 0 if the script should continue or
+ * nonzero with the same meaning as return value of this function
+ */
+int FWScript::execute() {
+ int ret = 0;
+
+ while (!ret) {
+ _line = _pos;
+ byte opcode = getNextByte();
+ opFunc handler = _info->opcodeHandler(opcode);
+
+ if (handler) {
+ ret = (this->*handler)();
+ }
+ }
+
+ return ret;
+}
+
+/*! \brief Save script to savefile
+ * \param fHandle Savefile handle
+ */
+void FWScript::save(Common::OutSaveFile &fHandle) const {
+ _labels.save(fHandle);
+ _localVars.save(fHandle);
+ fHandle.writeUint16BE(_compare);
+ fHandle.writeUint16BE(_pos);
+ // data order sucks...
+ fHandle.writeUint16BE(_index);
+}
+
+/*! \brief Get opcode info string
+ * \param opcode Opcode to look for in opcode table
+ */
+const char *FWScriptInfo::opcodeInfo(byte opcode) const {
+ if (opcode == 0 || opcode > FWScript::_numOpcodes) {
+ return NULL;
+ }
+
+ if (!FWScript::_opcodeTable[opcode - 1].args) {
+ warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1);
+ return NULL;
+ }
+
+ return FWScript::_opcodeTable[opcode - 1].args;
+}
+
+/*! \brief Get opcode handler pointer
+ * \param opcode Opcode to look for in opcode table
+ */
+opFunc FWScriptInfo::opcodeHandler(byte opcode) const {
+ if (opcode == 0 || opcode > FWScript::_numOpcodes) {
+ return NULL;
+ }
+
+ if (!FWScript::_opcodeTable[opcode - 1].proc) {
+ warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1);
+ return NULL;
+ }
+
+ return FWScript::_opcodeTable[opcode - 1].proc;
+}
+
+/*! \brief Create new FWScript instance
+ * \param script Script bytecode
+ * \param index Bytecode index
+ */
+FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const {
+ return new FWScript(script, index);
+}
+
+/*! \brief Create new FWScript instance
+ * \param script Object script bytecode
+ * \param index Bytecode index
+ */
+FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const {
+ return new FWScript(script, index);
+}
+
+/*! \brief Load saved FWScript 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 *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ FWScript *tmp = new FWScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
+}
+
+/*! \brief Load saved FWScript 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 *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
+ FWScript *tmp = new FWScript(script, index);
+ assert(tmp);
+ tmp->load(labels, local, compare, pos);
+ return tmp;
+}
+
+// ------------------------------------------------------------------------
+// FUTURE WARS opcodes
+// ------------------------------------------------------------------------
+
+int FWScript::o1_modifyObjectParam() {
+ byte objIdx = getNextByte();
+ byte paramIdx = getNextByte();
+ int16 newValue = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
+
+ modifyObjectParam(objIdx, paramIdx, newValue);
+ return 0;
+}
+
+int FWScript::o1_getObjectParam() {
+ byte objIdx = getNextByte();
+ byte paramIdx = getNextByte();
+ byte newValue = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue);
+
+ _localVars[newValue] = getObjectParam(objIdx, paramIdx);
+ return 0;
+}
+
+int FWScript::o1_addObjectParam() {
+ byte objIdx = getNextByte();
+ byte paramIdx = getNextByte();
+ int16 newValue = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
+
+ addObjectParam(objIdx, paramIdx, newValue);
+ return 0;
+}
+
+int FWScript::o1_subObjectParam() {
+ byte objIdx = getNextByte();
+ byte paramIdx = getNextByte();
+ int16 newValue = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
+
+ subObjectParam(objIdx, paramIdx, newValue);
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_add2ObjectParam() {
+ uint16 a = getNextByte();
+ uint16 b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c);
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_sub2ObjectParam() {
+ uint16 a = getNextByte();
+ uint16 b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c);
+ return 0;
+}
+
+int FWScript::o1_compareObjectParam() {
+ byte objIdx = getNextByte();
+ byte param1 = getNextByte();
+ int16 param2 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2);
+
+ _compare = compareObjectParam(objIdx, param1, param2);
+ return 0;
+}
+
+int FWScript::o1_setupObject() {
+ byte objIdx = getNextByte();
+ int16 param1 = getNextWord();
+ int16 param2 = getNextWord();
+ int16 param3 = getNextWord();
+ int16 param4 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
+
+ setupObject(objIdx, param1, param2, param3, param4);
+ return 0;
+}
+
+int FWScript::o1_checkCollision() {
+ byte objIdx = getNextByte();
+ int16 param1 = getNextWord();
+ int16 param2 = getNextWord();
+ int16 param3 = getNextWord();
+ int16 param4 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
+
+ _compare = checkCollision(objIdx, param1, param2, param3, param4);
+ return 0;
+}
+
+int FWScript::o1_loadVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+ int16 var;
+
+ switch (varType) {
+ case 1:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] = _localVars[dataIdx];
+ break;
+ case 2:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] = _globalVars[dataIdx];
+ break;
+ case 3:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx);
+ getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16);
+ _localVars[varIdx] = var;
+ break;
+ case 4:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx);
+ getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var);
+ _localVars[varIdx] = var;
+ break;
+ case 5:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx);
+ _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
+ break;
+ case 8:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
+ _localVars[varIdx] = partBuffer[dataIdx].packedSize;
+ break;
+ case 9:
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
+ _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
+ break;
+ default:
+ error("executeScript: o1_loadVar: Unknown variable type %d", varType);
+ }
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value);
+ _localVars[varIdx] = value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_addVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] += _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] += _globalVars[dataIdx];
+ }
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value);
+ _localVars[varIdx] += value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_subVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] -= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] -= _globalVars[dataIdx];
+ }
+
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value);
+ _localVars[varIdx] -= value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_mulVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] *= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] *= _globalVars[dataIdx];
+ }
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value);
+ _localVars[varIdx] *= value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_divVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] /= _localVars[dataIdx];
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx);
+ _localVars[varIdx] /= _globalVars[dataIdx];
+ }
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value);
+ _localVars[varIdx] /= value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_compareVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx);
+ _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]);
+ } else if (varType == 2) {
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx);
+ _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]);
+ }
+ } else {
+ int16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value);
+ _compare = compareVars(_localVars[varIdx], value);
+ }
+
+ return 0;
+}
+
+int FWScript::o1_modifyObjectParam2() {
+ byte objIdx = getNextByte();
+ byte paramIdx = getNextByte();
+ byte newValue = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue);
+
+ modifyObjectParam(objIdx, paramIdx, _localVars[newValue]);
+ return 0;
+}
+
+int FWScript::o1_loadMask0() {
+ // OP_loadV7Element
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
+ addOverlay(param, 0);
+ return 0;
+}
+
+int FWScript::o1_unloadMask0() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
+ removeOverlay(param, 0);
+ return 0;
+ return 0;
+}
+
+int FWScript::o1_addToBgList() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param);
+ addToBGList(param);
+ return 0;
+}
+
+int FWScript::o1_loadMask1() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
+ addOverlay(param, 1);
+ return 0;
+}
+
+int FWScript::o1_unloadMask1() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
+ removeOverlay(param, 1);
+ return 0;
+}
+
+int FWScript::o1_loadMask4() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
+ addOverlay(param, 4);
+ return 0;
+}
+
+int FWScript::o1_unloadMask4() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
+ removeOverlay(param, 4);
+ return 0;
+}
+
+int FWScript::o1_addSpriteFilledToBgList() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param);
+ addSpriteFilledToBGList(param);
+ return 0;
+}
+
+int FWScript::o1_op1B() {
+ debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
+ bgIncrustList.clear();
+ return 0;
+}
+
+int FWScript::o1_label() {
+ byte labelIdx = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx);
+ _labels[labelIdx] = _pos;
+ return 0;
+}
+
+int FWScript::o1_goto() {
+ byte labelIdx = getNextByte();
+
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ return 0;
+}
+
+int FWScript::o1_gotoIfSup() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpGT) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_gotoIfSupEqu() {
+ byte labelIdx = getNextByte();
+
+ if (_compare & (kCmpGT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_gotoIfInf() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpLT) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_gotoIfInfEqu() {
+ byte labelIdx = getNextByte();
+
+ if (_compare & (kCmpLT | kCmpEQ)) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_gotoIfEqu() {
+ byte labelIdx = getNextByte();
+
+ if (_compare == kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_gotoIfDiff() {
+ byte labelIdx = getNextByte();
+
+ if (_compare != kCmpEQ) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_removeLabel() {
+ byte labelIdx = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx);
+ _labels[labelIdx] = -1;
+ return 0;
+}
+
+int FWScript::o1_loop() {
+ byte varIdx = getNextByte();
+ byte labelIdx = getNextByte();
+
+ _localVars[varIdx]--;
+
+ if (_localVars[varIdx] >= 0) {
+ assert(_labels[labelIdx] != -1);
+
+ debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx);
+ _pos = _labels[labelIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx);
+ }
+ return 0;
+}
+
+int FWScript::o1_startGlobalScript() {
+ // OP_startScript
+ byte param = getNextByte();
+
+ assert(param < NUM_MAX_SCRIPT);
+
+ debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param);
+ addScriptToList0(param);
+ return 0;
+}
+
+int FWScript::o1_endGlobalScript() {
+ byte scriptIdx = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
+
+ ScriptList::iterator it = globalScripts.begin();
+
+ for (; it != globalScripts.end(); ++it) {
+ if ((*it)->_index == scriptIdx) {
+ (*it)->_index = -1;
+ }
+ }
+
+ return 0;
+}
+
+int FWScript::o1_loadAnim() {
+ // OP_loadResource
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param);
+ loadResource(param);
+ return 0;
+}
+
+int FWScript::o1_loadBg() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
+
+ loadBg(param);
+ bgIncrustList.clear();
+ bgVar0 = 0;
+ return 0;
+}
+
+int FWScript::o1_loadCt() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
+ loadCt(param);
+ return 0;
+}
+
+int FWScript::o1_loadPart() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
+ loadPart(param);
+ return 0;
+}
+
+int FWScript::o1_closePart() {
+ debugC(5, kCineDebugScript, "Line: %d: closePart", _line);
+ closePart();
+ return 0;
+}
+
+int FWScript::o1_loadNewPrcName() {
+ // OP_loadData
+ byte param1 = getNextByte();
+ const char *param2 = getNextString();
+
+ assert(param1 <= 3);
+
+ switch (param1) {
+ case 0:
+ debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2);
+ strcpy(newPrcName, param2);
+ break;
+ case 1:
+ debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2);
+ strcpy(newRelName, param2);
+ break;
+ case 2:
+ debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2);
+ strcpy(newObjectName, param2);
+ break;
+ case 3:
+ debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2);
+ strcpy(newMsgName, param2);
+ break;
+ }
+ return 0;
+}
+
+int FWScript::o1_requestCheckPendingDataLoad() {
+ debugC(5, kCineDebugScript, "Line: %d: request data load", _line);
+ checkForPendingDataLoadSwitch = 1;
+ return 0;
+}
+
+int FWScript::o1_blitAndFade() {
+ debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
+ // TODO: use real code
+
+ drawOverlays();
+ fadeRequired = true;
+ flip();
+
+// fadeFromBlack();
+ return 0;
+}
+
+int FWScript::o1_fadeToBlack() {
+ debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
+
+ fadeToBlack();
+ return 0;
+}
+
+int FWScript::o1_transformPaletteRange() {
+ byte startColor = getNextByte();
+ byte numColor = getNextByte();
+ uint16 r = getNextWord();
+ uint16 g = getNextWord();
+ uint16 b = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
+
+ transformPaletteRange(startColor, numColor, r, g, b);
+ return 0;
+}
+
+int FWScript::o1_setDefaultMenuColor2() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
+ defaultMenuBoxColor2 = param;
+ return 0;
+}
+
+int FWScript::o1_palRotate() {
+ byte a = getNextByte();
+ byte b = getNextByte();
+ byte c = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
+ palRotate(a, b, c);
+ return 0;
+}
+
+/*!\brief Pause script
+ * \todo Make sure it works
+ */
+int FWScript::o1_break() {
+ debugC(5, kCineDebugScript, "Line: %d: break", _line);
+
+ return 1;
+}
+
+/*! \brief Terminate script
+ * \todo Make sure it works
+ */
+int FWScript::o1_endScript() {
+ debugC(5, kCineDebugScript, "Line: %d: endScript", _line);
+
+ return -1;
+}
+
+int FWScript::o1_message() {
+ byte param1 = getNextByte();
+ uint16 param2 = getNextWord();
+ uint16 param3 = getNextWord();
+ uint16 param4 = getNextWord();
+ uint16 param5 = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5);
+
+ addMessage(param1, param2, param3, param4, param5);
+ return 0;
+}
+
+int FWScript::o1_loadGlobalVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte dataIdx = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx);
+ _globalVars[varIdx] = _localVars[dataIdx];
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx);
+ _globalVars[varIdx] = _globalVars[dataIdx];
+ }
+ } else {
+ uint16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value);
+ _globalVars[varIdx] = value;
+ }
+
+ return 0;
+}
+
+int FWScript::o1_compareGlobalVar() {
+ byte varIdx = getNextByte();
+ byte varType = getNextByte();
+
+ if (varType) {
+ byte value = getNextByte();
+
+ if (varType == 1) {
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value);
+ _compare = compareVars(_globalVars[varIdx], _localVars[value]);
+ } else {
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and globalVars[%d]", _line, varIdx, value);
+ _compare = compareVars(_globalVars[varIdx], _globalVars[value]);
+ }
+ } else {
+ uint16 value = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
+
+ if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix
+ _compare = 1;
+ } else {
+ _compare = compareVars(_globalVars[varIdx], value);
+ }
+ }
+
+ return 0;
+}
+
+int FWScript::o1_declareFunctionName() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param);
+ return 0;
+}
+
+int FWScript::o1_freePartRange() {
+ byte startIdx = getNextByte();
+ byte numIdx = getNextByte();
+
+ assert(startIdx + numIdx <= NUM_MAX_ANIMDATA);
+
+ debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx);
+ freeAnimDataRange(startIdx, numIdx);
+ return 0;
+}
+
+int FWScript::o1_unloadAllMasks() {
+ debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
+ overlayList.clear();
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_setScreenDimensions() {
+ uint16 a = getNextWord();
+ uint16 b = getNextWord();
+ uint16 c = getNextWord();
+ uint16 d = getNextWord();
+ warning("STUB: o1_setScreenDimensions(%x, %x, %x, %x)", a, b, c, d);
+ // setupScreenParam
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_displayBackground() {
+ warning("STUB: o1_displayBackground()");
+ return 0;
+}
+
+int FWScript::o1_initializeZoneData() {
+ debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
+
+ for (int i = 0; i < NUM_MAX_ZONE; i++) {
+ zoneData[i] = i;
+ }
+ return 0;
+}
+
+int FWScript::o1_setZoneDataEntry() {
+ byte zoneIdx = getNextByte();
+ uint16 var = getNextWord();
+
+ debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
+ zoneData[zoneIdx] = var;
+ return 0;
+}
+
+int FWScript::o1_getZoneDataEntry() {
+ byte zoneIdx = getNextByte();
+ byte var = getNextByte();
+
+ _localVars[var] = zoneData[zoneIdx];
+ return 0;
+}
+
+int FWScript::o1_setDefaultMenuColor() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
+ defaultMenuBoxColor = param;
+ return 0;
+}
+
+int FWScript::o1_allowPlayerInput() {
+ debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line);
+ allowPlayerInput = 1;
+ return 0;
+}
+
+int FWScript::o1_disallowPlayerInput() {
+ debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line);
+ allowPlayerInput = 0;
+ return 0;
+}
+
+int FWScript::o1_changeDataDisk() {
+ byte newDisk = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk);
+ checkDataDisk(newDisk);
+ return 0;
+}
+
+int FWScript::o1_loadMusic() {
+ const char *param = getNextString();
+
+ debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param);
+ g_sound->loadMusic(param);
+ return 0;
+}
+
+int FWScript::o1_playMusic() {
+ debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line);
+ g_sound->playMusic();
+ return 0;
+}
+
+int FWScript::o1_fadeOutMusic() {
+ debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line);
+ g_sound->fadeOutMusic();
+ return 0;
+}
+
+int FWScript::o1_stopSample() {
+ debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line);
+ g_sound->stopMusic();
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op71() {
+ byte a = getNextByte();
+ uint16 b = getNextWord();
+ warning("STUB: o1_op71(%x, %x)", a, b);
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op72() {
+ uint16 a = getNextWord();
+ byte b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
+ return 0;
+}
+
+/*! \todo Implement this instruction
+ */
+int FWScript::o1_op73() {
+ // I believe this opcode is identical to o1_op72(). In fact, Operation
+ // Stealth doesn't even have it. It uses o1_op72() instead.
+ uint16 a = getNextWord();
+ byte b = getNextByte();
+ uint16 c = getNextWord();
+ warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
+ return 0;
+}
+
+int FWScript::o1_playSample() {
+ debugC(5, kCineDebugScript, "Line: %d: playSample()", _line);
+
+ byte anim = getNextByte();
+ byte channel = getNextByte();
+
+ uint16 freq = getNextWord();
+ byte repeat = getNextByte();
+
+ int16 volume = getNextWord();
+ uint16 size = getNextWord();
+
+ const byte *data = animDataTable[anim].data();
+
+ if (!data) {
+ return 0;
+ }
+
+ if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
+ if (size == 0xFFFF) {
+ size = animDataTable[anim]._width * animDataTable[anim]._height;
+ }
+ if (channel < 10) { // || _currentOpcode == 0x78
+ int channel1, channel2;
+ if (channel == 0) {
+ channel1 = 0;
+ channel2 = 1;
+ } else {
+ channel1 = 2;
+ channel2 = 3;
+ }
+ g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
+ g_sound->playSound(channel2, freq, data, size, 1, volume, 0, repeat);
+ } else {
+ channel -= 10;
+ if (volume > 63) {
+ volume = 63;
+ }
+ g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat);
+ }
+ } else {
+ if (volume > 63 || volume < 0) {
+ volume = 63;
+ }
+ if (channel >= 10) {
+ channel -= 10;
+ }
+ if (volume < 50) {
+ volume = 50;
+ }
+ if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
+ return 0;
+ }
+ g_sound->stopMusic();
+ if (size == 0xFFFF) {
+ g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0);
+ } else {
+ g_sound->stopSound(channel);
+ }
+ }
+ return 0;
+}
+
+int FWScript::o1_disableSystemMenu() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
+ disableSystemMenu = (param != 0);
+ return 0;
+}
+
+int FWScript::o1_loadMask5() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
+ addOverlay(param, 5);
+ return 0;
+}
+
+int FWScript::o1_unloadMask5() {
+ byte param = getNextByte();
+
+ debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
+ removeOverlay(param, 5);
+ return 0;
+}
+
+//-----------------------------------------------------------------------
+
+void palRotate(byte a, byte b, byte c) {
+ if (c == 1) {
+ uint16 currentColor = c_palette[b];
+
+ for (int16 i = b; i > a; i--) {
+ c_palette[i] = c_palette[i - 1];
+ }
+
+ c_palette[a] = currentColor;
+ }
+}
+
+void addScriptToList0(uint16 idx) {
+ ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
+ assert(tmp);
+ globalScripts.push_back(tmp);
+}
+
+int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
+ byte *ptr = page + (y * width) + x / 2;
+ byte zoneVar;
+
+ if (!(x % 2)) {
+ zoneVar = (*(ptr) >> 4) & 0xF;
+ } else {
+ zoneVar = (*(ptr)) & 0xF;
+ }
+
+ return zoneVar;
+}
+
+int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
+ byte *ptr = page + (y * width) + x;
+ byte zoneVar;
+
+ zoneVar = (*(ptr)) & 0xF;
+
+ return zoneVar;
+}
+
+int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
+ int16 lx = objectTable[objIdx].x + x;
+ int16 ly = objectTable[objIdx].y + y;
+ int16 idx;
+
+ for (int16 i = 0; i < numZones; i++) {
+ idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
+
+ assert(idx >= 0 && idx <= NUM_MAX_ZONE);
+
+ if (zoneData[idx] == zoneIdx) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+uint16 compareVars(int16 a, int16 b) {
+ uint16 flag = 0;
+
+ if (a == b) {
+ flag |= kCmpEQ;
+ } else if (a > b) {
+ flag |= kCmpGT;
+ } else if (a < b) {
+ flag |= kCmpLT;
+ }
+
+ return flag;
+}
+
+void executeList1(void) {
+ ScriptList::iterator it = objectScripts.begin();
+ for (; it != objectScripts.end();) {
+ if ((*it)->_index < 0 || (*it)->execute() < 0) {
+ it = objectScripts.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void executeList0(void) {
+ ScriptList::iterator it = globalScripts.begin();
+ for (; it != globalScripts.end();) {
+ if ((*it)->_index < 0 || (*it)->execute() < 0) {
+ it = globalScripts.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+/*! \todo objectScripts.clear()?
+ */
+void purgeList1(void) {
+}
+
+void purgeList0(void) {
+}
+
+////////////////////////////////////
+// SCRIPT DECOMPILER
+
+#ifdef DUMP_SCRIPTS
+
+char decompileBuffer[10000][1000];
+uint16 decompileBufferPosition = 0;
+
+char bufferDec[256];
+
+char compareString1[256];
+char compareString2[256];
+
+const char *getObjPramName(byte paramIdx) {
+ switch (paramIdx) {
+ case 1:
+ return ".X";
+ case 2:
+ return ".Y";
+ case 3:
+ return ".mask";
+ case 4:
+ return ".frame";
+ case 5:
+ return ".status";
+ case 6:
+ return ".costume";
+ default:
+ sprintf(bufferDec, ".param%d", paramIdx);
+ return bufferDec;
+ }
+}
+
+void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx) {
+ char lineBuffer[256];
+ byte *localScriptPtr = scriptPtr;
+ uint16 exitScript;
+ uint32 position = 0;
+
+ assert(scriptPtr);
+ // assert(stackPtr);
+
+ exitScript = 0;
+
+ sprintf(decompileBuffer[decompileBufferPosition++], "--------- SCRIPT %d ---------\n", scriptIdx);
+
+ do {
+ uint16 opcode = *(localScriptPtr + position);
+ position++;
+
+ if (position == scriptSize) {
+ opcode = 0;
+ }
+
+ strcpy(lineBuffer, "");
+
+ switch (opcode - 1) {
+ case -1:
+ {
+ break;
+ }
+ case 0x0:
+ {
+ byte param1;
+ byte param2;
+ int16 param3;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "obj[%d]%s = %d\n", param1, getObjPramName(param2), param3);
+
+ break;
+ }
+ case 0x1:
+ {
+ byte param1;
+ byte param2;
+ byte param3;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "var[%d]=obj[%d]%s\n", param3, param1, getObjPramName(param2));
+ break;
+ }
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ {
+ byte param1;
+ byte param2;
+ int16 param3;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x2) {
+ sprintf(lineBuffer, "obj[%d]%s+=%d\n", param1, getObjPramName(param2), param3);
+ } else if (opcode - 1 == 0x3) {
+ sprintf(lineBuffer, "obj[%d]%s-=%d\n", param1, getObjPramName(param2), param3);
+ } else if (opcode - 1 == 0x4) {
+ sprintf(lineBuffer, "obj[%d]%s+=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
+ } else if (opcode - 1 == 0x5) {
+ sprintf(lineBuffer, "obj[%d]%s-=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
+ } else if (opcode - 1 == 0x6) {
+ sprintf(compareString1, "obj[%d]%s", param1, getObjPramName(param2));
+ sprintf(compareString2, "%d", param3);
+ }
+ break;
+ }
+ case 0x7:
+ case 0x8:
+ {
+ byte param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x7) {
+ sprintf(lineBuffer, "setupObject(Idx:%d,X:%d,Y:%d,mask:%d,frame:%d)\n", param1, param2, param3, param4, param5);
+ } else if (opcode - 1 == 0x8) {
+ sprintf(lineBuffer, "checkCollision(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+ }
+ break;
+ }
+ case 0x9:
+ {
+ byte param1;
+ int16 param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ if (param2) {
+ byte param3;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ if (param2 == 1) {
+ sprintf(lineBuffer, "var[%d]=var[%d]\n", param1, param3);
+ } else if (param2 == 2) {
+ sprintf(lineBuffer, "var[%d]=globalVar[%d]\n", param1, param3);
+ } else if (param2 == 3) {
+ sprintf(lineBuffer, "var[%d]=mouse.X\n", param1);
+ } else if (param2 == 4) {
+ sprintf(lineBuffer, "var[%d]=mouse.Y\n", param1);
+ } else if (param2 == 5) {
+ sprintf(lineBuffer, "var[%d]=rand() mod %d\n", param1, param3);
+ } else if (param2 == 8) {
+ sprintf(lineBuffer, "var[%d]=file[%d].packedSize\n", param1, param3);
+ } else if (param2 == 9) {
+ sprintf(lineBuffer, "var[%d]=file[%d].unpackedSize\n", param1, param3);
+ } else {
+ error("decompileScript: 0x09: param2 = %d", param2);
+ }
+ } else {
+ int16 param3;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "var[%d]=%d\n", param1, param3);
+ }
+
+ break;
+ }
+ case 0xA:
+ case 0xB:
+ case 0xC:
+ case 0xD:
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ if (param2) {
+ byte param3;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0xA) {
+ sprintf(lineBuffer, "var[%d]+=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xB) {
+ sprintf(lineBuffer, "var[%d]-=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xC) {
+ sprintf(lineBuffer, "var[%d]*=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xD) {
+ sprintf(lineBuffer, "var[%d]/=var[%d]\n", param1, param3);
+ }
+ } else {
+ int16 param3;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0xA) {
+ sprintf(lineBuffer, "var[%d]+=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xB) {
+ sprintf(lineBuffer, "var[%d]-=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xC) {
+ sprintf(lineBuffer, "var[%d]*=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xD) {
+ sprintf(lineBuffer, "var[%d]/=%d\n", param1, param3);
+ }
+ }
+ break;
+ }
+ case 0xE:
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ if (param2) {
+ byte param3;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ if (param2 == 1) {
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "var[%d]", param3);
+
+ } else if (param2 == 2) {
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "globalVar[%d]", param3);
+ } else {
+ error("decompileScript: 0x0E: param2 = %d", param2);
+ }
+ } else {
+ int16 param3;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "%d", param3);
+ }
+ break;
+ }
+ case 0xF:
+ {
+ byte param1;
+ byte param2;
+ byte param3;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "obj[%d]%s=var[%d]\n", param1, getObjPramName(param2), param3);
+
+ break;
+ }
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0x13) {
+ sprintf(lineBuffer, "loadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x14) {
+ sprintf(lineBuffer, "unloadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x15) {
+ sprintf(lineBuffer, "OP_15(%d)\n", param);
+ } else if (opcode - 1 == 0x16) {
+ sprintf(lineBuffer, "loadMask1(%d)\n", param);
+ } else if (opcode - 1 == 0x17) {
+ sprintf(lineBuffer, "unloadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x18) {
+ sprintf(lineBuffer, "loadMask4(%d)\n", param);
+ } else if (opcode - 1 == 0x19) {
+ sprintf(lineBuffer, "unloadMask4(%d)\n", param);
+ }
+ break;
+ }
+ case 0x1A:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_1A(%d)\n", param);
+
+ break;
+ }
+ case 0x1B:
+ {
+ sprintf(lineBuffer, "bgIncrustList.clear()\n");
+ break;
+ }
+ case 0x1D:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "label(%d)\n", param);
+
+ break;
+ }
+ case 0x1E:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "goto(%d)\n", param);
+
+ break;
+ }
+ // If cases
+ case 0x1F:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0x1F) {
+ sprintf(lineBuffer, "if(%s>%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x20) {
+ sprintf(lineBuffer, "if(%s>=%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x21) {
+ sprintf(lineBuffer, "if(%s<%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x22) {
+ sprintf(lineBuffer, "if(%s<=%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x23) {
+ sprintf(lineBuffer, "if(%s==%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x24) {
+ sprintf(lineBuffer, "if(%s!=%s) goto(%d)\n", compareString1, compareString2, param);
+ }
+ break;
+ }
+ case 0x25:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "removeLabel(%d)\n", param);
+
+ break;
+ }
+ case 0x26:
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "loop(--var[%d]) -> label(%d)\n", param1, param2);
+
+ break;
+ }
+ case 0x31:
+ case 0x32:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0x31) {
+ sprintf(lineBuffer, "startGlobalScript(%d)\n", param);
+ } else if (opcode - 1 == 0x32) {
+ sprintf(lineBuffer, "endGlobalScript(%d)\n", param);
+ }
+ break;
+ }
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case OP_loadPart:
+ {
+ if (opcode - 1 == 0x3B) {
+ sprintf(lineBuffer, "loadResource(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == 0x3C) {
+ sprintf(lineBuffer, "loadBg(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == 0x3D) {
+ sprintf(lineBuffer, "loadCt(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == OP_loadPart) {
+ sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position);
+ }
+
+ position += strlen((char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case 0x40:
+ {
+ sprintf(lineBuffer, "closePart()\n");
+ break;
+ }
+ case OP_loadNewPrcName:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position);
+
+ position += strlen((char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case OP_requestCheckPendingDataLoad: // nop
+ {
+ sprintf(lineBuffer, "requestCheckPendingDataLoad()\n");
+ break;
+ }
+ case 0x45:
+ {
+ sprintf(lineBuffer, "blitAndFade()\n");
+ break;
+ }
+ case 0x46:
+ {
+ sprintf(lineBuffer, "fadeToBlack()\n");
+ break;
+ }
+ case 0x47:
+ {
+ byte param1;
+ byte param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "transformPaletteRange(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+
+ break;
+ }
+ case 0x49:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "setDefaultMenuColor2(%d)\n", param);
+
+ break;
+ }
+ case 0x4F:
+ {
+ sprintf(lineBuffer, "break()\n");
+ exitScript = 1;
+ break;
+ }
+ case 0x50:
+ {
+ sprintf(lineBuffer, "endScript()\n\n");
+ break;
+ }
+ case 0x51:
+ {
+ byte param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "message(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+
+ break;
+ }
+ case 0x52:
+ case 0x53:
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ if (param2) {
+ byte param3;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ if (param2 == 1) {
+ if (opcode - 1 == 0x52) {
+ sprintf(lineBuffer, "globalVar[%d] = var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0x53) {
+ sprintf(compareString1, "globalVar[%d]", param1);
+ sprintf(compareString2, "var[%d]", param3);
+ }
+ } else if (param2 == 2) {
+ if (opcode - 1 == 0x52) {
+ sprintf(lineBuffer, "globalVar[%d] = globalVar[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0x53) {
+ sprintf(compareString1, "globalVar[%d]", param1);
+ sprintf(compareString2, "globalVar[%d]", param3);
+ }
+ } else {
+ if (opcode - 1 == 0x52) {
+ error("decompileScript: 0x52: param2 = %d", param2);
+ } else if (opcode - 1 == 0x53) {
+ error("decompileScript: 0x53: param2 = %d", param2);
+ }
+ }
+ } else {
+ int16 param3;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x52) {
+ sprintf(lineBuffer, "globalVar[%d] = %d\n", param1, param3);
+ } else if (opcode - 1 == 0x53) {
+ sprintf(compareString1, "globalVar[%d]", param1);
+ sprintf(compareString2, "%d", param3);
+ }
+ }
+ break;
+ }
+ case 0x59:
+ {
+ sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position);
+
+ position += strlen((char *)localScriptPtr + position);
+ break;
+ }
+ case 0x5A:
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "freePartRang(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ case 0x5B:
+ {
+ sprintf(lineBuffer, "unloadAllMasks()\n");
+ break;
+ }
+ case 0x65:
+ {
+ sprintf(lineBuffer, "setupTableUnk1()\n");
+ break;
+ }
+ case 0x66:
+ {
+ byte param1;
+ int16 param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "tableUnk1[%d] = %d\n", param1, param2);
+
+ break;
+ }
+ case 0x68:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "setDefaultMenuBoxColor(%d)\n", param);
+
+ break;
+ }
+ case 0x69:
+ {
+ sprintf(lineBuffer, "allowPlayerInput()\n");
+ break;
+ }
+ case 0x6A:
+ {
+ sprintf(lineBuffer, "disallowPlayerInput()\n");
+ break;
+ }
+ case 0x6B:
+ {
+ byte newDisk;
+
+ newDisk = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "changeDataDisk(%d)\n", newDisk);
+
+ break;
+ }
+ case 0x6D:
+ {
+ sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position);
+
+ position += strlen((char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case 0x6E: // nop
+ {
+ sprintf(lineBuffer, "updateDat()\n");
+ break;
+ }
+ case 0x6F:
+ {
+ sprintf(lineBuffer, "OP_6F() -> dat related\n");
+ break;
+ }
+ case 0x70:
+ {
+ sprintf(lineBuffer, "stopSample()\n");
+ break;
+ }
+ case 0x79:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "disableSystemMenu(%d)\n", param);
+
+ break;
+ }
+ case 0x77:
+ case 0x78:
+ {
+ byte param1;
+ byte param2;
+ int16 param3;
+ byte param4;
+ int16 param5;
+ int16 param6;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = *(localScriptPtr + position);
+ position++;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x77) {
+ sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
+ } else if (opcode - 1 == 0x78) {
+ sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
+ }
+
+ break;
+ }
+ case 0x7A:
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_7A(%d)\n", param);
+
+ break;
+ }
+ case 0x7B: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_7B(%d)\n", param);
+
+ break;
+ }
+ case 0x7F: // OS only
+ {
+ byte param1;
+ byte param2;
+ byte param3;
+ byte param4;
+ int16 param5;
+ int16 param6;
+ int16 param7;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = *(localScriptPtr + position);
+ position++;
+
+ param4 = *(localScriptPtr + position);
+ position++;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param7 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "OP_7F(%d,%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6, param7);
+
+ break;
+ }
+ case 0x80: // OS only
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_80(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ case 0x82: // OS only
+ {
+ byte param1;
+ byte param2;
+ uint16 param3;
+ uint16 param4;
+ byte param5;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param5 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_82(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+
+ break;
+ }
+ case 0x83: // OS only
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_83(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ case 0x89: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "if(%s!=%s) goto next label(%d)\n", compareString1, compareString2, param);
+
+ break;
+ }
+ case 0x8B: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_8B(%d)\n", param);
+
+ break;
+ }
+ case 0x8C: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_8C(%d)\n", param);
+
+ break;
+ }
+ case 0x8D: // OS only
+ {
+ int16 param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
+ int16 param6;
+ int16 param7;
+ int16 param8;
+
+ param1 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param7 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ param8 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(compareString1, "obj[%d]", param1);
+ sprintf(compareString2, "{%d,%d,%d,%d,%d,%d,%d}", param2, param3, param4, param5, param6, param7, param8);
+
+ break;
+ }
+ case 0x8E: // OS only
+ {
+ byte param1;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position);
+
+ position += strlen((char *)localScriptPtr + position);
+
+ break;
+ }
+ case 0x8F: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_8F(%d)\n", param);
+
+ break;
+ }
+ case 0x90: // OS only
+ {
+ byte param1;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position);
+
+ position += strlen((char *)localScriptPtr + position);
+
+ break;
+ }
+ case 0x91: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_91(%d)\n", param);
+
+ break;
+ }
+ case 0x9D: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_9D(%d) -> flip img idx\n", param);
+
+ break;
+ }
+ case 0x9E: // OS only
+ {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (param) {
+ byte param2;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
+ } else {
+ int16 param2;
+
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
+ }
+
+ break;
+ }
+ case 0xA0: // OS only
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_A0(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ case 0xA1: // OS only
+ {
+ byte param1;
+ byte param2;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ sprintf(lineBuffer, "OP_A1(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ default:
+ {
+ sprintf(lineBuffer, "Unsupported opcode %X in decompileScript\n\n", opcode - 1);
+ position = scriptSize;
+ break;
+ }
+ }
+
+ // printf(lineBuffer);
+ strcpy(decompileBuffer[decompileBufferPosition++], lineBuffer);
+
+ exitScript = 0;
+ if (position >= scriptSize) {
+ exitScript = 1;
+ }
+
+ } while (!exitScript);
+}
+
+void dumpScript(char *dumpName) {
+ Common::File fHandle;
+ uint16 i;
+
+ fHandle.open(dumpName, Common::File::kFileWriteMode);
+
+ for (i = 0; i < decompileBufferPosition; i++) {
+ fHandle.writeString(Common::String(decompileBuffer[i]));
+ }
+
+ fHandle.close();
+
+ decompileBufferPosition = 0;
+}
+
+#endif
+
+} // End of namespace Cine