diff options
Diffstat (limited to 'engines/cine/script.cpp')
-rw-r--r-- | engines/cine/script.cpp | 2739 |
1 files changed, 1651 insertions, 1088 deletions
diff --git a/engines/cine/script.cpp b/engines/cine/script.cpp index c1bfee317a..8ccd0ce3a1 100644 --- a/engines/cine/script.cpp +++ b/engines/cine/script.cpp @@ -23,6 +23,9 @@ * */ +/*! \file + * Script interpreter file + */ #include "common/endian.h" @@ -31,435 +34,423 @@ #include "cine/object.h" #include "cine/sound.h" #include "cine/various.h" +#include "cine/script.h" namespace Cine { -prcLinkedListStruct *_currentScriptElement; -byte *_currentScriptPtr; -uint16 _currentScriptParams; -uint16 _currentPosition; -uint16 _currentLine; -uint16 _closeScript; - -struct Opcode { - void (*proc)(); - const char *args; +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); + + +const Opcode OSScript::_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::o2_loadPart, "s" }, + /* 40 */ + { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */ + { &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_op72, "wbw" }, + /* 74 */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_playSample, "bbwbww" }, + /* 78 */ + { &FWScript::o2_playSampleAlt, "bbwbww" }, + { &FWScript::o1_disableSystemMenu, "b" }, + { &FWScript::o1_loadMask5, "b" }, + { &FWScript::o1_unloadMask5, "b" }, + /* 7C */ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_addSeqListElement, "bbbbwww" }, + /* 80 */ + { &FWScript::o2_removeSeq, "bb" }, + { &FWScript::o2_op81, "" }, + { &FWScript::o2_op82, "bbw" }, + { &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" }, + { 0, 0 }, + { &FWScript::o2_startObjectScript, "b" }, + /* 8C */ + { &FWScript::o2_stopObjectScript, "b" }, + { &FWScript::o2_op8D, "wwwwwwww" }, + { &FWScript::o2_addBackground, "bs" }, + { &FWScript::o2_removeBackground, "b" }, + /* 90 */ + { &FWScript::o2_loadAbs, "bs" }, + { &FWScript::o2_loadBg, "b" }, + { 0, 0 }, + { 0, 0 }, + /* 94 */ + { 0, 0 }, + { &FWScript::o1_changeDataDisk, "b" }, + { 0, 0 }, + { 0, 0 }, + /* 98 */ + { 0, 0 }, + { 0, 0 }, + { &FWScript::o2_wasZoneChecked, "" }, + { &FWScript::o2_op9B, "wwwwwwww" }, + /* 9C */ + { &FWScript::o2_op9C, "wwww" }, + { &FWScript::o2_useBgScroll, "b" }, + { &FWScript::o2_setAdditionalBgVScroll, "c" }, + { &FWScript::o2_op9F, "ww" }, + /* A0 */ + { &FWScript::o2_addGfxElementA0, "ww" }, + { &FWScript::o2_removeGfxElementA0, "ww" }, + { &FWScript::o2_opA2, "ww" }, + { &FWScript::o2_opA3, "ww" }, + /* A4 */ + { &FWScript::o2_loadMask22, "b" }, + { &FWScript::o2_unloadMask22, "b" }, + { 0, 0 }, + { 0, 0 }, + /* A8 */ + { 0, 0 }, + { &FWScript::o1_changeDataDisk, "b" } }; +const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable); -const Opcode *_opcodeTable; -int _numOpcodes; +FWScriptInfo *scriptInfo; ///< Script factory +RawScriptArray scriptTable; ///< Table of script bytecode +/*! \todo: replace with script subsystem + */ void setupOpcodes() { - static const Opcode opcodeTableFW[] = { - /* 00 */ - { o1_modifyObjectParam, "bbw" }, - { o1_getObjectParam, "bbb" }, - { o1_addObjectParam, "bbw" }, - { o1_subObjectParam, "bbw" }, - /* 04 */ - { o1_add2ObjectParam, "bbw" }, - { o1_sub2ObjectParam, "bbw" }, - { o1_compareObjectParam, "bbw" }, - { o1_setupObject, "bwwww" }, - /* 08 */ - { o1_checkCollision, "bwwww" }, - { o1_loadVar, "bc" }, - { o1_addVar, "bc" }, - { o1_subVar, "bc" }, - /* 0C */ - { o1_mulVar, "bc" }, - { o1_divVar, "bc" }, - { o1_compareVar, "bc" }, - { o1_modifyObjectParam2, "bbb" }, - /* 10 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadMask0, "b" }, - /* 14 */ - { o1_unloadMask0, "b" }, - { o1_addToBgList, "b" }, - { o1_loadMask1, "b" }, - { o1_unloadMask1, "b" }, - /* 18 */ - { o1_loadMask4, "b" }, - { o1_unloadMask4, "b" }, - { o1_addSpriteFilledToBgList, "b" }, - { o1_op1B, "" }, - /* 1C */ - { 0, 0 }, - { o1_label, "l" }, - { o1_goto, "b" }, - { o1_gotoIfSup, "b" }, - /* 20 */ - { o1_gotoIfSupEqu, "b" }, - { o1_gotoIfInf, "b" }, - { o1_gotoIfInfEqu, "b" }, - { o1_gotoIfEqu, "b" }, - /* 24 */ - { o1_gotoIfDiff, "b" }, - { o1_removeLabel, "b" }, - { 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 }, - { o1_startGlobalScript, "b" }, - { o1_endGlobalScript, "b" }, - { 0, 0 }, - /* 34 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 38 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadAnim, "s" }, - /* 3C */ - { o1_loadBg, "s" }, - { o1_loadCt, "s" }, - { 0, 0 }, - { o1_loadPart, "s" }, - /* 40 */ - { o1_closePart, "" }, - { o1_loadNewPrcName, "bs" }, - { o1_requestCheckPendingDataLoad, "" }, - { 0, 0 }, - /* 44 */ - { 0, 0 }, - { o1_blitAndFade, "" }, - { o1_fadeToBlack, "" }, - { o1_transformPaletteRange, "bbwww" }, - /* 48 */ - { 0, 0 }, - { o1_setDefaultMenuColor2, "b" }, - { o1_palRotate, "bbb" }, - { 0, 0 }, - /* 4C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_break, "" }, - /* 50 */ - { o1_endScript, "x" }, - { o1_message, "bwwww" }, - { o1_loadGlobalVar, "bc" }, - { o1_compareGlobalVar, "bc" }, - /* 54 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 58 */ - { 0, 0 }, - { o1_declareFunctionName, "s" }, - { o1_freePartRange, "bb" }, - { o1_unloadAllMasks, "" }, - // 5C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 60 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_setScreenDimensions, "wwww" }, - /* 64 */ - { o1_displayBackground, "" }, - { o1_initializeZoneData, "" }, - { o1_setZoneDataEntry, "bw" }, - { o1_getZoneDataEntry, "bb" }, - /* 68 */ - { o1_setDefaultMenuColor, "b" }, - { o1_allowPlayerInput, "" }, - { o1_disallowPlayerInput, "" }, - { o1_changeDataDisk, "b" }, - /* 6C */ - { 0, 0 }, - { o1_loadMusic, "s" }, - { o1_playMusic, "" }, - { o1_fadeOutMusic, "" }, - /* 70 */ - { o1_stopSample, "" }, - { o1_op71, "bw" }, - { o1_op72, "wbw" }, - { o1_op73, "wbw" }, - /* 74 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_playSample, "bbwbww" }, - /* 78 */ - { o1_playSample, "bbwbww" }, - { o1_disableSystemMenu, "b" }, - { o1_loadMask5, "b" }, - { o1_unloadMask5, "b" } - }; - - // TODO: We need to verify the Operation Stealth opcodes. - - static const Opcode opcodeTableOS[] = { - /* 00 */ - { o1_modifyObjectParam, "bbw" }, - { o1_getObjectParam, "bbb" }, - { o1_addObjectParam, "bbw" }, - { o1_subObjectParam, "bbw" }, - /* 04 */ - { o1_add2ObjectParam, "bbw" }, - { o1_sub2ObjectParam, "bbw" }, - { o1_compareObjectParam, "bbw" }, - { o1_setupObject, "bwwww" }, - /* 08 */ - { o1_checkCollision, "bwwww" }, - { o1_loadVar, "bc" }, - { o1_addVar, "bc" }, - { o1_subVar, "bc" }, - /* 0C */ - { o1_mulVar, "bc" }, - { o1_divVar, "bc" }, - { o1_compareVar, "bc" }, - { o1_modifyObjectParam2, "bbb" }, - /* 10 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadMask0, "b" }, - /* 14 */ - { o1_unloadMask0, "b" }, - { o1_addToBgList, "b" }, - { o1_loadMask1, "b" }, - { o1_unloadMask1, "b" }, - /* 18 */ - { o1_loadMask4, "b" }, - { o1_unloadMask4, "b" }, - { o1_addSpriteFilledToBgList, "b" }, - { o1_op1B, "" }, - /* 1C */ - { 0, 0 }, - { o1_label, "l" }, - { o1_goto, "b" }, - { o1_gotoIfSup, "b" }, - /* 20 */ - { o1_gotoIfSupEqu, "b" }, - { o1_gotoIfInf, "b" }, - { o1_gotoIfInfEqu, "b" }, - { o1_gotoIfEqu, "b" }, - /* 24 */ - { o1_gotoIfDiff, "b" }, - { o1_removeLabel, "b" }, - { 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 }, - { o1_startGlobalScript, "b" }, - { o1_endGlobalScript, "b" }, - { 0, 0 }, - /* 34 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 38 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_loadAnim, "s" }, - /* 3C */ - { o1_loadBg, "s" }, - { o1_loadCt, "s" }, - { 0, 0 }, - { o2_loadPart, "s" }, - /* 40 */ - { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */ - { o1_loadNewPrcName, "bs" }, - { o1_requestCheckPendingDataLoad, "" }, - { 0, 0 }, - /* 44 */ - { 0, 0 }, - { o1_blitAndFade, "" }, - { o1_fadeToBlack, "" }, - { o1_transformPaletteRange, "bbwww" }, - /* 48 */ - { 0, 0 }, - { o1_setDefaultMenuColor2, "b" }, - { o1_palRotate, "bbb" }, - { 0, 0 }, - /* 4C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_break, "" }, - /* 50 */ - { o1_endScript, "x" }, - { o1_message, "bwwww" }, - { o1_loadGlobalVar, "bc" }, - { o1_compareGlobalVar, "bc" }, - /* 54 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 58 */ - { 0, 0 }, - { o1_declareFunctionName, "s" }, - { o1_freePartRange, "bb" }, - { o1_unloadAllMasks, "" }, - // 5C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - /* 60 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o1_setScreenDimensions, "wwww" }, - /* 64 */ - { o1_displayBackground, "" }, - { o1_initializeZoneData, "" }, - { o1_setZoneDataEntry, "bw" }, - { o1_getZoneDataEntry, "bb" }, - /* 68 */ - { o1_setDefaultMenuColor, "b" }, - { o1_allowPlayerInput, "" }, - { o1_disallowPlayerInput, "" }, - { o1_changeDataDisk, "b" }, - /* 6C */ - { 0, 0 }, - { o1_loadMusic, "s" }, - { o1_playMusic, "" }, - { o1_fadeOutMusic, "" }, - /* 70 */ - { o1_stopSample, "" }, - { o1_op71, "bw" }, - { o1_op72, "wbw" }, - { o1_op72, "wbw" }, - /* 74 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o2_playSample, "bbwbww" }, - /* 78 */ - { o2_playSampleAlt, "bbwbww" }, - { o1_disableSystemMenu, "b" }, - { o1_loadMask5, "b" }, - { o1_unloadMask5, "b" }, - /* 7C */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { o2_addSeqListElement, "bbbbwww" }, - /* 80 */ - { o2_removeSeq, "bb" }, - { o2_op81, "" }, - { o2_op82, "bbw" }, - { o2_isSeqRunning, "bb" }, - /* 84 */ - { o2_gotoIfSupNearest, "b" }, - { o2_gotoIfSupEquNearest, "b" }, - { o2_gotoIfInfNearest, "b" }, - { o2_gotoIfInfEquNearest, "b" }, - /* 88 */ - { o2_gotoIfEquNearest, "b" }, - { o2_gotoIfDiffNearest, "b" }, - { 0, 0 }, - { o2_startObjectScript, "b" }, - /* 8C */ - { o2_stopObjectScript, "b" }, - { o2_op8D, "wwwwwwww" }, - { o2_addBackground, "bs" }, - { o2_removeBackground, "b" }, - /* 90 */ - { o2_loadAbs, "bs" }, - { o2_loadBg, "b" }, - { 0, 0 }, - { 0, 0 }, - /* 94 */ - { 0, 0 }, - { o1_changeDataDisk, "b" }, - { 0, 0 }, - { 0, 0 }, - /* 98 */ - { 0, 0 }, - { 0, 0 }, - { o2_wasZoneChecked, "" }, - { o2_op9B, "wwwwwwww" }, - /* 9C */ - { o2_op9C, "wwww" }, - { o2_useBgScroll, "b" }, - { o2_setAdditionalBgVScroll, "c" }, - { o2_op9F, "ww" }, - /* A0 */ - { o2_addGfxElementA0, "ww" }, - { o2_opA1, "ww" }, - { o2_opA2, "ww" }, - { o2_opA3, "ww" }, - /* A4 */ - { o2_loadMask22, "b" }, - { o2_unloadMask22, "b" }, - { 0, 0 }, - { 0, 0 }, - /* A8 */ - { 0, 0 }, - { o1_changeDataDisk, "b" } - }; - + static FWScriptInfo fw; + static OSScriptInfo os; if (g_cine->getGameType() == Cine::GType_FW) { - _opcodeTable = opcodeTableFW; - _numOpcodes = ARRAYSIZE(opcodeTableFW); + scriptInfo = &fw; } else { - _opcodeTable = opcodeTableOS; - _numOpcodes = ARRAYSIZE(opcodeTableOS); + scriptInfo = &os; } } -byte getNextByte() { - byte val = *(_currentScriptPtr + _currentPosition); - _currentPosition++; - return val; -} - -uint16 getNextWord() { - uint16 val = READ_BE_UINT16(_currentScriptPtr + _currentPosition); - _currentPosition += 2; - return val; -} - -const char *getNextString() { - const char *val = (const char *)(_currentScriptPtr + _currentPosition); - _currentPosition += strlen(val) + 1; - return val; -} - -// empty array +/*! \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(); } -// read game save, for later use +/*! \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]) { @@ -468,16 +459,21 @@ ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len) load(fHandle); } -// copy constructor +/*! \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; @@ -489,462 +485,708 @@ ScriptVars &ScriptVars::operator=(const ScriptVars &src) { return *this; } -// array access +/*! \brief Direct array item access + * \param idx Item index + * \return Reference to item + */ int16 &ScriptVars::operator[](unsigned int idx) { - debugN(5, "assert(%d < %d)", idx, _size); + 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 { - debugN(5, "assert(%d < %d)\n", idx, _size); + debug(6, "assert(%d < %d)", idx, _size); assert(idx < _size); return _vars[idx]; } -// dump to savefile -void ScriptVars::save(Common::OutSaveFile &fHandle) { +/*! \brief Savefile writer + * \param fHandle Savefile open for writing + */ +void ScriptVars::save(Common::OutSaveFile &fHandle) const { save(fHandle, _size); } -// globalVars[255] is not written to savefiles... -void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) { - debugN(5, "assert(%d <= %d)\n", len, _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]); } } -// read from savefile +/*! \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) { - debugN(5, "assert(%d <= %d)\n", len, _size); + 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)); } -void addGfxElementA0(int16 param1, int16 param2) { - overlayHeadElement *currentHead = &overlayHead; - overlayHeadElement *tempHead = currentHead; - overlayHeadElement *newElement; - - currentHead = tempHead->next; - - while (currentHead) { - if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) { - if (currentHead->type == 2 || currentHead->objIdx == 3) { - break; - } - } - - tempHead = currentHead; - currentHead = currentHead->next; - } - - if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2) - return; - - newElement = new overlayHeadElement; - - newElement->next = tempHead->next; - tempHead->next = newElement; - - newElement->objIdx = param1; - newElement->type = 20; - - newElement->x = param2; - newElement->y = 0; - newElement->width = 0; - newElement->color = 0; - - if (!currentHead) - currentHead = &overlayHead; +/*! \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) { } - newElement->previous = currentHead->previous; +/*! \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) { - currentHead->previous = newElement; + setData(info, data); } -void removeSeq(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } +/*! \brief Copy constructor + */ +RawScript::RawScript(const RawScript &src) : _size(src._size), + _data(new byte[_size+1]), _labels(src._labels) { - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - currentHead->var4 = -1; - } + assert(_data); + memcpy(_data, src._data, _size+1); } -uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { - SeqListElement *currentHead = &seqList; - SeqListElement *tempHead = currentHead; - - while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { - tempHead = currentHead; - currentHead = tempHead->next; - } - - if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { - return 1; - } - - return 0; +/*! \brief Destructor + */ +RawScript::~RawScript(void) { + delete[] _data; } -ScriptStruct scriptTable[NUM_MAX_SCRIPT]; - -void stopGlobalScript(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \brief Assignment operator + */ +RawScript &RawScript::operator=(const RawScript &src) { + assert(src._data); + byte *tmp = new byte[src._size+1]; - currentHead = tempHead->next; + assert(tmp); + _labels = src._labels; + _size = src._size; - while (currentHead && (currentHead->scriptIdx != scriptIdx)) { - tempHead = currentHead; - currentHead = tempHead->next; - } + delete[] _data; + _data = tmp; + memcpy(_data, src._data, _size); + _data[_size] = 0; - if (!currentHead) { - return; - } + return *this; +} - if (currentHead->scriptIdx != scriptIdx) { - return; - } +/*! \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; - currentHead->scriptIdx = -1; -} + assert(pos >= 0); -uint16 computeScriptStackSub(bool computeAllLabels, byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, byte labelIndex, uint16 startOffset) { - uint16 position; + while (pos < _size) { + uint8 opcode = _data[pos++]; + const char *ptr = info.opcodeInfo(opcode); - if (computeAllLabels) { - for (int i = 0; i < SCRIPT_STACK_SIZE; i++) { - stackPtr[i] = -1; - } - position = 0; - } else { - position = startOffset; - } - while (position < scriptSize) { - uint8 opcode = scriptPtr[position]; - position++; - if (opcode == 0 || opcode > _numOpcodes) { - continue; - } - if (!_opcodeTable[opcode - 1].args) { - warning("Undefined opcode 0x%02X in computeScriptStackSub", opcode - 1); + if (!ptr) { continue; } - for (const char *p = _opcodeTable[opcode - 1].args; *p; ++p) { - switch (*p) { + + for (; *ptr; ++ptr) { + switch (*ptr) { case 'b': // byte - position++; + pos++; break; case 'w': // word - position += 2; + pos += 2; break; case 'c': { // byte != 0 ? byte : word - uint8 test = scriptPtr[position]; - position++; + uint8 test = _data[pos]; + pos++; if (test) { - position++; + pos++; } else { - position += 2; - } - } - break; - case 'l': { // label - uint8 index = scriptPtr[position]; - position++; - if (computeAllLabels) { - stackPtr[index] = position; - } else { - if (labelIndex == index) { - return position; - } + pos += 2; } } break; + case 'l': // label + return pos; case 's': // string - while (scriptPtr[position++] != 0); + while (_data[pos++] != 0); break; case 'x': // exit script - return position; + return -pos-1; } } } - return position; + return _size; } -void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) { - computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0); -} +/*! \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; + } -uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) { - return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition); + // parse bytecode + while ((pos = getNextLabel(info, pos)) >= 0) { + i = _data[pos]; + _labels[i] = ++pos; + } } -void palRotate(byte a, byte b, byte c) { - if (c == 1) { - uint16 currentColor = c_palette[b]; +/*! \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 { - for (int16 i = b; i > a; i--) { - c_palette[i] = c_palette[i - 1]; - } + assert(_data); + int pos = offset; - c_palette[a] = currentColor; + while ((pos = getNextLabel(info, pos)) >= 0) { + if (_data[pos++] == index) { + return pos; + } } + + return -pos - 1; } -void addScriptToList0(uint16 idx) { - uint16 i; - prcLinkedListStruct *pNewElement; - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \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(idx <= NUM_MAX_SCRIPT); + assert(data && _data); + memcpy(_data, data, _size * sizeof(byte)); + _data[_size] = 0; - currentHead = tempHead->next; + computeLabels(info); +} - while (currentHead) { - tempHead = currentHead; +/*! \brief Initial script labels + * \return Precalculated script labels + */ +const ScriptVars &RawScript::labels(void) const { + assert(_data); + return _labels; +} - assert(tempHead); +/*! \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); - currentHead = tempHead->next; - } + return _data[pos]; +} - pNewElement = new prcLinkedListStruct; +/*! \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); - assert(pNewElement); + return READ_BE_UINT16(_data + pos); +} - pNewElement->next = tempHead->next; - tempHead->next = pNewElement; +/*! \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); - // copy the stack into the script instance - for (i = 0; i < SCRIPT_STACK_SIZE; i++) { - pNewElement->stack[i] = scriptTable[idx].stack[i]; - } + return (const char*)(_data+pos); +} - pNewElement->compareResult = 0; - pNewElement->scriptPosition = 0; +/*! \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) { } - pNewElement->scriptPtr = scriptTable[idx].ptr; - pNewElement->scriptIdx = idx; -} +/*! \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) { } -int16 endScript0(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &globalScriptsHead; - prcLinkedListStruct *tempHead = currentHead; +/*! \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) { - //assert(scriptIdx <= NUM_MAX_SCRIPT); + _localVars[0] = script.run(); +} - currentHead = tempHead->next; +/*! \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) { } - while (currentHead && currentHead->scriptIdx != scriptIdx) { - tempHead = currentHead; - currentHead = tempHead->next; - } +FWScript::~FWScript(void) { + delete _info; +} - if (!currentHead) { - return -1; - } +/*! \brief Read next byte from bytecode + * \return Byte from bytecode + */ +byte FWScript::getNextByte() { + byte val = _script.getByte(_pos); + _pos++; + return val; +} - if (currentHead->scriptIdx != scriptIdx) { - return -1; - } +/*! \brief Read next word from bytecode + * \return Word from bytecode + */ +uint16 FWScript::getNextWord() { + uint16 val = _script.getWord(_pos); + _pos += 2; + return val; +} - currentHead->scriptIdx = -1; +/*! \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; +} - return 0; +/*! \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; } -int16 endScript1(uint16 scriptIdx) { - prcLinkedListStruct *currentHead = &objScriptList; - prcLinkedListStruct *tempHead = currentHead; +/*! \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; - currentHead = tempHead->next; + while (!ret) { + _line = _pos; + byte opcode = getNextByte(); + opFunc handler = _info->opcodeHandler(opcode); - while (currentHead && currentHead->scriptIdx != scriptIdx) { - tempHead = currentHead; - currentHead = tempHead->next; + if (handler) { + ret = (this->*handler)(); + } } - if (!currentHead) { - return -1; - } + return ret; +} - if (currentHead->scriptIdx != scriptIdx) { - return -1; +/*! \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 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) {} + +/*! \brief 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) {} + +/*! \brief Copy constructor + */ +OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {} + +/*! \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 OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) { + FWScript::load(labels, local, compare, pos); +} +/*! \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; } - currentHead->scriptIdx = -1; + if (!FWScript::_opcodeTable[opcode - 1].args) { + warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1); + return NULL; + } - return 0; + return FWScript::_opcodeTable[opcode - 1].args; } -int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) { - byte *ptr = page + (y * width) + x / 2; - byte zoneVar; +/*! \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 (!(x % 2)) { - zoneVar = (*(ptr) >> 4) & 0xF; - } else { - zoneVar = (*(ptr)) & 0xF; + if (!FWScript::_opcodeTable[opcode - 1].proc) { + warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1); + return NULL; } - return zoneVar; + return FWScript::_opcodeTable[opcode - 1].proc; } -int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) { - byte *ptr = page + (y * width) + x; - byte zoneVar; +/*! \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); +} - zoneVar = (*(ptr)) & 0xF; +/*! \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); +} - return zoneVar; +/*! \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; } -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; +/*! \brief 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 NULL; + } - for (int16 i = 0; i < numZones; i++) { - idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); + if (!OSScript::_opcodeTable[opcode - 1].args) { + warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1); + return NULL; + } - assert(idx >= 0 && idx <= NUM_MAX_ZONE); + return OSScript::_opcodeTable[opcode - 1].args; +} - if (zoneData[idx] == zoneIdx) { - return 1; - } +/*! \brief 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 NULL; } - return 0; + if (!OSScript::_opcodeTable[opcode - 1].proc) { + warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1); + return NULL; + } + + return OSScript::_opcodeTable[opcode - 1].proc; } -uint16 compareVars(int16 a, int16 b) { - uint16 flag = 0; +/*! \brief 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); +} - if (a == b) { - flag |= kCmpEQ; - } else if (a > b) { - flag |= kCmpGT; - } else if (a < b) { - flag |= kCmpLT; - } +/*! \brief 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); +} - return flag; +/*! \brief 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; +} + +/*! \brief 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; } // ------------------------------------------------------------------------ // FUTURE WARS opcodes // ------------------------------------------------------------------------ -void o1_modifyObjectParam() { +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)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); modifyObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_getObjectParam() { +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)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue); - _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx); + _localVars[newValue] = getObjectParam(objIdx, paramIdx); + return 0; } -void o1_addObjectParam() { +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)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); addObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_subObjectParam() { +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)", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue); subObjectParam(objIdx, paramIdx, newValue); + return 0; } -void o1_add2ObjectParam() { - getNextByte(); - getNextByte(); - getNextWord(); - warning("STUB: o1_add2ObjectParam()"); +/*! \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; } -void o1_sub2ObjectParam() { - getNextByte(); - getNextByte(); - getNextWord(); - warning("STUB: o1_sub2ObjectParam()"); +/*! \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; } -void o1_compareObjectParam() { +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)", _currentLine, objIdx, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2); - _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2); + _compare = compareObjectParam(objIdx, param1, param2); + return 0; } -void o1_setupObject() { +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)", _currentLine, objIdx, param1, param2, param3, param4); + 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; } -void o1_checkCollision() { +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)", _currentLine, objIdx, param1, param2, param3, param4); + debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4); - _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4); + _compare = checkCollision(objIdx, param1, param2, param3, param4); + return 0; } -void o1_loadVar() { +int FWScript::o1_loadVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); @@ -954,34 +1196,34 @@ void o1_loadVar() { switch (varType) { case 1: - debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx]; + 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]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = globalVars[dataIdx]; + 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", _currentLine, varIdx); - getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, (uint16 *)&dummyU16); - _currentScriptElement->localVars[varIdx] = var; + 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", _currentLine, varIdx); - getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&dummyU16, (uint16 *)&var); - _currentScriptElement->localVars[varIdx] = var; + 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", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1); + 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", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize; + 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", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize; + 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); @@ -989,352 +1231,413 @@ void o1_loadVar() { } else { int16 value = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] = value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value); + _localVars[varIdx] = value; } + + return 0; } -void o1_addVar() { +int FWScript::o1_addVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx]; + 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", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] += value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value); + _localVars[varIdx] += value; } + + return 0; } -void o1_subVar() { +int FWScript::o1_subVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx]; + 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", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] -= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value); + _localVars[varIdx] -= value; } + + return 0; } -void o1_mulVar() { +int FWScript::o1_mulVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx]; + 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", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] *= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value); + _localVars[varIdx] *= value; } + + return 0; } -void o1_divVar() { +int FWScript::o1_divVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx]; + 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", _currentLine, varIdx, value); - _currentScriptElement->localVars[varIdx] /= value; + debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value); + _localVars[varIdx] /= value; } + + return 0; } -void o1_compareVar() { +int FWScript::o1_compareVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte dataIdx = getNextByte(); - // printf("Val: %d\n", dataIdx); - if (varType == 1) { - assert(varIdx < 50); - assert(dataIdx < 50); - - debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], _currentScriptElement->localVars[dataIdx]); + debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx); + _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]); } else if (varType == 2) { - assert(varIdx < 50); - - debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _currentLine, varIdx, dataIdx); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], globalVars[dataIdx]); + 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", _currentLine, varIdx, value); - _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value); + debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value); + _compare = compareVars(_localVars[varIdx], value); } + + return 0; } -void o1_modifyObjectParam2() { +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])", _currentLine, objIdx, paramIdx, newValue); + debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue); - modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]); + modifyObjectParam(objIdx, paramIdx, _localVars[newValue]); + return 0; } -void o1_loadMask0() { +int FWScript::o1_loadMask0() { // OP_loadV7Element byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param); loadOverlayElement(param, 0); + return 0; } -void o1_unloadMask0() { +int FWScript::o1_unloadMask0() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param); freeOverlay(param, 0); + return 0; } -void o1_addToBgList() { +int FWScript::o1_addToBgList() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param); addToBGList(param); + return 0; } -void o1_loadMask1() { +int FWScript::o1_loadMask1() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param); loadOverlayElement(param, 1); + return 0; } -void o1_unloadMask1() { +int FWScript::o1_unloadMask1() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param); freeOverlay(param, 1); + return 0; } -void o1_loadMask4() { +int FWScript::o1_loadMask4() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param); loadOverlayElement(param, 4); + return 0; } -void o1_unloadMask4() { +int FWScript::o1_unloadMask4() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param); freeOverlay(param, 4); + return 0; } -void o1_addSpriteFilledToBgList() { +int FWScript::o1_addSpriteFilledToBgList() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param); addSpriteFilledToBGList(param); + return 0; } -void o1_op1B() { - debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine); - freeBgIncrustList(); +int FWScript::o1_op1B() { + debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line); + bgIncrustList.clear(); + return 0; } -void o1_label() { +int FWScript::o1_label() { byte labelIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx); - _currentScriptElement->stack[labelIdx] = _currentPosition; + debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx); + _labels[labelIdx] = _pos; + return 0; } -void o1_goto() { +int FWScript::o1_goto() { byte labelIdx = getNextByte(); - assert(_currentScriptElement->stack[labelIdx] != -1); + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx); + _pos = _labels[labelIdx]; + return 0; } -void o1_gotoIfSup() { +int FWScript::o1_gotoIfSup() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpGT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpGT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfSupEqu() { +int FWScript::o1_gotoIfSupEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpGT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfInf() { +int FWScript::o1_gotoIfInf() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpLT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpLT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfInfEqu() { +int FWScript::o1_gotoIfInfEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpLT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfEqu() { +int FWScript::o1_gotoIfEqu() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_gotoIfDiff() { +int FWScript::o1_gotoIfDiff() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult != kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare != kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx); + _pos = _labels[labelIdx]; } else { - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx); } + return 0; } -void o1_removeLabel() { +int FWScript::o1_removeLabel() { byte labelIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx); - _currentScriptElement->stack[labelIdx] = -1; + debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx); + _labels[labelIdx] = -1; + return 0; } -void o1_loop() { +int FWScript::o1_loop() { byte varIdx = getNextByte(); byte labelIdx = getNextByte(); - _currentScriptElement->localVars[varIdx]--; + _localVars[varIdx]--; - if (_currentScriptElement->localVars[varIdx] >= 0) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_localVars[varIdx] >= 0) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx); - _currentPosition = _currentScriptElement->stack[labelIdx]; + 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)", _currentLine, varIdx, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx); } + return 0; } -void o1_startGlobalScript() { +int FWScript::o1_startGlobalScript() { // OP_startScript byte param = getNextByte(); assert(param < NUM_MAX_SCRIPT); - debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param); addScriptToList0(param); + return 0; } -void o1_endGlobalScript() { +int FWScript::o1_endGlobalScript() { byte scriptIdx = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx); - stopGlobalScript(scriptIdx); + 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; } -void o1_loadAnim() { +int FWScript::o1_loadAnim() { // OP_loadResource const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param); loadResource(param); + return 0; } -void o1_loadBg() { +int FWScript::o1_loadBg() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param); loadBg(param); - freeBgIncrustList(); + bgIncrustList.clear(); bgVar0 = 0; + return 0; } -void o1_loadCt() { +int FWScript::o1_loadCt() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param); loadCt(param); + return 0; } -void o1_loadPart() { +int FWScript::o1_loadPart() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param); loadPart(param); + return 0; } -void o1_closePart() { - debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine); +int FWScript::o1_closePart() { + debugC(5, kCineDebugScript, "Line: %d: closePart", _line); closePart(); + return 0; } -void o1_loadNewPrcName() { +int FWScript::o1_loadNewPrcName() { // OP_loadData byte param1 = getNextByte(); const char *param2 = getNextString(); @@ -1343,104 +1646,113 @@ void o1_loadNewPrcName() { switch (param1) { case 0: - debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2); strcpy(newPrcName, param2); break; case 1: - debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2); strcpy(newRelName, param2); break; case 2: - debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2); strcpy(newObjectName, param2); break; case 3: - debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2); strcpy(newMsgName, param2); break; } + return 0; } -void o1_requestCheckPendingDataLoad() { - debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine); +int FWScript::o1_requestCheckPendingDataLoad() { + debugC(5, kCineDebugScript, "Line: %d: request data load", _line); checkForPendingDataLoadSwitch = 1; + return 0; } -void o1_blitAndFade() { - debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine); +int FWScript::o1_blitAndFade() { + debugC(5, kCineDebugScript, "Line: %d: request fadein", _line); // TODO: use real code drawOverlays(); fadeRequired = true; flip(); + +// fadeFromBlack(); + return 0; } -void o1_fadeToBlack() { - debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine); +int FWScript::o1_fadeToBlack() { + debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line); fadeToBlack(); + return 0; } -void o1_transformPaletteRange() { +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)", _currentLine, startColor, numColor, r, g, b); + 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; } -void o1_setDefaultMenuColor2() { +int FWScript::o1_setDefaultMenuColor2() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param); defaultMenuBoxColor2 = param; + return 0; } -void o1_palRotate() { +int FWScript::o1_palRotate() { byte a = getNextByte(); byte b = getNextByte(); byte c = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c); + debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c); palRotate(a, b, c); + return 0; } -void o1_break() { - debugC(5, kCineDebugScript, "Line: %d: break", _currentLine); +/*!\brief Pause script + * \todo Make sure it works + */ +int FWScript::o1_break() { + debugC(5, kCineDebugScript, "Line: %d: break", _line); - _currentScriptElement->scriptPosition = _currentPosition; - _closeScript = 1; + return 1; } -void o1_endScript() { - debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine); - - if (_currentScriptParams == 0) { - endScript0(_currentScriptElement->scriptIdx); - } else { - endScript1(_currentScriptElement->scriptIdx); - } +/*! \brief Terminate script + * \todo Make sure it works + */ +int FWScript::o1_endScript() { + debugC(5, kCineDebugScript, "Line: %d: endScript", _line); - _closeScript = 1; + return -1; } -void o1_message() { +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)", _currentLine, param1, param2, param3, param4, param5); + 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; } -void o1_loadGlobalVar() { +int FWScript::o1_loadGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); @@ -1448,169 +1760,207 @@ void o1_loadGlobalVar() { byte dataIdx = getNextByte(); if (varType == 1) { - debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx); - globalVars[varIdx] = _currentScriptElement->localVars[dataIdx]; + 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]", _currentLine, varIdx, dataIdx); - globalVars[varIdx] = globalVars[dataIdx]; + 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", _currentLine, varIdx, value); - globalVars[varIdx] = value; + debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value); + _globalVars[varIdx] = value; } + + return 0; } -void o1_compareGlobalVar() { +int FWScript::o1_compareGlobalVar() { byte varIdx = getNextByte(); byte varType = getNextByte(); if (varType) { byte value = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value); - _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]); + 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", _currentLine, varIdx, value); + debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value); if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) { // TODO: fix - _currentScriptElement->compareResult = 1; + _compare = 1; } else { - _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value); + _compare = compareVars(_globalVars[varIdx], value); } } + + return 0; } -void o1_declareFunctionName() { +int FWScript::o1_declareFunctionName() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param); + return 0; } -void o1_freePartRange() { +int FWScript::o1_freePartRange() { byte startIdx = getNextByte(); byte numIdx = getNextByte(); assert(startIdx + numIdx <= NUM_MAX_ANIMDATA); - debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx); + debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx); freeAnimDataRange(startIdx, numIdx); + return 0; } -void o1_unloadAllMasks() { - debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine); +int FWScript::o1_unloadAllMasks() { + debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line); unloadAllMasks(); + return 0; } -void o1_setScreenDimensions() { - warning("STUB: o1_setScreenDimensions()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \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; } -void o1_displayBackground() { +/*! \todo Implement this instruction + */ +int FWScript::o1_displayBackground() { warning("STUB: o1_displayBackground()"); + return 0; } -void o1_initializeZoneData() { - debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine); +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; } -void o1_setZoneDataEntry() { +int FWScript::o1_setZoneDataEntry() { byte zoneIdx = getNextByte(); uint16 var = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var); + debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var); zoneData[zoneIdx] = var; + return 0; } -void o1_getZoneDataEntry() { +int FWScript::o1_getZoneDataEntry() { byte zoneIdx = getNextByte(); byte var = getNextByte(); - _currentScriptElement->localVars[var] = zoneData[zoneIdx]; + _localVars[var] = zoneData[zoneIdx]; + return 0; } -void o1_setDefaultMenuColor() { +int FWScript::o1_setDefaultMenuColor() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param); defaultMenuBoxColor = param; + return 0; } -void o1_allowPlayerInput() { - debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine); +int FWScript::o1_allowPlayerInput() { + debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line); allowPlayerInput = 1; + return 0; } -void o1_disallowPlayerInput() { - debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine); +int FWScript::o1_disallowPlayerInput() { + debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line); allowPlayerInput = 0; + return 0; } -void o1_changeDataDisk() { +int FWScript::o1_changeDataDisk() { byte newDisk = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk); + debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk); checkDataDisk(newDisk); + return 0; } -void o1_loadMusic() { +int FWScript::o1_loadMusic() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param); g_sound->loadMusic(param); + return 0; } -void o1_playMusic() { - debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine); +int FWScript::o1_playMusic() { + debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line); g_sound->playMusic(); + return 0; } -void o1_fadeOutMusic() { - debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine); +int FWScript::o1_fadeOutMusic() { + debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line); g_sound->fadeOutMusic(); + return 0; } -void o1_stopSample() { - debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine); +int FWScript::o1_stopSample() { + debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line); g_sound->stopMusic(); + return 0; } -void o1_op71() { - warning("STUB: o1_op71()"); - getNextByte(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o1_op71() { + byte a = getNextByte(); + uint16 b = getNextWord(); + warning("STUB: o1_op71(%x, %x)", a, b); + return 0; } -void o1_op72() { - warning("STUB: o1_op72()"); - getNextWord(); - getNextByte(); - getNextWord(); +/*! \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; } -void o1_op73() { +/*! \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. - warning("STUB: o1_op73()"); - getNextWord(); - getNextByte(); - getNextWord(); + uint16 a = getNextWord(); + byte b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o1_op72(%x, %x, %x)", a, b, c); + return 0; } -void o1_playSample() { - debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine); +int FWScript::o1_playSample() { + debugC(5, kCineDebugScript, "Line: %d: playSample()", _line); byte anim = getNextByte(); byte channel = getNextByte(); @@ -1621,13 +1971,15 @@ void o1_playSample() { int16 volume = getNextWord(); uint16 size = getNextWord(); - if (!animDataTable[anim].ptr1) { - return; + 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; + size = animDataTable[anim]._width * animDataTable[anim]._height; } if (channel < 10) { // || _currentOpcode == 0x78 int channel1, channel2; @@ -1638,14 +1990,14 @@ void o1_playSample() { channel1 = 2; channel2 = 3; } - g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat); - g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size, 1, volume, 0, repeat); + 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, animDataTable[anim].ptr1, size, 0, 0, volume, repeat); + g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat); } } else { if (volume > 63 || volume < 0) { @@ -1658,49 +2010,54 @@ void o1_playSample() { volume = 50; } if (g_cine->getGameType() == Cine::GType_OS && size == 0) { - return; + return 0; } g_sound->stopMusic(); if (size == 0xFFFF) { - g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0); + g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0); } else { g_sound->stopSound(channel); } } + return 0; } -void o1_disableSystemMenu() { +int FWScript::o1_disableSystemMenu() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param); disableSystemMenu = (param != 0); + return 0; } -void o1_loadMask5() { +int FWScript::o1_loadMask5() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param); loadOverlayElement(param, 5); + return 0; } -void o1_unloadMask5() { +int FWScript::o1_unloadMask5() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param); freeOverlay(param, 5); + return 0; } // ------------------------------------------------------------------------ // OPERATION STEALTH opcodes // ------------------------------------------------------------------------ -void o2_loadPart() { +int FWScript::o2_loadPart() { const char *param = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param); + return 0; } -void o2_playSample() { +int FWScript::o2_playSample() { if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) { // no-op in these versions getNextByte(); @@ -1709,12 +2066,12 @@ void o2_playSample() { getNextByte(); getNextWord(); getNextWord(); - return; + return 0; } - o1_playSample(); + return o1_playSample(); } -void o2_playSampleAlt() { +int FWScript::o2_playSampleAlt() { byte num = getNextByte(); byte channel = getNextByte(); uint16 frequency = getNextWord(); @@ -1723,21 +2080,22 @@ void o2_playSampleAlt() { uint16 size = getNextWord(); if (size == 0xFFFF) { - size = animDataTable[num].width * animDataTable[num].height; + size = animDataTable[num]._width * animDataTable[num]._height; } - if (animDataTable[num].ptr1) { + if (animDataTable[num].data()) { if (g_cine->getPlatform() == Common::kPlatformPC) { // 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, animDataTable[num].ptr1, size, 0, 0, 63, 0); + g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0); } } + return 0; } -void o2_addSeqListElement() { +int FWScript::o2_addSeqListElement() { byte param1 = getNextByte(); byte param2 = getNextByte(); byte param3 = getNextByte(); @@ -1746,162 +2104,201 @@ void o2_addSeqListElement() { uint16 param6 = getNextWord(); uint16 param7 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7); + 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; } -void o2_removeSeq() { +int FWScript::o2_removeSeq() { byte a = getNextByte(); byte b = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b); + debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b); removeSeq(a, 0, b); + return 0; } -void o2_op81() { +/*! \todo Implement this instruction + */ +int FWScript::o2_op81() { warning("STUB: o2_op81()"); // freeUnkList(); + return 0; } -void o2_op82() { - warning("STUB: o2_op82()"); - getNextByte(); - getNextByte(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op82() { + byte a = getNextByte(); + byte b = getNextByte(); + uint16 c = getNextWord(); + warning("STUB: o2_op82(%x, %x, %x)", a, b, c); + return 0; } -void o2_isSeqRunning() { +int FWScript::o2_isSeqRunning() { byte a = getNextByte(); byte b = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b); + debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b); if (isSeqRunning(a, 0, b)) { - _currentScriptElement->compareResult = 1; + _compare = 1; } else { - _currentScriptElement->compareResult = 0; + _compare = 0; } + return 0; } -void o2_gotoIfSupNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfSupNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpGT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpGT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfSupEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfSupEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpGT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfInfNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfInfNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpLT) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpLT) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfInfEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfInfEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare & (kCmpLT | kCmpEQ)) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfEquNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfEquNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult == kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare == kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_gotoIfDiffNearest() { +/*! \todo The assert may produce false positives and requires testing + */ +int FWScript::o2_gotoIfDiffNearest() { byte labelIdx = getNextByte(); - if (_currentScriptElement->compareResult != kCmpEQ) { - assert(_currentScriptElement->stack[labelIdx] != -1); + if (_compare != kCmpEQ) { + assert(_labels[labelIdx] != -1); - debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx); - _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size); + 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)", _currentLine, labelIdx); + debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx); } + return 0; } -void o2_startObjectScript() { +int FWScript::o2_startObjectScript() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param); runObjectScript(param); + return 0; } -void o2_stopObjectScript() { +int FWScript::o2_stopObjectScript() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param); - stopObjectScript(param); + debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param); + ScriptList::iterator it = objectScripts.begin(); + + for (; it != objectScripts.end(); ++it) { + if ((*it)->_index == param) { + (*it)->_index = -1; + } + } + return 0; } -void o2_op8D() { - warning("STUB: o2_op8D()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_op8D() { + 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_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h); // _currentScriptElement->compareResult = ... + return 0; } -void o2_addBackground() { +int FWScript::o2_addBackground() { byte param1 = getNextByte(); const char *param2 = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1); + debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1); addBackground(param2, param1); + return 0; } -void o2_removeBackground() { +int FWScript::o2_removeBackground() { byte param = getNextByte(); assert(param); - debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param); if (additionalBgTable[param]) { free(additionalBgTable[param]); @@ -1917,192 +2314,358 @@ void o2_removeBackground() { } strcpy(currentBgName[param], ""); + return 0; } -void o2_loadAbs() { +int FWScript::o2_loadAbs() { byte param1 = getNextByte(); const char *param2 = getNextString(); - debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2); loadAbs(param2, param1); + return 0; } -void o2_loadBg() { +int FWScript::o2_loadBg() { byte param = getNextByte(); assert(param <= 8); - debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param); if (additionalBgTable[param]) { currentAdditionalBgIdx = param; + if (param == 8) { + newColorMode = 3; + } else { + newColorMode = bgColorMode + 1; + } //if (_screenNeedFadeOut == 0) { // adBgVar1 = 1; //} fadeRequired = true; } + return 0; } -void o2_wasZoneChecked() { +/*! \todo Implement this instruction + */ +int FWScript::o2_wasZoneChecked() { warning("STUB: o2_wasZoneChecked()"); + return 0; } -void o2_op9B() { - warning("STUB: o2_op9B()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +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; } -void o2_op9C() { - warning("STUB: o2_op9C()"); - getNextWord(); - getNextWord(); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +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; } -void o2_useBgScroll() { +int FWScript::o2_useBgScroll() { byte param = getNextByte(); assert(param <= 8); - debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param); if (additionalBgTable[param]) { currentAdditionalBgIdx2 = param; } + return 0; } -void o2_setAdditionalBgVScroll() { +int FWScript::o2_setAdditionalBgVScroll() { byte param1 = getNextByte(); if (param1) { byte param2 = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2); - additionalBgVScroll = _currentScriptElement->localVars[param2]; + debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2); + additionalBgVScroll = _localVars[param2]; } else { uint16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2); + debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2); additionalBgVScroll = param2; } + return 0; } -void o2_op9F() { +/*! \todo Implement this instruction + */ +int FWScript::o2_op9F() { warning("o2_op9F()"); getNextWord(); getNextWord(); + return 0; } -void o2_addGfxElementA0() { +int FWScript::o2_addGfxElementA0() { uint16 param1 = getNextWord(); uint16 param2 = getNextWord(); - debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2); + debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2); addGfxElementA0(param1, param2); + return 0; } -void o2_opA1() { - warning("STUB: o2_opA1()"); - getNextWord(); - getNextWord(); - // removeGfxElementA0( ... ); +/*! \todo Implement this instruction + */ +int FWScript::o2_removeGfxElementA0() { + uint16 idx = getNextWord(); + uint16 param = getNextWord(); + warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param); + removeGfxElementA0(idx, param); + return 0; } -void o2_opA2() { - warning("STUB: o2_opA2()"); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_opA2() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + warning("STUB: o2_opA2(%x, %x)", a, b); // addGfxElementA2(); + return 0; } -void o2_opA3() { - warning("STUB: o2_opA3()"); - getNextWord(); - getNextWord(); +/*! \todo Implement this instruction + */ +int FWScript::o2_opA3() { + uint16 a = getNextWord(); + uint16 b = getNextWord(); + warning("STUB: o2_opA3(%x, %x)", a, b); // removeGfxElementA2(); + return 0; } -void o2_loadMask22() { +int FWScript::o2_loadMask22() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param); loadOverlayElement(param, 22); + return 0; } -void o2_unloadMask22() { +int FWScript::o2_unloadMask22() { byte param = getNextByte(); - debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param); + debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param); freeOverlay(param, 22); + return 0; } -// ------------------------------------------------------------------------ +//----------------------------------------------------------------------- -void executeScript(prcLinkedListStruct *scriptElement, uint16 params) { - assert(scriptElement); +void addGfxElementA0(int16 param1, int16 param2) { + overlayHeadElement *currentHead = &overlayHead; + overlayHeadElement *tempHead = currentHead; + overlayHeadElement *newElement; + + currentHead = tempHead->next; + + while (currentHead) { + if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) { + if (currentHead->type == 2 || currentHead->objIdx == 3) { + break; + } + } + + tempHead = currentHead; + currentHead = currentHead->next; + } - if (scriptElement->scriptIdx == -1) { + if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2) return; + + newElement = new overlayHeadElement; + + newElement->next = tempHead->next; + tempHead->next = newElement; + + newElement->objIdx = param1; + newElement->type = 20; + + newElement->x = param2; + newElement->y = 0; + newElement->width = 0; + newElement->color = 0; + + if (!currentHead) + currentHead = &overlayHead; + + newElement->previous = currentHead->previous; + + currentHead->previous = newElement; +} + +/*! \todo Check that it works + */ +void removeGfxElementA0(int16 idx, int16 param) { + overlayHeadElement *parent = &overlayHead; + overlayHeadElement *head = overlayHead.next; + overlayHeadElement *tmp; + + while (head) { + if (head->objIdx == idx && head->x == param) { + parent->next = head->next; + tmp = head->next ? head->next : &overlayHead; + tmp->previous = parent; + delete head; + return; + } + + parent = head; + head = head->next; } +} - assert(scriptElement->scriptPtr); +void removeSeq(uint16 param1, uint16 param2, uint16 param3) { + SeqListElement *currentHead = &seqList; + SeqListElement *tempHead = currentHead; - _currentScriptElement = scriptElement; - _currentScriptParams = params; - _currentScriptPtr = scriptElement->scriptPtr; - _currentPosition = scriptElement->scriptPosition; + while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { + tempHead = currentHead; + currentHead = tempHead->next; + } - _closeScript = 0; + if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { + currentHead->var4 = -1; + } +} - while (!_closeScript) { - _currentLine = _currentPosition; +uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { + SeqListElement *currentHead = &seqList; + SeqListElement *tempHead = currentHead; - byte opcode = getNextByte(); + while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { + tempHead = currentHead; + currentHead = tempHead->next; + } + + if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { + return 1; + } + + return 0; +} + +void palRotate(byte a, byte b, byte c) { + if (c == 1) { + uint16 currentColor = c_palette[b]; - if (opcode && opcode < _numOpcodes) { - if (_opcodeTable[opcode - 1].proc) - (_opcodeTable[opcode - 1].proc) (); - else - warning("Undefined opcode 0x%02X in executeScript", opcode - 1); + for (int16 i = b; i > a; i--) { + c_palette[i] = c_palette[i - 1]; } + + c_palette[a] = currentColor; } } -void executeList1(void) { - prcLinkedListStruct *currentHead = objScriptList.next; +void addScriptToList0(uint16 idx) { + ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx)); + assert(tmp); + globalScripts.push_back(tmp); +} - while (currentHead) { - prcLinkedListStruct *tempHead; +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; - tempHead = currentHead->next; + for (int16 i = 0; i < numZones; i++) { + idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320); - executeScript(currentHead, 1); + assert(idx >= 0 && idx <= NUM_MAX_ZONE); - currentHead = tempHead; + if (zoneData[idx] == zoneIdx) { + return 1; + } } + + return 0; } -void executeList0(void) { - prcLinkedListStruct *currentHead = globalScriptsHead.next; +uint16 compareVars(int16 a, int16 b) { + uint16 flag = 0; - while (currentHead) { - prcLinkedListStruct *tempHead; + if (a == b) { + flag |= kCmpEQ; + } else if (a > b) { + flag |= kCmpGT; + } else if (a < b) { + flag |= kCmpLT; + } + + return flag; +} - executeScript(currentHead, 0); +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; + } + } +} - tempHead = currentHead->next; - currentHead = tempHead; +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) { } @@ -2463,7 +3026,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 } case 0x1B: { - sprintf(lineBuffer, "freeBgIncrustList()\n"); + sprintf(lineBuffer, "bgIncrustList.clear()\n"); break; } case 0x1D: @@ -2804,7 +3367,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 sprintf(lineBuffer, "disallowPlayerInput()\n"); break; } - case OP_changeDataDisk: + case 0x6B: { byte newDisk; @@ -2878,7 +3441,7 @@ void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 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) { + } else if (opcode - 1 == 0x78) { sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6); } |