Ticket #8841: script.patch

File script.patch, 135.2 KB (added by SF/next_ghost, 16 years ago)

Script system replacement

  • engines/cine/script.h

     
    2727#define CINE_SCRIPT_H
    2828
    2929#include "common/savefile.h"
     30#include "common/array.h"
     31#include "common/list.h"
     32#include "common/ptr.h"
    3033
    3134namespace Cine {
    3235
    3336#define SCRIPT_STACK_SIZE 50
     37#define LOCAL_VARS_SIZE 50
    3438
     39/*! \brief Fixed size array of script variables.
     40 *
     41 * Array size can be set in constructors, once the instance is created,
     42 * it cannot be changed directly.
     43 */
     44
     45class FWScript;
     46
     47typedef int (FWScript::*opFunc)();
     48
     49struct Opcode {
     50        opFunc proc;
     51        const char *args;
     52};
     53
     54/*! \brief Fixed size array for script variables
     55 */
    3556class ScriptVars {
    3657private:
    37         unsigned int _size;
    38         int16 *_vars;
     58        unsigned int _size; ///< Size of array
     59        int16 *_vars; ///< Variable values
    3960
    4061public:
     62        // Explicit to prevent var=0 instead of var[i]=0 typos.
    4163        explicit ScriptVars(unsigned int len = 50);
    4264        ScriptVars(Common::InSaveFile &fHandle, unsigned int len = 50);
    4365        ScriptVars(const ScriptVars &src);
     
    4769        int16 &operator[](unsigned int idx);
    4870        int16 operator[](unsigned int idx) const;
    4971
    50         void save(Common::OutSaveFile &fHandle);
    51         void save(Common::OutSaveFile &fHandle, unsigned int len);
     72        void save(Common::OutSaveFile &fHandle) const;
     73        void save(Common::OutSaveFile &fHandle, unsigned int len) const;
    5274        void load(Common::InSaveFile &fHandle);
    5375        void load(Common::InSaveFile &fHandle, unsigned int len);
    5476        void reset(void);
    5577};
    5678
    57 struct ScriptStruct {
    58         byte *ptr;
    59         uint16 size;
    60         int16 stack[SCRIPT_STACK_SIZE];
     79class FWScriptInfo;
     80
     81/*! \brief Script bytecode and initial labels, ScriptStruct replacement.
     82 *
     83 * _data is one byte longer to make sure strings in bytecode are properly
     84 * terminated
     85 */
     86class RawScript {
     87private:
     88        uint16 _size; ///< Bytecode length
     89        byte *_data; ///< Script bytecode
     90        ScriptVars _labels; ///< Initial script labels
     91
     92protected:
     93        void computeLabels(const FWScriptInfo &info);
     94        uint16 getNextLabel(const FWScriptInfo &info, uint16 offset) const;
     95
     96public:
     97        explicit RawScript(uint16 size);
     98        RawScript(const FWScriptInfo &info, const byte *data, uint16 size);
     99        RawScript(const RawScript &src);
     100        ~RawScript(void);
     101
     102        RawScript &operator=(const RawScript &src);
     103
     104        void setData(const FWScriptInfo &info, const byte *data);
     105        /*! \brief Size of script
     106         * \return Size of script
     107         */
     108        uint16 size(void) const { return _size; }
     109        const ScriptVars &labels(void) const;
     110        byte getByte(unsigned int pos) const;
     111        uint16 getWord(unsigned int pos) const;
     112        const char *getString(unsigned int pos) const;
     113        uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const;
    61114};
    62115
     116/*! \brief Object script class, RelObjectScript replacement
     117 *
     118 * Script parameters are not used, this class is required by different
     119 * script initialization of object scripts
     120 */
     121class RawObjectScript : public RawScript {
     122private:
     123        int16 _runCount; ///< How many times the script was used
     124        uint16 _param1; ///< Additional parameter not used at the moment
     125        uint16 _param2; ///< Additional parameter not used at the moment
     126        uint16 _param3; ///< Additional parameter not used at the moment
     127
     128public:
     129        RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3);
     130        RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3);
     131
     132        /// \brief Read run count
     133        /// \return Run count
     134        int16 runCount(void) const { return _runCount; }
     135        /// \brief Run the script one more time
     136        /// \return Run count before incrementation
     137        int16 run(void) { return _runCount++; }
     138
     139        /// \brief Get the first object script parameter
     140        /// \return First script parameter
     141        uint16 param1(void) const { return _param1; }
     142        /// \brief Get the second object script parameter
     143        /// \return Second script parameter
     144        uint16 param2(void) const { return _param2; }
     145        /// \brief Get the third object script parameter
     146        /// \return Third script parameter
     147        uint16 param3(void) const { return _param3; }
     148};
     149
     150/*! \brief Future Wars script, prcLinkedListStruct replacement
     151 * \todo Rewrite _globalVars initialization
     152 */
     153class FWScript {
     154private:
     155        const RawScript &_script; ///< Script bytecode reference
     156        uint16 _pos; ///< Current position in script
     157        uint16 _line; ///< Current opcode index in bytecode for debugging
     158        uint16 _compare; ///< Last compare result
     159        int16 _index; ///< Index in script table
     160        ScriptVars _labels; ///< Current script labels
     161        ScriptVars _localVars; ///< Local script variables
     162        ScriptVars &_globalVars; ///< Global variables reference
     163        FWScriptInfo *_info; ///< Script info
     164
     165        static const Opcode _opcodeTable[];
     166        static const unsigned int _numOpcodes;
     167
     168protected:
     169        int o1_modifyObjectParam();
     170        int o1_getObjectParam();
     171        int o1_addObjectParam();
     172        int o1_subObjectParam();
     173        int o1_add2ObjectParam();
     174        int o1_sub2ObjectParam();
     175        int o1_compareObjectParam();
     176        int o1_setupObject();
     177        int o1_checkCollision();
     178        int o1_loadVar();
     179        int o1_addVar();
     180        int o1_subVar();
     181        int o1_mulVar();
     182        int o1_divVar();
     183        int o1_compareVar();
     184        int o1_modifyObjectParam2();
     185        int o1_loadMask0();
     186        int o1_unloadMask0();
     187        int o1_addToBgList();
     188        int o1_loadMask1();
     189        int o1_unloadMask1();
     190        int o1_loadMask4();
     191        int o1_unloadMask4();
     192        int o1_addSpriteFilledToBgList();
     193        int o1_op1B();
     194        int o1_label();
     195        int o1_goto();
     196        int o1_gotoIfSup();
     197        int o1_gotoIfSupEqu();
     198        int o1_gotoIfInf();
     199        int o1_gotoIfInfEqu();
     200        int o1_gotoIfEqu();
     201        int o1_gotoIfDiff();
     202        int o1_removeLabel();
     203        int o1_loop();
     204        int o1_startGlobalScript();
     205        int o1_endGlobalScript();
     206        int o1_loadAnim();
     207        int o1_loadBg();
     208        int o1_loadCt();
     209        int o1_loadPart();
     210        int o1_closePart();
     211        int o1_loadNewPrcName();
     212        int o1_requestCheckPendingDataLoad();
     213        int o1_blitAndFade();
     214        int o1_fadeToBlack();
     215        int o1_transformPaletteRange();
     216        int o1_setDefaultMenuColor2();
     217        int o1_palRotate();
     218        int o1_break();
     219        int o1_endScript();
     220        int o1_message();
     221        int o1_loadGlobalVar();
     222        int o1_compareGlobalVar();
     223        int o1_declareFunctionName();
     224        int o1_freePartRange();
     225        int o1_unloadAllMasks();
     226        int o1_setScreenDimensions();
     227        int o1_displayBackground();
     228        int o1_initializeZoneData();
     229        int o1_setZoneDataEntry();
     230        int o1_getZoneDataEntry();
     231        int o1_setDefaultMenuColor();
     232        int o1_allowPlayerInput();
     233        int o1_disallowPlayerInput();
     234        int o1_changeDataDisk();
     235        int o1_loadMusic();
     236        int o1_playMusic();
     237        int o1_fadeOutMusic();
     238        int o1_stopSample();
     239        int o1_op71();
     240        int o1_op72();
     241        int o1_op73();
     242        int o1_playSample();
     243        int o1_disableSystemMenu();
     244        int o1_loadMask5();
     245        int o1_unloadMask5();
     246
     247        // pointers to member functions in C++ suck...
     248        int o2_loadPart();
     249        int o2_addSeqListElement();
     250        int o2_removeSeq();
     251        int o2_playSample();
     252        int o2_playSampleAlt();
     253        int o2_op81();
     254        int o2_op82();
     255        int o2_isSeqRunning();
     256        int o2_gotoIfSupNearest();
     257        int o2_gotoIfSupEquNearest();
     258        int o2_gotoIfInfNearest();
     259        int o2_gotoIfInfEquNearest();
     260        int o2_gotoIfEquNearest();
     261        int o2_gotoIfDiffNearest();
     262        int o2_startObjectScript();
     263        int o2_stopObjectScript();
     264        int o2_op8D();
     265        int o2_addBackground();
     266        int o2_removeBackground();
     267        int o2_loadAbs();
     268        int o2_loadBg();
     269        int o2_wasZoneChecked();
     270        int o2_op9B();
     271        int o2_op9C();
     272        int o2_useBgScroll();
     273        int o2_setAdditionalBgVScroll();
     274        int o2_op9F();
     275        int o2_addGfxElementA0();
     276        int o2_opA1();
     277        int o2_opA2();
     278        int o2_opA3();
     279        int o2_loadMask22();
     280        int o2_unloadMask22();
     281
     282        byte getNextByte();
     283        uint16 getNextWord();
     284        const char *getNextString();
     285
     286        void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
     287
     288        FWScript(const RawScript &script, int16 index, FWScriptInfo *info);
     289        FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info);
     290        FWScript(const FWScript &src, FWScriptInfo *info);
     291
     292public:
     293        FWScript(const RawScript &script, int16 index);
     294//      FWScript(const RawObjectScript &script, int16 index);
     295        FWScript(const FWScript &src);
     296        ~FWScript(void);
     297
     298        int execute();
     299        void save(Common::OutSaveFile &fHandle) const;
     300
     301        /*! \brief Index in script table
     302         * \return Index in script table
     303         */
     304        int16 index(void) const { return _index; }
     305
     306        friend class FWScriptInfo;
     307
     308        // workaround for bug in g++ which prevents protected member functions
     309        // of FWScript from being used in OSScript::_opcodeTable[]
     310        // initialization ("error: protected within this context")
     311        friend class OSScript;
     312};
     313
     314/*! \brief Operation Stealth script, prcLinkedListStruct replacement
     315 */
     316class OSScript : public FWScript {
     317private:
     318        static const Opcode _opcodeTable[];
     319        static const unsigned int _numOpcodes;
     320
     321protected:
     322        void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
     323
     324public:
     325        OSScript(const RawScript &script, int16 index);
     326        OSScript(RawObjectScript &script, int16 index);
     327        OSScript(const OSScript &src);
     328
     329        friend class OSScriptInfo;
     330};
     331
     332/*! \brief Future Wars script factory and info
     333 */
     334class FWScriptInfo {
     335protected:
     336        virtual opFunc opcodeHandler(byte opcode) const;
     337
     338public:
     339        virtual ~FWScriptInfo() {}
     340
     341        virtual const char *opcodeInfo(byte opcode) const;
     342        virtual FWScript *create(const RawScript &script, int16 index) const;
     343        virtual FWScript *create(const RawObjectScript &script, int16 index) const;
     344        virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     345        virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     346
     347        friend class FWScript;
     348};
     349
     350/*! \brief Operation Stealth script factory and info
     351 */
     352class OSScriptInfo : public FWScriptInfo {
     353protected:
     354        virtual opFunc opcodeHandler(byte opcode) const;
     355
     356public:
     357        virtual ~OSScriptInfo() {}
     358
     359        virtual const char *opcodeInfo(byte opcode) const;
     360        virtual FWScript *create(const RawScript &script, int16 index) const;
     361        virtual FWScript *create(const RawObjectScript &script, int16 index) const;
     362        virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     363        virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     364
     365        friend class FWScript;
     366};
     367
     368typedef Common::SharedPtr<FWScript> ScriptPtr;
     369typedef Common::SharedPtr<RawScript> RawScriptPtr;
     370typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr;
     371typedef Common::List<ScriptPtr> ScriptList;
     372typedef Common::Array<RawScriptPtr> RawScriptArray;
     373typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
     374
    63375#define NUM_MAX_SCRIPT 50
    64376
    65 extern ScriptStruct scriptTable[NUM_MAX_SCRIPT];
     377extern RawScriptArray scriptTable;
     378extern FWScriptInfo *scriptInfo;
    66379
    67380void setupOpcodes();
    68381
    69 void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize);
    70382void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx);
    71383void dumpScript(char *dumpName);
    72384
     
    79391int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx);
    80392
    81393void runObjectScript(int16 entryIdx);
    82 int16 stopObjectScript(int16 entryIdx);
    83394
    84395void executeList1(void);
    85396void executeList0(void);
     
    87398void purgeList1(void);
    88399void purgeList0(void);
    89400
    90 void o1_modifyObjectParam();
    91 void o1_getObjectParam();
    92 void o1_addObjectParam();
    93 void o1_subObjectParam();
    94 void o1_add2ObjectParam();
    95 void o1_sub2ObjectParam();
    96 void o1_compareObjectParam();
    97 void o1_setupObject();
    98 void o1_checkCollision();
    99 void o1_loadVar();
    100 void o1_addVar();
    101 void o1_subVar();
    102 void o1_mulVar();
    103 void o1_divVar();
    104 void o1_compareVar();
    105 void o1_modifyObjectParam2();
    106 void o1_loadMask0();
    107 void o1_unloadMask0();
    108 void o1_addToBgList();
    109 void o1_loadMask1();
    110 void o1_unloadMask1();
    111 void o1_loadMask4();
    112 void o1_unloadMask4();
    113 void o1_addSpriteFilledToBgList();
    114 void o1_op1B();
    115 void o1_label();
    116 void o1_goto();
    117 void o1_gotoIfSup();
    118 void o1_gotoIfSupEqu();
    119 void o1_gotoIfInf();
    120 void o1_gotoIfInfEqu();
    121 void o1_gotoIfEqu();
    122 void o1_gotoIfDiff();
    123 void o1_removeLabel();
    124 void o1_loop();
    125 void o1_startGlobalScript();
    126 void o1_endGlobalScript();
    127 void o1_loadAnim();
    128 void o1_loadBg();
    129 void o1_loadCt();
    130 void o1_loadPart();
    131 void o1_closePart();
    132 void o1_loadNewPrcName();
    133 void o1_requestCheckPendingDataLoad();
    134 void o1_blitAndFade();
    135 void o1_fadeToBlack();
    136 void o1_transformPaletteRange();
    137 void o1_setDefaultMenuColor2();
    138 void o1_palRotate();
    139 void o1_break();
    140 void o1_endScript();
    141 void o1_message();
    142 void o1_loadGlobalVar();
    143 void o1_compareGlobalVar();
    144 void o1_declareFunctionName();
    145 void o1_freePartRange();
    146 void o1_unloadAllMasks();
    147 void o1_setScreenDimensions();
    148 void o1_displayBackground();
    149 void o1_initializeZoneData();
    150 void o1_setZoneDataEntry();
    151 void o1_getZoneDataEntry();
    152 void o1_setDefaultMenuColor();
    153 void o1_allowPlayerInput();
    154 void o1_disallowPlayerInput();
    155 void o1_changeDataDisk();
    156 void o1_loadMusic();
    157 void o1_playMusic();
    158 void o1_fadeOutMusic();
    159 void o1_stopSample();
    160 void o1_op71();
    161 void o1_op72();
    162 void o1_op73();
    163 void o1_playSample();
    164 void o1_playSample();
    165 void o1_disableSystemMenu();
    166 void o1_loadMask5();
    167 void o1_unloadMask5();
    168 
    169 void o2_loadPart();
    170 void o2_addSeqListElement();
    171 void o2_removeSeq();
    172 void o2_playSample();
    173 void o2_playSampleAlt();
    174 void o2_op81();
    175 void o2_op82();
    176 void o2_isSeqRunning();
    177 void o2_gotoIfSupNearest();
    178 void o2_gotoIfSupEquNearest();
    179 void o2_gotoIfInfNearest();
    180 void o2_gotoIfInfEquNearest();
    181 void o2_gotoIfEquNearest();
    182 void o2_gotoIfDiffNearest();
    183 void o2_startObjectScript();
    184 void o2_stopObjectScript();
    185 void o2_op8D();
    186 void o2_addBackground();
    187 void o2_removeBackground();
    188 void o2_loadAbs();
    189 void o2_loadBg();
    190 void o2_wasZoneChecked();
    191 void o2_op9B();
    192 void o2_op9C();
    193 void o2_useBgScroll();
    194 void o2_setAdditionalBgVScroll();
    195 void o2_op9F();
    196 void o2_addGfxElementA0();
    197 void o2_opA1();
    198 void o2_opA2();
    199 void o2_opA3();
    200 void o2_loadMask22();
    201 void o2_unloadMask22();
    202 
    203401} // End of namespace Cine
    204402
    205403#endif
  • engines/cine/rel.cpp

     
    3131
    3232namespace Cine {
    3333
    34 RelObjectScript relTable[NUM_MAX_REL];
     34RawObjectScriptArray relTable; ///< Object script bytecode table
    3535
    36 void resetObjectScriptHead(void) {
    37         objScriptList.next = NULL;
    38         objScriptList.scriptIdx = -1;
    39 }
    40 
    41 void releaseObjectScripts(void) {
    42         prcLinkedListStruct *currentHead = objScriptList.next;
    43 
    44         while (currentHead) {
    45                 prcLinkedListStruct *temp;
    46 
    47                 assert(currentHead);
    48 
    49                 temp = currentHead->next;
    50 
    51                 delete currentHead;
    52 
    53                 currentHead = temp;
    54         }
    55 
    56         resetObjectScriptHead();
    57 }
    58 
     36/*! \todo Is script size of 0 valid?
     37 * \todo Fix script dump code
     38 */
    5939void loadRel(char *pRelName) {
    6040        uint16 numEntry;
    6141        uint16 i;
     42        uint16 size, p1, p2, p3;
    6243        byte *ptr, *dataPtr;
    6344
    6445        checkDataDisk(-1);
    6546
    66         for (i = 0; i < NUM_MAX_REL; i++) {
    67                 if (relTable[i].data) {
    68                         free(relTable[i].data);
    69                         relTable[i].data = NULL;
    70                         relTable[i].size = 0;
    71                 }
    72         }
     47        objectScripts.clear();
     48        relTable.clear();
    7349
    7450        ptr = dataPtr = readBundleFile(findFileInBundle(pRelName));
    7551
     
    7753
    7854        numEntry = READ_BE_UINT16(ptr); ptr += 2;
    7955
    80         assert(numEntry <= NUM_MAX_REL);
    81 
    8256        for (i = 0; i < numEntry; i++) {
    83                 relTable[i].size = READ_BE_UINT16(ptr); ptr += 2;
    84                 relTable[i].obj1Param1 = READ_BE_UINT16(ptr); ptr += 2;
    85                 relTable[i].obj1Param2 = READ_BE_UINT16(ptr); ptr += 2;
    86                 relTable[i].obj2Param = READ_BE_UINT16(ptr); ptr += 2;
    87                 relTable[i].runCount = 0;
     57                size = READ_BE_UINT16(ptr); ptr += 2;
     58                p1 = READ_BE_UINT16(ptr); ptr += 2;
     59                p2 = READ_BE_UINT16(ptr); ptr += 2;
     60                p3 = READ_BE_UINT16(ptr); ptr += 2;
     61                RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3));
     62                assert(tmp);
     63                relTable.push_back(tmp);
    8864        }
    8965
    9066        for (i = 0; i < numEntry; i++) {
    91                 if (relTable[i].size) {
    92                         relTable[i].data = (byte *)malloc(relTable[i].size);
    93 
    94                         assert(relTable[i].data);
    95 
    96                         memcpy(relTable[i].data, ptr, relTable[i].size);
    97                         ptr += relTable[i].size;
     67                size = relTable[i]->size();
     68                // TODO: delete the test?
     69                if (size) {
     70                        relTable[i]->setData(*scriptInfo, ptr);
     71                        ptr += size;
    9872                }
    9973        }
    10074
  • engines/cine/various.cpp

     
    124124//      }
    125125}
    126126
    127 int16 stopObjectScript(int16 entryIdx) {
    128         prcLinkedListStruct *currentHead = &objScriptList;
    129         prcLinkedListStruct *tempHead = currentHead;
    130 
    131         currentHead = tempHead->next;
    132 
    133         while (currentHead) {
    134                 if (currentHead->scriptIdx == entryIdx) {
    135                         currentHead->scriptIdx = -1;
    136                         return 0;
    137                 }
    138 
    139                 currentHead = currentHead->next;
    140         }
    141 
    142         return -1;
    143 }
    144 
    145127void runObjectScript(int16 entryIdx) {
    146         uint16 i;
    147         prcLinkedListStruct *pNewElement;
    148         prcLinkedListStruct *currentHead = &objScriptList;
    149         prcLinkedListStruct *tempHead = currentHead;
    150 
    151         currentHead = tempHead->next;
    152 
    153         while (currentHead) {
    154                 tempHead = currentHead;
    155 
    156                 assert(tempHead);
    157 
    158                 currentHead = tempHead->next;
    159         }
    160 
    161         pNewElement = new prcLinkedListStruct;
    162 
    163         assert(pNewElement);
    164 
    165         pNewElement->next = tempHead->next;
    166         tempHead->next = pNewElement;
    167 
    168         // copy the stack into the script instance
    169         for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
    170                 pNewElement->stack[i] = 0;
    171         }
    172 
    173         pNewElement->compareResult = 0;
    174         pNewElement->scriptPosition = 0;
    175 
    176         pNewElement->scriptPtr = (byte *)relTable[entryIdx].data;
    177         pNewElement->scriptIdx = entryIdx;
    178 
    179         if (g_cine->getGameType() == Cine::GType_OS) {
    180                 pNewElement->localVars[0] = relTable[entryIdx].runCount;
    181                 ++relTable[entryIdx].runCount;
    182         }
    183 
    184         computeScriptStack(pNewElement->scriptPtr, pNewElement->stack, relTable[entryIdx].size);
     128        ScriptPtr tmp(scriptInfo->create(*relTable[entryIdx], entryIdx));
     129        assert(tmp);
     130        objectScripts.push_back(tmp);
    185131}
    186132
    187133void addPlayerCommandMessage(int16 cmd) {
     
    214160
    215161int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
    216162        int16 i;
    217         int16 di = -1;
     163        int16 found = -1;
    218164
    219         for (i = 0; i < NUM_MAX_REL; i++) {
    220                 if (relTable[i].data && relTable[i].obj1Param1 == param1 && relTable[i].obj1Param2 == pSelectedObject->idx) {
     165        for (i = 0; i < (int16)relTable.size(); i++) {
     166                if (relTable[i]->param1() == param1 && relTable[i]->param2() == pSelectedObject->idx) {
    221167                        if (param2 == 1) {
    222                                 di = i;
     168                                found = i;
    223169                        } else if (param2 == 2) {
    224                                 if (relTable[i].obj2Param == pSelectedObject->param) {
    225                                         di = i;
     170                                if (relTable[i]->param3() == pSelectedObject->param) {
     171                                        found = i;
    226172                                }
    227173                        }
    228174                }
    229175
    230                 if (di != -1)
     176                if (found != -1)
    231177                        break;
    232178        }
    233179
    234         return di;
     180        return found;
    235181}
    236182
    237183int16 getObjectUnderCursor(uint16 x, uint16 y) {
     
    302248        return true;
    303249}
    304250
     251/*! \brief Restore script list item from savefile
     252 * \param fHandle Savefile handlem open for reading
     253 * \param isGlobal Restore object or global script?
     254 */
    305255void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) {
    306         int16 i;
     256        ScriptVars localVars, labels;
     257        uint16 compare, pos;
     258        int16 idx;
    307259
    308         prcLinkedListStruct *newElement;
    309         prcLinkedListStruct *currentHead = &globalScriptsHead;
    310         prcLinkedListStruct *tempHead = currentHead;
     260        labels.load(*fHandle);
     261        localVars.load(*fHandle);
    311262
    312         currentHead = tempHead->next;
     263        compare = fHandle->readUint16BE();
     264        pos = fHandle->readUint16BE();
     265        idx = fHandle->readUint16BE();
    313266
    314         while (currentHead) {
    315                 tempHead = currentHead;
    316                 currentHead = tempHead->next;
     267        // no way to reinitialize these
     268        if (idx < 0) {
     269                return;
    317270        }
    318271
    319         newElement = new prcLinkedListStruct;
    320 
    321         newElement->next = tempHead->next;
    322         tempHead->next = newElement;
    323 
    324         for (i = 0; i < SCRIPT_STACK_SIZE; i++)
    325                 newElement->stack[i] = fHandle->readUint16BE();
    326 
    327         newElement->localVars.load(*fHandle);
    328 
    329         newElement->compareResult = fHandle->readUint16BE();
    330         newElement->scriptPosition = fHandle->readUint16BE();
    331         newElement->scriptIdx = fHandle->readUint16BE();
    332 
    333         if (isGlobal)
    334                 newElement->scriptPtr = scriptTable[newElement->scriptIdx].ptr;
    335         else
    336                 newElement->scriptPtr = (byte *)relTable[newElement->scriptIdx].data;
     272        // original code loaded everything into globalScripts, this should be
     273        // the correct behavior
     274        if (isGlobal) {
     275                ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx, labels, localVars, compare, pos));
     276                assert(tmp);
     277                globalScripts.push_back(tmp);
     278        } else {
     279                ScriptPtr tmp(scriptInfo->create(*relTable[idx], idx, labels, localVars, compare, pos));
     280                assert(tmp);
     281                objectScripts.push_back(tmp);
     282        }
    337283}
    338284
    339285void loadOverlayFromSave(Common::InSaveFile *fHandle) {
     
    370316        currentHead->previous = newElement;
    371317}
    372318
    373 void setupScriptList(bool isGlobal) {
    374         prcLinkedListStruct *currentHead;
    375 
    376         if (isGlobal)
    377                 currentHead = globalScriptsHead.next;
    378         else
    379                 currentHead = objScriptList.next;
    380 
    381         while (currentHead) {
    382                 if (isGlobal)
    383                         currentHead->scriptPtr = scriptTable[currentHead->scriptIdx].ptr;
    384                 else
    385                         currentHead->scriptPtr = (byte *)relTable[currentHead->scriptIdx].data;
    386                 currentHead = currentHead->next;
    387         }
    388 }
    389 
    390319bool CineEngine::makeLoad(char *saveName) {
    391320        int16 i;
    392321        int16 size;
     322        bool oldSave = false;
    393323        Common::InSaveFile *fHandle;
    394324
    395325        fHandle = g_saveFileMan->openForLoading(saveName);
     
    408338        // if (g_cine->getGameType() == Cine::GType_OS) {
    409339        //      freeUnkList();
    410340        // }
    411         freePrcLinkedList();
    412         releaseObjectScripts();
    413341        freeBgIncrustList();
    414342        closePart();
    415343
    416         for (i = 0; i < NUM_MAX_REL; i++) {
    417                 if (relTable[i].data) {
    418                         free(relTable[i].data);
    419                         relTable[i].data = NULL;
    420                         relTable[i].size = 0;
    421                         relTable[i].obj1Param1 = 0;
    422                         relTable[i].obj1Param2 = 0;
    423                         relTable[i].obj2Param = 0;
    424                 }
    425         }
     344        objectScripts.clear();
     345        globalScripts.clear();
     346        relTable.clear();
     347        scriptTable.clear();
    426348
    427         for (i = 0; i < NUM_MAX_SCRIPT; i++) {
    428                 if (scriptTable[i].ptr) {
    429                         free(scriptTable[i].ptr);
    430                         scriptTable[i].ptr = NULL;
    431                         scriptTable[i].size = 0;
    432                 }
    433         }
    434 
    435349        for (i = 0; i < NUM_MAX_MESSAGE; i++) {
    436350                messageTable[i].len = 0;
    437351
     
    491405        fHandle->read(currentBgName[0], 13);
    492406        fHandle->read(currentCtName, 13);
    493407
     408        checkDataDisk(currentDisk);
     409
     410        if (strlen(currentPartName)) {
     411                loadPart(currentPartName);
     412        }
     413
     414        if (strlen(currentPrcName)) {
     415                loadPrc(currentPrcName);
     416        }
     417
     418        if (strlen(currentRelName)) {
     419                loadRel(currentRelName);
     420        }
     421
    494422        fHandle->readUint16BE();
    495423        fHandle->readUint16BE();
    496424
     
    539467
    540468        fHandle->readUint16BE();
    541469        fHandle->readUint16BE();
     470       
     471        animDataTable[0].width = fHandle->readUint16BE();
     472        animDataTable[0].var1 = fHandle->readUint16BE();
     473        animDataTable[0].bpp = fHandle->readUint16BE();
     474        animDataTable[0].height = fHandle->readUint16BE();
     475        animDataTable[0].ptr1 = NULL;
     476        animDataTable[0].ptr2 = NULL;
     477        animDataTable[0].fileIdx = fHandle->readSint16BE();
     478        animDataTable[0].frameIdx = fHandle->readSint16BE();
     479        fHandle->read(animDataTable[0].name, 10);
    542480
    543         for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
     481        // ugly hack that may not work
     482        // guess whether we're loading 0.10.0 buggy save or original save
     483        // original save has 8 extra almost meaningless bytes before fileIdx,
     484        // therefore name[8] will be non-zero
     485        // 9-character part name in 0.10.0 means BIG trouble, luckily
     486        // that can't happen in unmodified game
     487        if (animDataTable[0].name[8] != 0) {
     488                oldSave = true;
     489                animDataTable[0].refresh = (animDataTable[0].fileIdx ||
     490                        animDataTable[0].frameIdx) ? 1 : 0;
     491                Common::MemoryReadStream readS((byte*)animDataTable[0].name+4, 10);
     492                animDataTable[0].fileIdx = readS.readUint16BE();
     493                animDataTable[0].frameIdx = readS.readUint16BE();
     494                animDataTable[0].name[0] = animDataTable[0].name[8];
     495                animDataTable[0].name[1] = animDataTable[0].name[9];
     496                fHandle->read(animDataTable[0].name+2, 8);
     497        } else {
     498                animDataTable[0].refresh = (fHandle->readByte() != 0);
     499        }
     500
     501        for (i = 1; i < NUM_MAX_ANIMDATA; i++) {
    544502                animDataTable[i].width = fHandle->readUint16BE();
    545503                animDataTable[i].var1 = fHandle->readUint16BE();
    546504                animDataTable[i].bpp = fHandle->readUint16BE();
    547505                animDataTable[i].height = fHandle->readUint16BE();
     506                if(oldSave) {
     507                        animDataTable[i].refresh = (fHandle->readUint32BE() != 0);
     508                        fHandle->readUint32BE();
     509                }
    548510                animDataTable[i].ptr1 = NULL;
    549511                animDataTable[i].ptr2 = NULL;
    550512                animDataTable[i].fileIdx = fHandle->readSint16BE();
    551513                animDataTable[i].frameIdx = fHandle->readSint16BE();
    552514                fHandle->read(animDataTable[i].name, 10);
    553                 animDataTable[i].refresh = (fHandle->readByte() != 0);
     515                if(!oldSave) {
     516                        animDataTable[i].refresh = (fHandle->readByte() != 0);
     517                }
    554518        }
    555519
    556520        // TODO: handle screen params (really required ?)
     
    583547
    584548        delete fHandle;
    585549
    586         checkDataDisk(currentDisk);
    587 
    588         if (strlen(currentPartName)) {
    589                 loadPart(currentPartName);
    590         }
    591 
    592         if (strlen(currentPrcName)) {
    593                 loadPrc(currentPrcName);
    594                 setupScriptList(true);
    595         }
    596 
    597         if (strlen(currentRelName)) {
    598                 loadRel(currentRelName);
    599                 setupScriptList(false);
    600         }
    601 
    602550        if (strlen(currentMsgName)) {
    603551                loadMsg(currentMsgName);
    604552        }
     
    706654                fHandle->writeUint16BE(animDataTable[i].var1);
    707655                fHandle->writeUint16BE(animDataTable[i].bpp);
    708656                fHandle->writeUint16BE(animDataTable[i].height);
     657                // This file format looks like Delphine guys
     658                // hacked it together 10 minutes before release deadline...
     659                // Just because I write pointers to a file doesn't mean
     660                // anyone should actually read those values back!
     661                fHandle->writeUint32BE((uint32)animDataTable[i].ptr1);
     662                fHandle->writeUint32BE((uint32)animDataTable[i].ptr2);
    709663                fHandle->writeSint16BE(animDataTable[i].fileIdx);
    710664                fHandle->writeSint16BE(animDataTable[i].frameIdx);
    711665                fHandle->write(animDataTable[i].name, 10);
    712 
    713                 // Horrifyingly, cinE used to dump the entire struct to the
    714                 // save file, including the data pointers. While these pointers
    715                 // would be invalid after loading, the loadResourcesFromSave()
    716                 // function would still test if ptr1 was non-NULL, presumably
    717                 // to see if the object was present in the room.
    718 
    719                 fHandle->writeByte(animDataTable[i].ptr1 ? 1 : 0);
    720666        }
    721667
    722668        fHandle->writeUint16BE(0);  // Screen params, unhandled
     
    727673        fHandle->writeUint16BE(0);
    728674
    729675        {
    730                 int16 numScript = 0;
    731                 prcLinkedListStruct *currentHead = globalScriptsHead.next;
    732 
    733                 while (currentHead) {
    734                         numScript++;
    735                         currentHead = currentHead->next;
     676                ScriptList::iterator it;
     677                fHandle->writeUint16BE(globalScripts.size());
     678                for (it = globalScripts.begin(); it != globalScripts.end(); ++it) {
     679                        (*it)->save(*fHandle);
    736680                }
    737681
    738                 fHandle->writeUint16BE(numScript);
    739 
    740                 // actual save
    741                 currentHead = globalScriptsHead.next;
    742 
    743                 while (currentHead) {
    744                         for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
    745                                 fHandle->writeUint16BE(currentHead->stack[i]);
    746                         }
    747 
    748                         currentHead->localVars.save(*fHandle);
    749 
    750                         fHandle->writeUint16BE(currentHead->compareResult);
    751                         fHandle->writeUint16BE(currentHead->scriptPosition);
    752                         fHandle->writeUint16BE(currentHead->scriptIdx);
    753 
    754                         currentHead = currentHead->next;
     682                fHandle->writeUint16BE(objectScripts.size());
     683                for (it = objectScripts.begin(); it != objectScripts.end(); ++it) {
     684                        (*it)->save(*fHandle);
    755685                }
    756686        }
    757687
    758688        {
    759689                int16 numScript = 0;
    760                 prcLinkedListStruct *currentHead = objScriptList.next;
    761 
    762                 while (currentHead) {
    763                         numScript++;
    764                         currentHead = currentHead->next;
    765                 }
    766 
    767                 fHandle->writeUint16BE(numScript);
    768 
    769                 // actual save
    770                 currentHead = objScriptList.next;
    771 
    772                 while (currentHead) {
    773                         for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
    774                                 fHandle->writeUint16BE(currentHead->stack[i]);
    775                         }
    776 
    777                         currentHead->localVars.save(*fHandle);
    778 
    779                         fHandle->writeUint16BE(currentHead->compareResult);
    780                         fHandle->writeUint16BE(currentHead->scriptPosition);
    781                         fHandle->writeUint16BE(currentHead->scriptIdx);
    782 
    783                         currentHead = currentHead->next;
    784                 }
    785         }
    786 
    787         {
    788                 int16 numScript = 0;
    789690                overlayHeadElement *currentHead = overlayHead.next;
    790691
    791692                while (currentHead) {
     
    20751976
    20761977void checkForPendingDataLoad(void) {
    20771978        if (newPrcName[0] != 0) {
    2078                 freePrcLinkedList();
    2079                 resetglobalScriptsHead();
    2080 
    20811979                loadPrc(newPrcName);
    20821980
    20831981                strcpy(currentPrcName, newPrcName);
     
    20871985        }
    20881986
    20891987        if (newRelName[0] != 0) {
    2090                 releaseObjectScripts();
    2091                 resetObjectScriptHead();
    2092 
    20931988                loadRel(newRelName);
    20941989
    20951990                strcpy(currentRelName, newRelName);
  • engines/cine/prc.h

     
    2828
    2929namespace Cine {
    3030
    31 struct prcLinkedListStruct {
    32         struct prcLinkedListStruct *next;
    33         int16 stack[SCRIPT_STACK_SIZE];
    34         ScriptVars localVars;
    35         uint16 compareResult;
    36         uint16 scriptPosition;
    37         byte *scriptPtr;
    38         int16 scriptIdx;
    39 };
     31extern ScriptList globalScripts;
     32extern ScriptList objectScripts;
    4033
    41 extern prcLinkedListStruct globalScriptsHead;
    42 extern prcLinkedListStruct objScriptList;
    43 
    44 void resetglobalScriptsHead(void);
    45 void freePrcLinkedList(void);
    4634void loadPrc(const char *pPrcName);
    4735
    4836} // End of namespace Cine
  • engines/cine/script.cpp

     
    2323 *
    2424 */
    2525
     26/*! \file
     27 * Script interpreter file
     28 */
    2629
    2730#include "common/endian.h"
    2831
     
    3134#include "cine/object.h"
    3235#include "cine/sound.h"
    3336#include "cine/various.h"
     37#include "cine/script.h"
    3438
    3539namespace Cine {
    3640
    37 prcLinkedListStruct *_currentScriptElement;
    38 byte *_currentScriptPtr;
    39 uint16 _currentScriptParams;
    40 uint16 _currentPosition;
    41 uint16 _currentLine;
    42 uint16 _closeScript;
     41uint16 compareVars(int16 a, int16 b);
     42void palRotate(byte a, byte b, byte c);
     43void removeSeq(uint16 param1, uint16 param2, uint16 param3);
     44uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
     45void addGfxElementA0(int16 param1, int16 param2);
    4346
    44 struct Opcode {
    45         void (*proc)();
    46         const char *args;
     47const Opcode FWScript::_opcodeTable[] = {
     48        /* 00 */
     49        { &FWScript::o1_modifyObjectParam, "bbw" },
     50        { &FWScript::o1_getObjectParam, "bbb" },
     51        { &FWScript::o1_addObjectParam, "bbw" },
     52        { &FWScript::o1_subObjectParam, "bbw" },
     53        /* 04 */
     54        { &FWScript::o1_add2ObjectParam, "bbw" },
     55        { &FWScript::o1_sub2ObjectParam, "bbw" },
     56        { &FWScript::o1_compareObjectParam, "bbw" },
     57        { &FWScript::o1_setupObject, "bwwww" },
     58        /* 08 */
     59        { &FWScript::o1_checkCollision, "bwwww" },
     60        { &FWScript::o1_loadVar, "bc" },
     61        { &FWScript::o1_addVar, "bc" },
     62        { &FWScript::o1_subVar, "bc" },
     63        /* 0C */
     64        { &FWScript::o1_mulVar, "bc" },
     65        { &FWScript::o1_divVar, "bc" },
     66        { &FWScript::o1_compareVar, "bc" },
     67        { &FWScript::o1_modifyObjectParam2, "bbb" },
     68        /* 10 */
     69        { 0, 0 },
     70        { 0, 0 },
     71        { 0, 0 },
     72        { &FWScript::o1_loadMask0, "b" },
     73        /* 14 */
     74        { &FWScript::o1_unloadMask0, "b" },
     75        { &FWScript::o1_addToBgList, "b" },
     76        { &FWScript::o1_loadMask1, "b" },
     77        { &FWScript::o1_unloadMask1, "b" },
     78        /* 18 */
     79        { &FWScript::o1_loadMask4, "b" },
     80        { &FWScript::o1_unloadMask4, "b" },
     81        { &FWScript::o1_addSpriteFilledToBgList, "b" },
     82        { &FWScript::o1_op1B, "" },
     83        /* 1C */
     84        { 0, 0 },
     85        { &FWScript::o1_label, "l" },
     86        { &FWScript::o1_goto, "b" },
     87        { &FWScript::o1_gotoIfSup, "b" },
     88        /* 20 */
     89        { &FWScript::o1_gotoIfSupEqu, "b" },
     90        { &FWScript::o1_gotoIfInf, "b" },
     91        { &FWScript::o1_gotoIfInfEqu, "b" },
     92        { &FWScript::o1_gotoIfEqu, "b" },
     93        /* 24 */
     94        { &FWScript::o1_gotoIfDiff, "b" },
     95        { &FWScript::o1_removeLabel, "b" },
     96        { &FWScript::o1_loop, "bb" },
     97        { 0, 0 },
     98        /* 28 */
     99        { 0, 0 },
     100        { 0, 0 },
     101        { 0, 0 },
     102        { 0, 0 },
     103        /* 2C */
     104        { 0, 0 },
     105        { 0, 0 },
     106        { 0, 0 },
     107        { 0, 0 },
     108        /* 30 */
     109        { 0, 0 },
     110        { &FWScript::o1_startGlobalScript, "b" },
     111        { &FWScript::o1_endGlobalScript, "b" },
     112        { 0, 0 },
     113        /* 34 */
     114        { 0, 0 },
     115        { 0, 0 },
     116        { 0, 0 },
     117        { 0, 0 },
     118        /* 38 */
     119        { 0, 0 },
     120        { 0, 0 },
     121        { 0, 0 },
     122        { &FWScript::o1_loadAnim, "s" },
     123        /* 3C */
     124        { &FWScript::o1_loadBg, "s" },
     125        { &FWScript::o1_loadCt, "s" },
     126        { 0, 0 },
     127        { &FWScript::o1_loadPart, "s" },
     128        /* 40 */
     129        { &FWScript::o1_closePart, "" },
     130        { &FWScript::o1_loadNewPrcName, "bs" },
     131        { &FWScript::o1_requestCheckPendingDataLoad, "" },
     132        { 0, 0 },
     133        /* 44 */
     134        { 0, 0 },
     135        { &FWScript::o1_blitAndFade, "" },
     136        { &FWScript::o1_fadeToBlack, "" },
     137        { &FWScript::o1_transformPaletteRange, "bbwww" },
     138        /* 48 */
     139        { 0, 0 },
     140        { &FWScript::o1_setDefaultMenuColor2, "b" },
     141        { &FWScript::o1_palRotate, "bbb" },
     142        { 0, 0 },
     143        /* 4C */
     144        { 0, 0 },
     145        { 0, 0 },
     146        { 0, 0 },
     147        { &FWScript::o1_break, "" },
     148        /* 50 */
     149        { &FWScript::o1_endScript, "x" },
     150        { &FWScript::o1_message, "bwwww" },
     151        { &FWScript::o1_loadGlobalVar, "bc" },
     152        { &FWScript::o1_compareGlobalVar, "bc" },
     153        /* 54 */
     154        { 0, 0 },
     155        { 0, 0 },
     156        { 0, 0 },
     157        { 0, 0 },
     158        /* 58 */
     159        { 0, 0 },
     160        { &FWScript::o1_declareFunctionName, "s" },
     161        { &FWScript::o1_freePartRange, "bb" },
     162        { &FWScript::o1_unloadAllMasks, "" },
     163        // 5C */
     164        { 0, 0 },
     165        { 0, 0 },
     166        { 0, 0 },
     167        { 0, 0 },
     168        /* 60 */
     169        { 0, 0 },
     170        { 0, 0 },
     171        { 0, 0 },
     172        { &FWScript::o1_setScreenDimensions, "wwww" },
     173        /* 64 */
     174        { &FWScript::o1_displayBackground, "" },
     175        { &FWScript::o1_initializeZoneData, "" },
     176        { &FWScript::o1_setZoneDataEntry, "bw" },
     177        { &FWScript::o1_getZoneDataEntry, "bb" },
     178        /* 68 */
     179        { &FWScript::o1_setDefaultMenuColor, "b" },
     180        { &FWScript::o1_allowPlayerInput, "" },
     181        { &FWScript::o1_disallowPlayerInput, "" },
     182        { &FWScript::o1_changeDataDisk, "b" },
     183        /* 6C */
     184        { 0, 0 },
     185        { &FWScript::o1_loadMusic, "s" },
     186        { &FWScript::o1_playMusic, "" },
     187        { &FWScript::o1_fadeOutMusic, "" },
     188        /* 70 */
     189        { &FWScript::o1_stopSample, "" },
     190        { &FWScript::o1_op71, "bw" },
     191        { &FWScript::o1_op72, "wbw" },
     192        { &FWScript::o1_op73, "wbw" },
     193        /* 74 */
     194        { 0, 0 },
     195        { 0, 0 },
     196        { 0, 0 },
     197        { &FWScript::o1_playSample, "bbwbww" },
     198        /* 78 */
     199        { &FWScript::o1_playSample, "bbwbww" },
     200        { &FWScript::o1_disableSystemMenu, "b" },
     201        { &FWScript::o1_loadMask5, "b" },
     202        { &FWScript::o1_unloadMask5, "b" }
    47203};
     204const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable);
    48205
    49 const Opcode *_opcodeTable;
    50 int _numOpcodes;
    51206
    52 void setupOpcodes() {
    53         static const Opcode opcodeTableFW[] = {
    54                 /* 00 */
    55                 { o1_modifyObjectParam, "bbw" },
    56                 { o1_getObjectParam, "bbb" },
    57                 { o1_addObjectParam, "bbw" },
    58                 { o1_subObjectParam, "bbw" },
    59                 /* 04 */
    60                 { o1_add2ObjectParam, "bbw" },
    61                 { o1_sub2ObjectParam, "bbw" },
    62                 { o1_compareObjectParam, "bbw" },
    63                 { o1_setupObject, "bwwww" },
    64                 /* 08 */
    65                 { o1_checkCollision, "bwwww" },
    66                 { o1_loadVar, "bc" },
    67                 { o1_addVar, "bc" },
    68                 { o1_subVar, "bc" },
    69                 /* 0C */
    70                 { o1_mulVar, "bc" },
    71                 { o1_divVar, "bc" },
    72                 { o1_compareVar, "bc" },
    73                 { o1_modifyObjectParam2, "bbb" },
    74                 /* 10 */
    75                 { 0, 0 },
    76                 { 0, 0 },
    77                 { 0, 0 },
    78                 { o1_loadMask0, "b" },
    79                 /* 14 */
    80                 { o1_unloadMask0, "b" },
    81                 { o1_addToBgList, "b" },
    82                 { o1_loadMask1, "b" },
    83                 { o1_unloadMask1, "b" },
    84                 /* 18 */
    85                 { o1_loadMask4, "b" },
    86                 { o1_unloadMask4, "b" },
    87                 { o1_addSpriteFilledToBgList, "b" },
    88                 { o1_op1B, "" },
    89                 /* 1C */
    90                 { 0, 0 },
    91                 { o1_label, "l" },
    92                 { o1_goto, "b" },
    93                 { o1_gotoIfSup, "b" },
    94                 /* 20 */
    95                 { o1_gotoIfSupEqu, "b" },
    96                 { o1_gotoIfInf, "b" },
    97                 { o1_gotoIfInfEqu, "b" },
    98                 { o1_gotoIfEqu, "b" },
    99                 /* 24 */
    100                 { o1_gotoIfDiff, "b" },
    101                 { o1_removeLabel, "b" },
    102                 { o1_loop, "bb" },
    103                 { 0, 0 },
    104                 /* 28 */
    105                 { 0, 0 },
    106                 { 0, 0 },
    107                 { 0, 0 },
    108                 { 0, 0 },
    109                 /* 2C */
    110                 { 0, 0 },
    111                 { 0, 0 },
    112                 { 0, 0 },
    113                 { 0, 0 },
    114                 /* 30 */
    115                 { 0, 0 },
    116                 { o1_startGlobalScript, "b" },
    117                 { o1_endGlobalScript, "b" },
    118                 { 0, 0 },
    119                 /* 34 */
    120                 { 0, 0 },
    121                 { 0, 0 },
    122                 { 0, 0 },
    123                 { 0, 0 },
    124                 /* 38 */
    125                 { 0, 0 },
    126                 { 0, 0 },
    127                 { 0, 0 },
    128                 { o1_loadAnim, "s" },
    129                 /* 3C */
    130                 { o1_loadBg, "s" },
    131                 { o1_loadCt, "s" },
    132                 { 0, 0 },
    133                 { o1_loadPart, "s" },
    134                 /* 40 */
    135                 { o1_closePart, "" },
    136                 { o1_loadNewPrcName, "bs" },
    137                 { o1_requestCheckPendingDataLoad, "" },
    138                 { 0, 0 },
    139                 /* 44 */
    140                 { 0, 0 },
    141                 { o1_blitAndFade, "" },
    142                 { o1_fadeToBlack, "" },
    143                 { o1_transformPaletteRange, "bbwww" },
    144                 /* 48 */
    145                 { 0, 0 },
    146                 { o1_setDefaultMenuColor2, "b" },
    147                 { o1_palRotate, "bbb" },
    148                 { 0, 0 },
    149                 /* 4C */
    150                 { 0, 0 },
    151                 { 0, 0 },
    152                 { 0, 0 },
    153                 { o1_break, "" },
    154                 /* 50 */
    155                 { o1_endScript, "x" },
    156                 { o1_message, "bwwww" },
    157                 { o1_loadGlobalVar, "bc" },
    158                 { o1_compareGlobalVar, "bc" },
    159                 /* 54 */
    160                 { 0, 0 },
    161                 { 0, 0 },
    162                 { 0, 0 },
    163                 { 0, 0 },
    164                 /* 58 */
    165                 { 0, 0 },
    166                 { o1_declareFunctionName, "s" },
    167                 { o1_freePartRange, "bb" },
    168                 { o1_unloadAllMasks, "" },
    169                 // 5C */
    170                 { 0, 0 },
    171                 { 0, 0 },
    172                 { 0, 0 },
    173                 { 0, 0 },
    174                 /* 60 */
    175                 { 0, 0 },
    176                 { 0, 0 },
    177                 { 0, 0 },
    178                 { o1_setScreenDimensions, "wwww" },
    179                 /* 64 */
    180                 { o1_displayBackground, "" },
    181                 { o1_initializeZoneData, "" },
    182                 { o1_setZoneDataEntry, "bw" },
    183                 { o1_getZoneDataEntry, "bb" },
    184                 /* 68 */
    185                 { o1_setDefaultMenuColor, "b" },
    186                 { o1_allowPlayerInput, "" },
    187                 { o1_disallowPlayerInput, "" },
    188                 { o1_changeDataDisk, "b" },
    189                 /* 6C */
    190                 { 0, 0 },
    191                 { o1_loadMusic, "s" },
    192                 { o1_playMusic, "" },
    193                 { o1_fadeOutMusic, "" },
    194                 /* 70 */
    195                 { o1_stopSample, "" },
    196                 { o1_op71, "bw" },
    197                 { o1_op72, "wbw" },
    198                 { o1_op73, "wbw" },
    199                 /* 74 */
    200                 { 0, 0 },
    201                 { 0, 0 },
    202                 { 0, 0 },
    203                 { o1_playSample, "bbwbww" },
    204                 /* 78 */
    205                 { o1_playSample, "bbwbww" },
    206                 { o1_disableSystemMenu, "b" },
    207                 { o1_loadMask5, "b" },
    208                 { o1_unloadMask5, "b" }
    209         };
     207const Opcode OSScript::_opcodeTable[] = {
     208        /* 00 */
     209        { &FWScript::o1_modifyObjectParam, "bbw" },
     210        { &FWScript::o1_getObjectParam, "bbb" },
     211        { &FWScript::o1_addObjectParam, "bbw" },
     212        { &FWScript::o1_subObjectParam, "bbw" },
     213        /* 04 */
     214        { &FWScript::o1_add2ObjectParam, "bbw" },
     215        { &FWScript::o1_sub2ObjectParam, "bbw" },
     216        { &FWScript::o1_compareObjectParam, "bbw" },
     217        { &FWScript::o1_setupObject, "bwwww" },
     218        /* 08 */
     219        { &FWScript::o1_checkCollision, "bwwww" },
     220        { &FWScript::o1_loadVar, "bc" },
     221        { &FWScript::o1_addVar, "bc" },
     222        { &FWScript::o1_subVar, "bc" },
     223        /* 0C */
     224        { &FWScript::o1_mulVar, "bc" },
     225        { &FWScript::o1_divVar, "bc" },
     226        { &FWScript::o1_compareVar, "bc" },
     227        { &FWScript::o1_modifyObjectParam2, "bbb" },
     228        /* 10 */
     229        { 0, 0 },
     230        { 0, 0 },
     231        { 0, 0 },
     232        { &FWScript::o1_loadMask0, "b" },
     233        /* 14 */
     234        { &FWScript::o1_unloadMask0, "b" },
     235        { &FWScript::o1_addToBgList, "b" },
     236        { &FWScript::o1_loadMask1, "b" },
     237        { &FWScript::o1_unloadMask1, "b" },
     238        /* 18 */
     239        { &FWScript::o1_loadMask4, "b" },
     240        { &FWScript::o1_unloadMask4, "b" },
     241        { &FWScript::o1_addSpriteFilledToBgList, "b" },
     242        { &FWScript::o1_op1B, "" },
     243        /* 1C */
     244        { 0, 0 },
     245        { &FWScript::o1_label, "l" },
     246        { &FWScript::o1_goto, "b" },
     247        { &FWScript::o1_gotoIfSup, "b" },
     248        /* 20 */
     249        { &FWScript::o1_gotoIfSupEqu, "b" },
     250        { &FWScript::o1_gotoIfInf, "b" },
     251        { &FWScript::o1_gotoIfInfEqu, "b" },
     252        { &FWScript::o1_gotoIfEqu, "b" },
     253        /* 24 */
     254        { &FWScript::o1_gotoIfDiff, "b" },
     255        { &FWScript::o1_removeLabel, "b" },
     256        { &FWScript::o1_loop, "bb" },
     257        { 0, 0 },
     258        /* 28 */
     259        { 0, 0 },
     260        { 0, 0 },
     261        { 0, 0 },
     262        { 0, 0 },
     263        /* 2C */
     264        { 0, 0 },
     265        { 0, 0 },
     266        { 0, 0 },
     267        { 0, 0 },
     268        /* 30 */
     269        { 0, 0 },
     270        { &FWScript::o1_startGlobalScript, "b" },
     271        { &FWScript::o1_endGlobalScript, "b" },
     272        { 0, 0 },
     273        /* 34 */
     274        { 0, 0 },
     275        { 0, 0 },
     276        { 0, 0 },
     277        { 0, 0 },
     278        /* 38 */
     279        { 0, 0 },
     280        { 0, 0 },
     281        { 0, 0 },
     282        { &FWScript::o1_loadAnim, "s" },
     283        /* 3C */
     284        { &FWScript::o1_loadBg, "s" },
     285        { &FWScript::o1_loadCt, "s" },
     286        { 0, 0 },
     287        { &FWScript::o2_loadPart, "s" },
     288        /* 40 */
     289        { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
     290        { &FWScript::o1_loadNewPrcName, "bs" },
     291        { &FWScript::o1_requestCheckPendingDataLoad, "" },
     292        { 0, 0 },
     293        /* 44 */
     294        { 0, 0 },
     295        { &FWScript::o1_blitAndFade, "" },
     296        { &FWScript::o1_fadeToBlack, "" },
     297        { &FWScript::o1_transformPaletteRange, "bbwww" },
     298        /* 48 */
     299        { 0, 0 },
     300        { &FWScript::o1_setDefaultMenuColor2, "b" },
     301        { &FWScript::o1_palRotate, "bbb" },
     302        { 0, 0 },
     303        /* 4C */
     304        { 0, 0 },
     305        { 0, 0 },
     306        { 0, 0 },
     307        { &FWScript::o1_break, "" },
     308        /* 50 */
     309        { &FWScript::o1_endScript, "x" },
     310        { &FWScript::o1_message, "bwwww" },
     311        { &FWScript::o1_loadGlobalVar, "bc" },
     312        { &FWScript::o1_compareGlobalVar, "bc" },
     313        /* 54 */
     314        { 0, 0 },
     315        { 0, 0 },
     316        { 0, 0 },
     317        { 0, 0 },
     318        /* 58 */
     319        { 0, 0 },
     320        { &FWScript::o1_declareFunctionName, "s" },
     321        { &FWScript::o1_freePartRange, "bb" },
     322        { &FWScript::o1_unloadAllMasks, "" },
     323        // 5C */
     324        { 0, 0 },
     325        { 0, 0 },
     326        { 0, 0 },
     327        { 0, 0 },
     328        /* 60 */
     329        { 0, 0 },
     330        { 0, 0 },
     331        { 0, 0 },
     332        { &FWScript::o1_setScreenDimensions, "wwww" },
     333        /* 64 */
     334        { &FWScript::o1_displayBackground, "" },
     335        { &FWScript::o1_initializeZoneData, "" },
     336        { &FWScript::o1_setZoneDataEntry, "bw" },
     337        { &FWScript::o1_getZoneDataEntry, "bb" },
     338        /* 68 */
     339        { &FWScript::o1_setDefaultMenuColor, "b" },
     340        { &FWScript::o1_allowPlayerInput, "" },
     341        { &FWScript::o1_disallowPlayerInput, "" },
     342        { &FWScript::o1_changeDataDisk, "b" },
     343        /* 6C */
     344        { 0, 0 },
     345        { &FWScript::o1_loadMusic, "s" },
     346        { &FWScript::o1_playMusic, "" },
     347        { &FWScript::o1_fadeOutMusic, "" },
     348        /* 70 */
     349        { &FWScript::o1_stopSample, "" },
     350        { &FWScript::o1_op71, "bw" },
     351        { &FWScript::o1_op72, "wbw" },
     352        { &FWScript::o1_op72, "wbw" },
     353        /* 74 */
     354        { 0, 0 },
     355        { 0, 0 },
     356        { 0, 0 },
     357        { &FWScript::o2_playSample, "bbwbww" },
     358        /* 78 */
     359        { &FWScript::o2_playSampleAlt, "bbwbww" },
     360        { &FWScript::o1_disableSystemMenu, "b" },
     361        { &FWScript::o1_loadMask5, "b" },
     362        { &FWScript::o1_unloadMask5, "b" },
     363        /* 7C */
     364        { 0, 0 },
     365        { 0, 0 },
     366        { 0, 0 },
     367        { &FWScript::o2_addSeqListElement, "bbbbwww" },
     368        /* 80 */
     369        { &FWScript::o2_removeSeq, "bb" },
     370        { &FWScript::o2_op81, "" },
     371        { &FWScript::o2_op82, "bbw" },
     372        { &FWScript::o2_isSeqRunning, "bb" },
     373        /* 84 */
     374        { &FWScript::o2_gotoIfSupNearest, "b" },
     375        { &FWScript::o2_gotoIfSupEquNearest, "b" },
     376        { &FWScript::o2_gotoIfInfNearest, "b" },
     377        { &FWScript::o2_gotoIfInfEquNearest, "b" },
     378        /* 88 */
     379        { &FWScript::o2_gotoIfEquNearest, "b" },
     380        { &FWScript::o2_gotoIfDiffNearest, "b" },
     381        { 0, 0 },
     382        { &FWScript::o2_startObjectScript, "b" },
     383        /* 8C */
     384        { &FWScript::o2_stopObjectScript, "b" },
     385        { &FWScript::o2_op8D, "wwwwwwww" },
     386        { &FWScript::o2_addBackground, "bs" },
     387        { &FWScript::o2_removeBackground, "b" },
     388        /* 90 */
     389        { &FWScript::o2_loadAbs, "bs" },
     390        { &FWScript::o2_loadBg, "b" },
     391        { 0, 0 },
     392        { 0, 0 },
     393        /* 94 */
     394        { 0, 0 },
     395        { &FWScript::o1_changeDataDisk, "b" },
     396        { 0, 0 },
     397        { 0, 0 },
     398        /* 98 */
     399        { 0, 0 },
     400        { 0, 0 },
     401        { &FWScript::o2_wasZoneChecked, "" },
     402        { &FWScript::o2_op9B, "wwwwwwww" },
     403        /* 9C */
     404        { &FWScript::o2_op9C, "wwww" },
     405        { &FWScript::o2_useBgScroll, "b" },
     406        { &FWScript::o2_setAdditionalBgVScroll, "c" },
     407        { &FWScript::o2_op9F, "ww" },
     408        /* A0 */
     409        { &FWScript::o2_addGfxElementA0, "ww" },
     410        { &FWScript::o2_opA1, "ww" },
     411        { &FWScript::o2_opA2, "ww" },
     412        { &FWScript::o2_opA3, "ww" },
     413        /* A4 */
     414        { &FWScript::o2_loadMask22, "b" },
     415        { &FWScript::o2_unloadMask22, "b" },
     416        { 0, 0 },
     417        { 0, 0 },
     418        /* A8 */
     419        { 0, 0 },
     420        { &FWScript::o1_changeDataDisk, "b" }
     421};
     422const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable);
    210423
    211         // TODO: We need to verify the Operation Stealth opcodes.
     424FWScriptInfo *scriptInfo; ///< Script factory
     425RawScriptArray scriptTable; ///< Table of script bytecode
    212426
    213         static const Opcode opcodeTableOS[] = {
    214                 /* 00 */
    215                 { o1_modifyObjectParam, "bbw" },
    216                 { o1_getObjectParam, "bbb" },
    217                 { o1_addObjectParam, "bbw" },
    218                 { o1_subObjectParam, "bbw" },
    219                 /* 04 */
    220                 { o1_add2ObjectParam, "bbw" },
    221                 { o1_sub2ObjectParam, "bbw" },
    222                 { o1_compareObjectParam, "bbw" },
    223                 { o1_setupObject, "bwwww" },
    224                 /* 08 */
    225                 { o1_checkCollision, "bwwww" },
    226                 { o1_loadVar, "bc" },
    227                 { o1_addVar, "bc" },
    228                 { o1_subVar, "bc" },
    229                 /* 0C */
    230                 { o1_mulVar, "bc" },
    231                 { o1_divVar, "bc" },
    232                 { o1_compareVar, "bc" },
    233                 { o1_modifyObjectParam2, "bbb" },
    234                 /* 10 */
    235                 { 0, 0 },
    236                 { 0, 0 },
    237                 { 0, 0 },
    238                 { o1_loadMask0, "b" },
    239                 /* 14 */
    240                 { o1_unloadMask0, "b" },
    241                 { o1_addToBgList, "b" },
    242                 { o1_loadMask1, "b" },
    243                 { o1_unloadMask1, "b" },
    244                 /* 18 */
    245                 { o1_loadMask4, "b" },
    246                 { o1_unloadMask4, "b" },
    247                 { o1_addSpriteFilledToBgList, "b" },
    248                 { o1_op1B, "" },
    249                 /* 1C */
    250                 { 0, 0 },
    251                 { o1_label, "l" },
    252                 { o1_goto, "b" },
    253                 { o1_gotoIfSup, "b" },
    254                 /* 20 */
    255                 { o1_gotoIfSupEqu, "b" },
    256                 { o1_gotoIfInf, "b" },
    257                 { o1_gotoIfInfEqu, "b" },
    258                 { o1_gotoIfEqu, "b" },
    259                 /* 24 */
    260                 { o1_gotoIfDiff, "b" },
    261                 { o1_removeLabel, "b" },
    262                 { o1_loop, "bb" },
    263                 { 0, 0 },
    264                 /* 28 */
    265                 { 0, 0 },
    266                 { 0, 0 },
    267                 { 0, 0 },
    268                 { 0, 0 },
    269                 /* 2C */
    270                 { 0, 0 },
    271                 { 0, 0 },
    272                 { 0, 0 },
    273                 { 0, 0 },
    274                 /* 30 */
    275                 { 0, 0 },
    276                 { o1_startGlobalScript, "b" },
    277                 { o1_endGlobalScript, "b" },
    278                 { 0, 0 },
    279                 /* 34 */
    280                 { 0, 0 },
    281                 { 0, 0 },
    282                 { 0, 0 },
    283                 { 0, 0 },
    284                 /* 38 */
    285                 { 0, 0 },
    286                 { 0, 0 },
    287                 { 0, 0 },
    288                 { o1_loadAnim, "s" },
    289                 /* 3C */
    290                 { o1_loadBg, "s" },
    291                 { o1_loadCt, "s" },
    292                 { 0, 0 },
    293                 { o2_loadPart, "s" },
    294                 /* 40 */
    295                 { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
    296                 { o1_loadNewPrcName, "bs" },
    297                 { o1_requestCheckPendingDataLoad, "" },
    298                 { 0, 0 },
    299                 /* 44 */
    300                 { 0, 0 },
    301                 { o1_blitAndFade, "" },
    302                 { o1_fadeToBlack, "" },
    303                 { o1_transformPaletteRange, "bbwww" },
    304                 /* 48 */
    305                 { 0, 0 },
    306                 { o1_setDefaultMenuColor2, "b" },
    307                 { o1_palRotate, "bbb" },
    308                 { 0, 0 },
    309                 /* 4C */
    310                 { 0, 0 },
    311                 { 0, 0 },
    312                 { 0, 0 },
    313                 { o1_break, "" },
    314                 /* 50 */
    315                 { o1_endScript, "x" },
    316                 { o1_message, "bwwww" },
    317                 { o1_loadGlobalVar, "bc" },
    318                 { o1_compareGlobalVar, "bc" },
    319                 /* 54 */
    320                 { 0, 0 },
    321                 { 0, 0 },
    322                 { 0, 0 },
    323                 { 0, 0 },
    324                 /* 58 */
    325                 { 0, 0 },
    326                 { o1_declareFunctionName, "s" },
    327                 { o1_freePartRange, "bb" },
    328                 { o1_unloadAllMasks, "" },
    329                 // 5C */
    330                 { 0, 0 },
    331                 { 0, 0 },
    332                 { 0, 0 },
    333                 { 0, 0 },
    334                 /* 60 */
    335                 { 0, 0 },
    336                 { 0, 0 },
    337                 { 0, 0 },
    338                 { o1_setScreenDimensions, "wwww" },
    339                 /* 64 */
    340                 { o1_displayBackground, "" },
    341                 { o1_initializeZoneData, "" },
    342                 { o1_setZoneDataEntry, "bw" },
    343                 { o1_getZoneDataEntry, "bb" },
    344                 /* 68 */
    345                 { o1_setDefaultMenuColor, "b" },
    346                 { o1_allowPlayerInput, "" },
    347                 { o1_disallowPlayerInput, "" },
    348                 { o1_changeDataDisk, "b" },
    349                 /* 6C */
    350                 { 0, 0 },
    351                 { o1_loadMusic, "s" },
    352                 { o1_playMusic, "" },
    353                 { o1_fadeOutMusic, "" },
    354                 /* 70 */
    355                 { o1_stopSample, "" },
    356                 { o1_op71, "bw" },
    357                 { o1_op72, "wbw" },
    358                 { o1_op72, "wbw" },
    359                 /* 74 */
    360                 { 0, 0 },
    361                 { 0, 0 },
    362                 { 0, 0 },
    363                 { o2_playSample, "bbwbww" },
    364                 /* 78 */
    365                 { o2_playSampleAlt, "bbwbww" },
    366                 { o1_disableSystemMenu, "b" },
    367                 { o1_loadMask5, "b" },
    368                 { o1_unloadMask5, "b" },
    369                 /* 7C */
    370                 { 0, 0 },
    371                 { 0, 0 },
    372                 { 0, 0 },
    373                 { o2_addSeqListElement, "bbbbwww" },
    374                 /* 80 */
    375                 { o2_removeSeq, "bb" },
    376                 { o2_op81, "" },
    377                 { o2_op82, "bbw" },
    378                 { o2_isSeqRunning, "bb" },
    379                 /* 84 */
    380                 { o2_gotoIfSupNearest, "b" },
    381                 { o2_gotoIfSupEquNearest, "b" },
    382                 { o2_gotoIfInfNearest, "b" },
    383                 { o2_gotoIfInfEquNearest, "b" },
    384                 /* 88 */
    385                 { o2_gotoIfEquNearest, "b" },
    386                 { o2_gotoIfDiffNearest, "b" },
    387                 { 0, 0 },
    388                 { o2_startObjectScript, "b" },
    389                 /* 8C */
    390                 { o2_stopObjectScript, "b" },
    391                 { o2_op8D, "wwwwwwww" },
    392                 { o2_addBackground, "bs" },
    393                 { o2_removeBackground, "b" },
    394                 /* 90 */
    395                 { o2_loadAbs, "bs" },
    396                 { o2_loadBg, "b" },
    397                 { 0, 0 },
    398                 { 0, 0 },
    399                 /* 94 */
    400                 { 0, 0 },
    401                 { o1_changeDataDisk, "b" },
    402                 { 0, 0 },
    403                 { 0, 0 },
    404                 /* 98 */
    405                 { 0, 0 },
    406                 { 0, 0 },
    407                 { o2_wasZoneChecked, "" },
    408                 { o2_op9B, "wwwwwwww" },
    409                 /* 9C */
    410                 { o2_op9C, "wwww" },
    411                 { o2_useBgScroll, "b" },
    412                 { o2_setAdditionalBgVScroll, "c" },
    413                 { o2_op9F, "ww" },
    414                 /* A0 */
    415                 { o2_addGfxElementA0, "ww" },
    416                 { o2_opA1, "ww" },
    417                 { o2_opA2, "ww" },
    418                 { o2_opA3, "ww" },
    419                 /* A4 */
    420                 { o2_loadMask22, "b" },
    421                 { o2_unloadMask22, "b" },
    422                 { 0, 0 },
    423                 { 0, 0 },
    424                 /* A8 */
    425                 { 0, 0 },
    426                 { o1_changeDataDisk, "b" }
    427         };
    428 
     427/*! \todo: replace with script subsystem
     428 */
     429void setupOpcodes() {
     430        static FWScriptInfo fw;
     431        static OSScriptInfo os;
    429432        if (g_cine->getGameType() == Cine::GType_FW) {
    430                 _opcodeTable = opcodeTableFW;
    431                 _numOpcodes = ARRAYSIZE(opcodeTableFW);
     433                scriptInfo = &fw;
    432434        } else {
    433                 _opcodeTable = opcodeTableOS;
    434                 _numOpcodes = ARRAYSIZE(opcodeTableOS);
     435                scriptInfo = &os;
    435436        }
    436437}
    437438
    438 byte getNextByte() {
    439         byte val = *(_currentScriptPtr + _currentPosition);
    440         _currentPosition++;
    441         return val;
    442 }
    443 
    444 uint16 getNextWord() {
    445         uint16 val = READ_BE_UINT16(_currentScriptPtr + _currentPosition);
    446         _currentPosition += 2;
    447         return val;
    448 }
    449 
    450 const char *getNextString() {
    451         const char *val = (const char *)(_currentScriptPtr + _currentPosition);
    452         _currentPosition += strlen(val) + 1;
    453         return val;
    454 }
    455 
    456 // empty array
     439/*! \brief Allocate empty array
     440 * \param len Size of array
     441 *
     442 * Explicit to prevent var=0 instead of var[i]=0 typos.
     443 */
    457444ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) {
    458445        assert(_vars);
    459446        reset();
    460447}
    461448
    462 // read game save, for later use
     449/*! \brief Allocate array and read contents from savefile
     450 * \param fHandle Savefile open for reading
     451 * \param len Size of array
     452 */
    463453ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len)
    464454        : _size(len), _vars(new int16[len]) {
    465455
     
    468458        load(fHandle);
    469459}
    470460
    471 // copy constructor
     461/*! \brief Copy constructor
     462 */
    472463ScriptVars::ScriptVars(const ScriptVars &src) : _size(src._size), _vars(new int16[_size]) {
    473464        assert(_vars);
    474465        memcpy(_vars, src._vars, _size * sizeof(int16));
    475466}
    476467
     468/*! \brief Destructor
     469 */
    477470ScriptVars::~ScriptVars(void) {
    478471        delete[] _vars;
    479472}
    480473
     474/*! \brief Assignment operator
     475 */
    481476ScriptVars &ScriptVars::operator=(const ScriptVars &src) {
    482477        ScriptVars tmp(src);
    483478        int16 *tmpvars = _vars;
     
    489484        return *this;
    490485}
    491486
    492 // array access
     487/*! \brief Direct array item access
     488 * \param idx Item index
     489 * \return Reference to item
     490 */
    493491int16 &ScriptVars::operator[](unsigned int idx) {
    494         debugN(5, "assert(%d < %d)", idx, _size);
     492        debugN(5, "assert(%d < %d)\n", idx, _size);
    495493        assert(idx < _size);
    496494        return _vars[idx];
    497495}
    498496
     497/*! \brief Direct read-only array item access
     498 * \param idx Item index
     499 * \return Copy of item
     500 */
    499501int16 ScriptVars::operator[](unsigned int idx) const {
    500502        debugN(5, "assert(%d < %d)\n", idx, _size);
    501503        assert(idx < _size);
    502504        return _vars[idx];
    503505}
    504506
    505 // dump to savefile
    506 void ScriptVars::save(Common::OutSaveFile &fHandle) {
     507/*! \brief Savefile writer
     508 * \param fHandle Savefile open for writing
     509 */
     510void ScriptVars::save(Common::OutSaveFile &fHandle) const {
    507511        save(fHandle, _size);
    508512}
    509513
    510 // globalVars[255] is not written to savefiles...
    511 void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) {
     514/*! \brief Savefile writer with data length limit
     515 * \param fHandle Savefile open for writing
     516 * \param len Length of data to be written (len <= _size)
     517 */
     518void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const {
    512519        debugN(5, "assert(%d <= %d)\n", len, _size);
    513520        assert(len <= _size);
    514521        for (unsigned int i = 0; i < len; i++) {
     
    516523        }
    517524}
    518525
    519 // read from savefile
     526/*! \brief Restore array from savefile
     527 * \param fHandle Savefile open for reading
     528 */
    520529void ScriptVars::load(Common::InSaveFile &fHandle) {
    521530        load(fHandle, _size);
    522531}
    523532
     533/*! \brief Restore part of array from savefile
     534 * \param fHandle Savefile open for reading
     535 * \param len Length of data to be read
     536 */
    524537void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) {
    525538        debugN(5, "assert(%d <= %d)\n", len, _size);
    526539        assert(len <= _size);
     
    529542        }
    530543}
    531544
     545/*! \brief Reset all values to 0
     546 */
    532547void ScriptVars::reset(void) {
    533548        memset( _vars, 0, _size * sizeof(int16));
    534549}
    535550
    536 void addGfxElementA0(int16 param1, int16 param2) {
    537         overlayHeadElement *currentHead = &overlayHead;
    538         overlayHeadElement *tempHead = currentHead;
    539         overlayHeadElement *newElement;
     551/*! \brief Constructor for partial loading
     552 * \param s Size of bytecode which will be added later
     553 *
     554 * This constructor _MUST_ be followed by setdata() method call before the
     555 * instance can be used. It leaves the instance in partially invalid state.
     556 */
     557RawScript::RawScript(uint16 s) : _size(s), _data(NULL),
     558        _labels(SCRIPT_STACK_SIZE) { }
    540559
    541         currentHead = tempHead->next;
     560/*! \brief Complete constructor
     561 * \param data Script bytecode
     562 * \param s Bytecode length
     563 */
     564RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) :
     565        _size(s), _data(NULL), _labels(SCRIPT_STACK_SIZE) {
    542566
    543         while (currentHead) {
    544                 if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
    545                         if (currentHead->type == 2 || currentHead->objIdx == 3) {
    546                                 break;
    547                         }
    548                 }
     567        setData(info, data);
     568}
    549569
    550                 tempHead = currentHead;
    551                 currentHead = currentHead->next;
    552         }
     570/*! \brief Copy constructor
     571 */
     572RawScript::RawScript(const RawScript &src) : _size(src._size),
     573        _data(new byte[_size+1]), _labels(src._labels) {
    553574
    554         if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
    555                 return;
    556 
    557         newElement = new overlayHeadElement;
    558 
    559         newElement->next = tempHead->next;
    560         tempHead->next = newElement;
    561 
    562         newElement->objIdx = param1;
    563         newElement->type = 20;
    564 
    565         newElement->x = param2;
    566         newElement->y = 0;
    567         newElement->width = 0;
    568         newElement->color = 0;
    569 
    570         if (!currentHead)
    571                 currentHead = &overlayHead;
    572 
    573         newElement->previous = currentHead->previous;
    574 
    575         currentHead->previous = newElement;
     575        assert(_data);
     576        memcpy(_data, src._data, _size+1);
    576577}
    577578
    578 void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
    579         SeqListElement *currentHead = &seqList;
    580         SeqListElement *tempHead = currentHead;
    581 
    582         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    583                 tempHead = currentHead;
    584                 currentHead = tempHead->next;
    585         }
    586 
    587         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    588                 currentHead->var4 = -1;
    589         }
     579/*! \brief Destructor
     580 */
     581RawScript::~RawScript(void) {
     582        delete[] _data;
    590583}
    591584
    592 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
    593         SeqListElement *currentHead = &seqList;
    594         SeqListElement *tempHead = currentHead;
     585/*! \brief Assignment operator
     586 */
     587RawScript &RawScript::operator=(const RawScript &src) {
     588        assert(src._data);
     589        byte *tmp = new byte[src._size+1];
    595590
    596         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    597                 tempHead = currentHead;
    598                 currentHead = tempHead->next;
    599         }
     591        assert(tmp);
     592        _labels = src._labels;
     593        _size = src._size;
    600594
    601         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    602                 return 1;
    603         }
     595        delete[] _data;
     596        _data = tmp;
     597        memcpy(_data, src._data, _size);
     598        _data[_size] = 0;
    604599
    605         return 0;
     600        return *this;
    606601}
    607602
    608 ScriptStruct scriptTable[NUM_MAX_SCRIPT];
     603/*! \brief Get the next label in bytecode
     604 * \param info Script info instance
     605 * \param offset Starting offset
     606 * \return Index of the next label in bytecode or _size on end of bytecode
     607 *
     608 * computeScriptStackSub replacement
     609 */
     610uint16 RawScript::getNextLabel(const FWScriptInfo &info, uint16 offset) const {
     611        assert(_data);
     612        uint16 pos = offset;
    609613
    610 void stopGlobalScript(uint16 scriptIdx) {
    611         prcLinkedListStruct *currentHead = &globalScriptsHead;
    612         prcLinkedListStruct *tempHead = currentHead;
     614        while (pos < _size) {
     615                uint8 opcode = _data[pos];
     616                pos++;
     617                const char *ptr = info.opcodeInfo(opcode);
    613618
    614         currentHead = tempHead->next;
    615 
    616         while (currentHead && (currentHead->scriptIdx != scriptIdx)) {
    617                 tempHead = currentHead;
    618                 currentHead = tempHead->next;
    619         }
    620 
    621         if (!currentHead) {
    622                 return;
    623         }
    624 
    625         if (currentHead->scriptIdx != scriptIdx) {
    626                 return;
    627         }
    628 
    629         currentHead->scriptIdx = -1;
    630 }
    631 
    632 uint16 computeScriptStackSub(bool computeAllLabels, byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, byte labelIndex, uint16 startOffset) {
    633         uint16 position;
    634 
    635         if (computeAllLabels) {
    636                 for (int i = 0; i < SCRIPT_STACK_SIZE; i++) {
    637                         stackPtr[i] = -1;
    638                 }
    639                 position = 0;
    640         } else {
    641                 position = startOffset;
    642         }
    643         while (position < scriptSize) {
    644                 uint8 opcode = scriptPtr[position];
    645                 position++;
    646                 if (opcode == 0 || opcode > _numOpcodes) {
     619                if (!ptr) {
    647620                        continue;
    648621                }
    649                 if (!_opcodeTable[opcode - 1].args) {
    650                         warning("Undefined opcode 0x%02X in computeScriptStackSub", opcode - 1);
    651                         continue;
    652                 }
    653                 for (const char *p = _opcodeTable[opcode - 1].args; *p; ++p) {
    654                         switch (*p) {
     622
     623                for (; *ptr; ++ptr) {
     624                        switch (*ptr) {
    655625                        case 'b': // byte
    656                                 position++;
     626                                pos++;
    657627                                break;
    658628                        case 'w': // word
    659                                 position += 2;
     629                                pos += 2;
    660630                                break;
    661631                        case 'c': { // byte != 0 ? byte : word
    662                                         uint8 test = scriptPtr[position];
    663                                         position++;
     632                                        uint8 test = _data[pos];
     633                                        pos++;
    664634                                        if (test) {
    665                                                 position++;
     635                                                pos++;
    666636                                        } else {
    667                                                 position += 2;
     637                                                pos += 2;
    668638                                        }
    669639                                }
    670640                                break;
    671                         case 'l': { // label
    672                                         uint8 index = scriptPtr[position];
    673                                         position++;
    674                                         if (computeAllLabels) {
    675                                                 stackPtr[index] = position;
    676                                         } else {
    677                                                 if (labelIndex == index) {
    678                                                         return position;
    679                                                 }
    680                                         }
    681                                 }
    682                                 break;
     641                        case 'l': // label
     642                                return pos;
    683643                        case 's': // string
    684                                 while (scriptPtr[position++] != 0);
     644                                while (_data[pos++] != 0);
    685645                                break;
    686646                        case 'x': // exit script
    687                                 return position;
     647                                // this is a little change from the original
     648                                // code, I want to know if it breaks something
     649                                assert(pos >= _size-1);
     650                                return _size;
    688651                        }
    689652                }
    690653        }
    691         return position;
     654        return _size;
    692655}
    693656
    694 void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) {
    695         computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0);
    696 }
     657/*! \brief Calculate initial script labels
     658 * \param info Script info instance
     659 *
     660 * computeScriptStack replacement
     661 */
     662void RawScript::computeLabels(const FWScriptInfo &info) {
     663        assert(_data);
     664        uint16 pos = 0;
     665        int i;
    697666
    698 uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) {
    699         return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition);
     667        // reset labels
     668        for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
     669                _labels[i] = -1;
     670        }
     671
     672        // parse bytecode
     673        while ((pos = getNextLabel(info, pos)) < _size) {
     674                i = _data[pos];
     675                _labels[i] = ++pos;
     676        }
    700677}
    701678
    702 void palRotate(byte a, byte b, byte c) {
    703         if (c == 1) {
    704                 uint16 currentColor = c_palette[b];
     679/*! \brief find the next label from current position
     680 * \param info Script info instance
     681 * \param index Label index to look for
     682 * \param offset Current position in script
     683 * \return Position of next instruction following the label
     684 *
     685 * computeScriptStackFromScript replacement
     686 */
     687uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
     688        const {
    705689
    706                 for (int16 i = b; i > a; i--) {
    707                         c_palette[i] = c_palette[i - 1];
     690        assert(_data);
     691        uint16 pos = offset;
     692
     693        while ((pos = getNextLabel(info, pos)) < _size) {
     694                if (_data[pos++] == index) {
     695                        return pos;
    708696                }
     697        }
    709698
    710                 c_palette[a] = currentColor;
    711         }
     699        return _size;
    712700}
    713701
    714 void addScriptToList0(uint16 idx) {
    715         uint16 i;
    716         prcLinkedListStruct *pNewElement;
    717         prcLinkedListStruct *currentHead = &globalScriptsHead;
    718         prcLinkedListStruct *tempHead = currentHead;
     702/*! \brief Copy bytecode and calculate labels
     703 * \param data Bytecode to copy, must be _size long
     704 */
     705void RawScript::setData(const FWScriptInfo &info, const byte *data) {
     706        assert(!_data); // this function should be called only once per instance
     707        _data = new byte[_size+1];
    719708
    720         assert(idx <= NUM_MAX_SCRIPT);
     709        assert(data && _data);
     710        memcpy(_data, data, _size * sizeof(byte));
     711        _data[_size] = 0;
    721712
    722         currentHead = tempHead->next;
     713        computeLabels(info);
     714}
    723715
    724         while (currentHead) {
    725                 tempHead = currentHead;
     716/*! \brief Initial script labels
     717 * \return Precalculated script labels
     718 */
     719const ScriptVars &RawScript::labels(void) const {
     720        assert(_data);
     721        return _labels;
     722}
    726723
    727                 assert(tempHead);
     724/*! \brief One byte of bytecode
     725 * \param pos Index in bytecode
     726 * \return Byte from bytecode
     727 */
     728byte RawScript::getByte(unsigned int pos) const {
     729        assert(_data && pos < _size);
    728730
    729                 currentHead = tempHead->next;
    730         }
     731        return _data[pos];
     732}
    731733
    732         pNewElement = new prcLinkedListStruct;
     734/*! \brief One word of bytecode
     735 * \param pos Index of the first byte in bytecode
     736 * \return Word of bytecode
     737 */
     738uint16 RawScript::getWord(unsigned int pos) const {
     739        assert(_data && pos+1 < _size);
    733740
    734         assert(pNewElement);
     741        return READ_BE_UINT16(_data + pos);
     742}
    735743
    736         pNewElement->next = tempHead->next;
    737         tempHead->next = pNewElement;
     744/*! \brief String in bytecode
     745 * \param pos Index of the first char in string
     746 * \return Pointer to part of bytecode
     747 */
     748const char *RawScript::getString(unsigned int pos) const {
     749        assert(_data && pos < _size);
    738750
    739         // copy the stack into the script instance
    740         for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
    741                 pNewElement->stack[i] = scriptTable[idx].stack[i];
    742         }
     751        return (const char*)(_data+pos);
     752}
    743753
    744         pNewElement->compareResult = 0;
    745         pNewElement->scriptPosition = 0;
     754/*! \brief Constructor for partial loading
     755 * \param size Size of bytecode which will be added later
     756 * \param p1 First object script parameter
     757 * \param p2 Second object script parameter
     758 * \param p3 Third object script parameter
     759 *
     760 * This constructor _MUST_ be followed by setdata() method call before the
     761 * instance can be used. It leaves the instance in partially invalid state.
     762 */
     763RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
     764        : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
     765{ }
    746766
    747         pNewElement->scriptPtr = scriptTable[idx].ptr;
    748         pNewElement->scriptIdx = idx;
     767/*! \brief Complete constructor
     768 * \param data Script bytecode
     769 * \param s Bytecode length
     770 * \param p1 First object script parameter
     771 * \param p2 Second object script parameter
     772 * \param p3 Third object script parameter
     773 */
     774RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
     775        uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
     776        _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
     777
     778/*! \brief Contructor for global scripts
     779 * \param script Script bytecode reference
     780 * \param idx Script bytecode index
     781 */
     782FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
     783        _pos(0), _line(0), _compare(0), _index(idx),
     784        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     785        _globalVars(globalVars), _info(new FWScriptInfo) { }
     786
     787/*! \brief Copy constructor
     788 */
     789FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
     790        _line(src._line), _compare(src._compare), _index(src._index),
     791        _labels(src._labels), _localVars(src._localVars),
     792        _globalVars(src._globalVars), _info(new FWScriptInfo) { }
     793
     794/*! \brief Contructor for global scripts in derived classes
     795 * \param script Script bytecode reference
     796 * \param idx Script bytecode index
     797 */
     798FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
     799        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     800        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     801        _globalVars(globalVars), _info(info) { }
     802
     803/*! \brief Constructor for object scripts in derived classes
     804 * \param script Script bytecode reference
     805 * \param idx Script bytecode index
     806 */
     807FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
     808        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     809        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     810        _globalVars(globalVars), _info(info) {
     811
     812        _localVars[0] = script.run();
    749813}
    750814
    751 int16 endScript0(uint16 scriptIdx) {
    752         prcLinkedListStruct *currentHead = &globalScriptsHead;
    753         prcLinkedListStruct *tempHead = currentHead;
     815/*! \brief Copy constructor for derived classes
     816 */
     817FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
     818        _script(src._script), _pos(src._pos), _line(src._line),
     819        _compare(src._compare), _index(src._index), _labels(src._labels),
     820        _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
    754821
    755         //assert(scriptIdx <= NUM_MAX_SCRIPT);
     822FWScript::~FWScript(void) {
     823        delete _info;
     824}
    756825
    757         currentHead = tempHead->next;
     826/*! \brief Read next byte from bytecode
     827 * \return Byte from bytecode
     828 */
     829byte FWScript::getNextByte() {
     830        byte val = _script.getByte(_pos);
     831        _pos++;
     832        return val;
     833}
    758834
    759         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    760                 tempHead = currentHead;
    761                 currentHead = tempHead->next;
    762         }
     835/*! \brief Read next word from bytecode
     836 * \return Word from bytecode
     837 */
     838uint16 FWScript::getNextWord() {
     839        uint16 val = _script.getWord(_pos);
     840        _pos += 2;
     841        return val;
     842}
    763843
    764         if (!currentHead) {
    765                 return -1;
    766         }
     844/*! \brief Read next string from bytecode
     845 * \return Pointer to string
     846 */
     847const char *FWScript::getNextString() {
     848        const char *val = _script.getString(_pos);
     849        _pos += strlen(val) + 1;
     850        return val;
     851}
    767852
    768         if (currentHead->scriptIdx != scriptIdx) {
    769                 return -1;
     853/*! \brief Restore script state from savefile
     854 * \param labels Restored script labels
     855 * \param local Restored local script variables
     856 * \param compare Restored last comparison result
     857 * \param pos Restored script position
     858 */
     859void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     860        assert(pos < _script.size());
     861        _labels = labels;
     862        _localVars = local;
     863        _compare = compare;
     864        _pos = _line = pos;
     865}
     866
     867/*! \brief Execute script
     868 * \return <0 on script termination, >0 on script pause
     869 *
     870 * executeScript replacement.
     871 * Instruction handler must return 0 if the script should continue or
     872 * nonzero with the same meaning as return value of this function
     873 */
     874int FWScript::execute() {
     875        int ret = 0;
     876
     877        while (!ret) {
     878                _line = _pos;
     879                byte opcode = getNextByte();
     880                opFunc handler = _info->opcodeHandler(opcode);
     881
     882                if (handler) {
     883                        ret = (this->*handler)();
     884                }
    770885        }
    771886
    772         currentHead->scriptIdx = -1;
     887        return ret;
     888}
    773889
    774         return 0;
     890/*! \brief Save script to savefile
     891 * \param fHandle Savefile handle
     892 */
     893void FWScript::save(Common::OutSaveFile &fHandle) const {
     894        _labels.save(fHandle);
     895        _localVars.save(fHandle);
     896        fHandle.writeUint16BE(_compare);
     897        fHandle.writeUint16BE(_pos);
     898        // data order sucks...
     899        fHandle.writeUint16BE(_index);
    775900}
    776901
    777 int16 endScript1(uint16 scriptIdx) {
    778         prcLinkedListStruct *currentHead = &objScriptList;
    779         prcLinkedListStruct *tempHead = currentHead;
     902/*! \brief Contructor for global scripts
     903 * \param script Script bytecode reference
     904 * \param idx Script bytecode index
     905 */
     906OSScript::OSScript(const RawScript &script, int16 idx) :
     907        FWScript(script, idx, new OSScriptInfo) {}
    780908
    781         currentHead = tempHead->next;
     909/*! \brief Constructor for object scripts
     910 * \param script Script bytecode reference
     911 * \param idx Script bytecode index
     912 */
     913OSScript::OSScript(RawObjectScript &script, int16 idx) :
     914        FWScript(script, idx, new OSScriptInfo) {}
    782915
    783         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    784                 tempHead = currentHead;
    785                 currentHead = tempHead->next;
    786         }
     916/*! \brief Copy constructor
     917 */
     918OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
    787919
    788         if (!currentHead) {
    789                 return -1;
     920/*! \brief Restore script state from savefile
     921 * \param labels Restored script labels
     922 * \param local Restored local script variables
     923 * \param compare Restored last comparison result
     924 * \param pos Restored script position
     925 */
     926void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     927        FWScript::load(labels, local, compare, pos);
     928}
     929/*! \brief Get opcode info string
     930 * \param opcode Opcode to look for in opcode table
     931 */
     932const char *FWScriptInfo::opcodeInfo(byte opcode) const {
     933        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     934                return NULL;
    790935        }
    791936
    792         if (currentHead->scriptIdx != scriptIdx) {
    793                 return -1;
     937        if (!FWScript::_opcodeTable[opcode - 1].args) {
     938                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1);
     939                return NULL;
    794940        }
    795941
    796         currentHead->scriptIdx = -1;
    797 
    798         return 0;
     942        return FWScript::_opcodeTable[opcode - 1].args;
    799943}
    800944
    801 int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
    802         byte *ptr = page + (y * width) + x / 2;
    803         byte zoneVar;
     945/*! \brief Get opcode handler pointer
     946 * \param opcode Opcode to look for in opcode table
     947 */
     948opFunc FWScriptInfo::opcodeHandler(byte opcode) const {
     949        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     950                return NULL;
     951        }
    804952
    805         if (!(x % 2)) {
    806                 zoneVar = (*(ptr) >> 4) & 0xF;
    807         } else {
    808                 zoneVar = (*(ptr)) & 0xF;
     953        if (!FWScript::_opcodeTable[opcode - 1].proc) {
     954                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1);
     955                return NULL;
    809956        }
    810957
    811         return zoneVar;
     958        return FWScript::_opcodeTable[opcode - 1].proc;
    812959}
    813960
    814 int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
    815         byte *ptr = page + (y * width) + x;
    816         byte zoneVar;
     961/*! \brief Create new FWScript instance
     962 * \param script Script bytecode
     963 * \param index Bytecode index
     964 */
     965FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const {
     966        return new FWScript(script, index);
     967}
    817968
    818         zoneVar = (*(ptr)) & 0xF;
     969/*! \brief Create new FWScript instance
     970 * \param script Object script bytecode
     971 * \param index Bytecode index
     972 */
     973FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const {
     974        return new FWScript(script, index);
     975}
    819976
    820         return zoneVar;
     977/*! \brief Load saved FWScript instance
     978 * \param script Script bytecode
     979 * \param index Bytecode index
     980 * \param local Local variables
     981 * \param labels Script labels
     982 * \param compare Last compare result
     983 * \param pos Position in script
     984 */
     985FWScript *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     986        FWScript *tmp = new FWScript(script, index);
     987        assert(tmp);
     988        tmp->load(labels, local, compare, pos);
     989        return tmp;
    821990}
    822991
    823 int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
    824         int16 lx = objectTable[objIdx].x + x;
    825         int16 ly = objectTable[objIdx].y + y;
    826         int16 idx;
     992/*! \brief Load saved FWScript instance
     993 * \param script Object script bytecode
     994 * \param index Bytecode index
     995 * \param local Local variables
     996 * \param labels Script labels
     997 * \param compare Last compare result
     998 * \param pos Position in script
     999 */
     1000FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1001        FWScript *tmp = new FWScript(script, index);
     1002        assert(tmp);
     1003        tmp->load(labels, local, compare, pos);
     1004        return tmp;
     1005}
    8271006
    828         for (int16 i = 0; i < numZones; i++) {
    829                 idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     1007/*! \brief Get opcode info string
     1008 * \param opcode Opcode to look for in opcode table
     1009 */
     1010const char *OSScriptInfo::opcodeInfo(byte opcode) const {
     1011        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1012                return NULL;
     1013        }
    8301014
    831                 assert(idx >= 0 && idx <= NUM_MAX_ZONE);
    832 
    833                 if (zoneData[idx] == zoneIdx) {
    834                         return 1;
    835                 }
     1015        if (!OSScript::_opcodeTable[opcode - 1].args) {
     1016                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
     1017                return NULL;
    8361018        }
    8371019
    838         return 0;
     1020        return OSScript::_opcodeTable[opcode - 1].args;
    8391021}
    8401022
    841 uint16 compareVars(int16 a, int16 b) {
    842         uint16 flag = 0;
     1023/*! \brief Get opcode handler pointer
     1024 * \param opcode Opcode to look for in opcode table
     1025 */
     1026opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
     1027        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1028                return NULL;
     1029        }
    8431030
    844         if (a == b) {
    845                 flag |= kCmpEQ;
    846         } else if (a > b) {
    847                 flag |= kCmpGT;
    848         } else if (a < b) {
    849                 flag |= kCmpLT;
     1031        if (!OSScript::_opcodeTable[opcode - 1].proc) {
     1032                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
     1033                return NULL;
    8501034        }
    8511035
    852         return flag;
     1036        return OSScript::_opcodeTable[opcode - 1].proc;
    8531037}
    8541038
     1039/*! \brief Create new OSScript instance
     1040 * \param script Script bytecode
     1041 * \param index Bytecode index
     1042 */
     1043FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
     1044        return new OSScript(script, index);
     1045}
     1046
     1047/*! \brief Create new OSScript instance
     1048 * \param script Object script bytecode
     1049 * \param index Bytecode index
     1050 */
     1051FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
     1052        return new OSScript(script, index);
     1053}
     1054
     1055/*! \brief Load saved OSScript instance
     1056 * \param script Script bytecode
     1057 * \param index Bytecode index
     1058 * \param local Local variables
     1059 * \param labels Script labels
     1060 * \param compare Last compare result
     1061 * \param pos Position in script
     1062 */
     1063FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1064        OSScript *tmp = new OSScript(script, index);
     1065        assert(tmp);
     1066        tmp->load(labels, local, compare, pos);
     1067        return tmp;
     1068}
     1069
     1070/*! \brief Load saved OSScript instance
     1071 * \param script Object script bytecode
     1072 * \param index Bytecode index
     1073 * \param local Local variables
     1074 * \param labels Script labels
     1075 * \param compare Last compare result
     1076 * \param pos Position in script
     1077 */
     1078FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1079        OSScript *tmp = new OSScript(script, index);
     1080        assert(tmp);
     1081        tmp->load(labels, local, compare, pos);
     1082        return tmp;
     1083}
     1084
    8551085// ------------------------------------------------------------------------
    8561086// FUTURE WARS opcodes
    8571087// ------------------------------------------------------------------------
    8581088
    859 void o1_modifyObjectParam() {
     1089int FWScript::o1_modifyObjectParam() {
    8601090        byte objIdx = getNextByte();
    8611091        byte paramIdx = getNextByte();
    8621092        int16 newValue = getNextWord();
    8631093
    864         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1094        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8651095
    8661096        modifyObjectParam(objIdx, paramIdx, newValue);
     1097        return 0;
    8671098}
    8681099
    869 void o1_getObjectParam() {
     1100int FWScript::o1_getObjectParam() {
    8701101        byte objIdx = getNextByte();
    8711102        byte paramIdx = getNextByte();
    8721103        byte newValue = getNextByte();
    8731104
    874         debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue);
     1105        debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue);
    8751106
    876         _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1107        _localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1108        return 0;
    8771109}
    8781110
    879 void o1_addObjectParam() {
     1111int FWScript::o1_addObjectParam() {
    8801112        byte objIdx = getNextByte();
    8811113        byte paramIdx = getNextByte();
    8821114        int16 newValue = getNextWord();
    8831115
    884         debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1116        debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8851117
    8861118        addObjectParam(objIdx, paramIdx, newValue);
     1119        return 0;
    8871120}
    8881121
    889 void o1_subObjectParam() {
     1122int FWScript::o1_subObjectParam() {
    8901123        byte objIdx = getNextByte();
    8911124        byte paramIdx = getNextByte();
    8921125        int16 newValue = getNextWord();
    8931126
    894         debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1127        debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8951128
    8961129        subObjectParam(objIdx, paramIdx, newValue);
     1130        return 0;
    8971131}
    8981132
    899 void o1_add2ObjectParam() {
     1133/*! \todo Implement this instruction
     1134 */
     1135int FWScript::o1_add2ObjectParam() {
    9001136        getNextByte();
    9011137        getNextByte();
    9021138        getNextWord();
    9031139        warning("STUB: o1_add2ObjectParam()");
     1140        return 0;
    9041141}
    9051142
    906 void o1_sub2ObjectParam() {
     1143/*! \todo Implement this instruction
     1144 */
     1145int FWScript::o1_sub2ObjectParam() {
    9071146        getNextByte();
    9081147        getNextByte();
    9091148        getNextWord();
    9101149        warning("STUB: o1_sub2ObjectParam()");
     1150        return 0;
    9111151}
    9121152
    913 void o1_compareObjectParam() {
     1153int FWScript::o1_compareObjectParam() {
    9141154        byte objIdx = getNextByte();
    9151155        byte param1 = getNextByte();
    9161156        int16 param2 = getNextWord();
    9171157
    918         debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2);
     1158        debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2);
    9191159
    920         _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2);
     1160        _compare = compareObjectParam(objIdx, param1, param2);
     1161        return 0;
    9211162}
    9221163
    923 void o1_setupObject() {
     1164int FWScript::o1_setupObject() {
    9241165        byte objIdx = getNextByte();
    9251166        int16 param1 = getNextWord();
    9261167        int16 param2 = getNextWord();
    9271168        int16 param3 = getNextWord();
    9281169        int16 param4 = getNextWord();
    9291170
    930         debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1171        debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9311172
    9321173        setupObject(objIdx, param1, param2, param3, param4);
     1174        return 0;
    9331175}
    9341176
    935 void o1_checkCollision() {
     1177int FWScript::o1_checkCollision() {
    9361178        byte objIdx = getNextByte();
    9371179        int16 param1 = getNextWord();
    9381180        int16 param2 = getNextWord();
    9391181        int16 param3 = getNextWord();
    9401182        int16 param4 = getNextWord();
    9411183
    942         debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1184        debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9431185
    944         _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4);
     1186        _compare = checkCollision(objIdx, param1, param2, param3, param4);
     1187        return 0;
    9451188}
    9461189
    947 void o1_loadVar() {
     1190int FWScript::o1_loadVar() {
    9481191        byte varIdx = getNextByte();
    9491192        byte varType = getNextByte();
    9501193
     
    9541197
    9551198                switch (varType) {
    9561199                case 1:
    957                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    958                         _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1200                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx);
     1201                        _localVars[varIdx] = _localVars[dataIdx];
    9591202                        break;
    9601203                case 2:
    961                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    962                         _currentScriptElement->localVars[varIdx] = globalVars[dataIdx];
     1204                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1205                        _localVars[varIdx] = _globalVars[dataIdx];
    9631206                        break;
    9641207                case 3:
    965                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _currentLine, varIdx);
    966                         getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, (uint16 *)&dummyU16);
    967                         _currentScriptElement->localVars[varIdx] = var;
     1208                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx);
     1209                        getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16);
     1210                        _localVars[varIdx] = var;
    9681211                        break;
    9691212                case 4:
    970                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _currentLine, varIdx);
    971                         getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&dummyU16, (uint16 *)&var);
    972                         _currentScriptElement->localVars[varIdx] = var;
     1213                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx);
     1214                        getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var);
     1215                        _localVars[varIdx] = var;
    9731216                        break;
    9741217                case 5:
    975                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _currentLine, varIdx, dataIdx);
    976                         _currentScriptElement->localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
     1218                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx);
     1219                        _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
    9771220                        break;
    9781221                case 8:
    979                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx);
    980                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize;
     1222                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
     1223                        _localVars[varIdx] = partBuffer[dataIdx].packedSize;
    9811224                        break;
    9821225                case 9:
    983                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx);
    984                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
     1226                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
     1227                        _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
    9851228                        break;
    9861229                default:
    9871230                        error("executeScript: o1_loadVar: Unknown variable type %d", varType);
     
    9891232        } else {
    9901233                int16 value = getNextWord();
    9911234
    992                 debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value);
    993                 _currentScriptElement->localVars[varIdx] = value;
     1235                debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value);
     1236                _localVars[varIdx] = value;
    9941237        }
     1238
     1239        return 0;
    9951240}
    9961241
    997 void o1_addVar() {
     1242int FWScript::o1_addVar() {
    9981243        byte varIdx = getNextByte();
    9991244        byte varType = getNextByte();
    10001245
    10011246        if (varType) {
    10021247                byte dataIdx = getNextByte();
    10031248
    1004                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx);
    1005                 _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx];
     1249                if (varType == 1) {
     1250                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx);
     1251                        _localVars[varIdx] += _localVars[dataIdx];
     1252                } else if (varType == 2) {
     1253                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx);
     1254                        _localVars[varIdx] += _globalVars[dataIdx];
     1255                }
    10061256        } else {
    10071257                int16 value = getNextWord();
    10081258
    1009                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value);
    1010                 _currentScriptElement->localVars[varIdx] += value;
     1259                debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value);
     1260                _localVars[varIdx] += value;
    10111261        }
     1262
     1263        return 0;
    10121264}
    10131265
    1014 void o1_subVar() {
     1266int FWScript::o1_subVar() {
    10151267        byte varIdx = getNextByte();
    10161268        byte varType = getNextByte();
    10171269
    10181270        if (varType) {
    10191271                byte dataIdx = getNextByte();
    10201272
    1021                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx);
    1022                 _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx];
     1273                if (varType == 1) {
     1274                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx);
     1275                        _localVars[varIdx] -= _localVars[dataIdx];
     1276                } else if (varType == 2) {
     1277                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx);
     1278                        _localVars[varIdx] -= _globalVars[dataIdx];
     1279                }
     1280
    10231281        } else {
    10241282                int16 value = getNextWord();
    10251283
    1026                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value);
    1027                 _currentScriptElement->localVars[varIdx] -= value;
     1284                debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value);
     1285                _localVars[varIdx] -= value;
    10281286        }
     1287
     1288        return 0;
    10291289}
    10301290
    1031 void o1_mulVar() {
     1291int FWScript::o1_mulVar() {
    10321292        byte varIdx = getNextByte();
    10331293        byte varType = getNextByte();
    10341294
    10351295        if (varType) {
    10361296                byte dataIdx = getNextByte();
    10371297
    1038                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx);
    1039                 _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx];
     1298                if (varType == 1) {
     1299                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx);
     1300                        _localVars[varIdx] *= _localVars[dataIdx];
     1301                } else if (varType == 2) {
     1302                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx);
     1303                        _localVars[varIdx] *= _globalVars[dataIdx];
     1304                }
    10401305        } else {
    10411306                int16 value = getNextWord();
    10421307
    1043                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value);
    1044                 _currentScriptElement->localVars[varIdx] *= value;
     1308                debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value);
     1309                _localVars[varIdx] *= value;
    10451310        }
     1311
     1312        return 0;
    10461313}
    10471314
    1048 void o1_divVar() {
     1315int FWScript::o1_divVar() {
    10491316        byte varIdx = getNextByte();
    10501317        byte varType = getNextByte();
    10511318
    10521319        if (varType) {
    10531320                byte dataIdx = getNextByte();
    10541321
    1055                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx);
    1056                 _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx];
     1322                if (varType == 1) {
     1323                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx);
     1324                        _localVars[varIdx] /= _localVars[dataIdx];
     1325                } else if (varType == 2) {
     1326                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx);
     1327                        _localVars[varIdx] /= _globalVars[dataIdx];
     1328                }
    10571329        } else {
    10581330                int16 value = getNextWord();
    10591331
    1060                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value);
    1061                 _currentScriptElement->localVars[varIdx] /= value;
     1332                debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value);
     1333                _localVars[varIdx] /= value;
    10621334        }
     1335
     1336        return 0;
    10631337}
    10641338
    1065 void o1_compareVar() {
     1339int FWScript::o1_compareVar() {
    10661340        byte varIdx = getNextByte();
    10671341        byte varType = getNextByte();
    10681342
    10691343        if (varType) {
    10701344                byte dataIdx = getNextByte();
    10711345
    1072                 // printf("Val: %d\n", dataIdx);
    1073 
    10741346                if (varType == 1) {
    1075                         assert(varIdx < 50);
    1076                         assert(dataIdx < 50);
    1077 
    1078                         debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _currentLine, varIdx, dataIdx);
    1079                         _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], _currentScriptElement->localVars[dataIdx]);
     1347                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx);
     1348                        _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]);
    10801349                } else if (varType == 2) {
    1081                         assert(varIdx < 50);
    1082 
    1083                         debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _currentLine, varIdx, dataIdx);
    1084                         _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], globalVars[dataIdx]);
     1350                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx);
     1351                        _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]);
    10851352                }
    10861353        } else {
    10871354                int16 value = getNextWord();
    10881355
    1089                 debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value);
    1090                 _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value);
     1356                debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value);
     1357                _compare = compareVars(_localVars[varIdx], value);
    10911358        }
     1359
     1360        return 0;
    10921361}
    10931362
    1094 void o1_modifyObjectParam2() {
     1363int FWScript::o1_modifyObjectParam2() {
    10951364        byte objIdx = getNextByte();
    10961365        byte paramIdx = getNextByte();
    10971366        byte newValue = getNextByte();
    10981367
    1099         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue);
     1368        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue);
    11001369
    1101         modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]);
     1370        modifyObjectParam(objIdx, paramIdx, _localVars[newValue]);
     1371        return 0;
    11021372}
    11031373
    1104 void o1_loadMask0() {
     1374int FWScript::o1_loadMask0() {
    11051375        // OP_loadV7Element
    11061376        byte param = getNextByte();
    11071377
    1108         debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param);
     1378        debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
    11091379        loadOverlayElement(param, 0);
     1380        return 0;
    11101381}
    11111382
    1112 void o1_unloadMask0() {
     1383int FWScript::o1_unloadMask0() {
    11131384        byte param = getNextByte();
    11141385
    1115         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param);
     1386        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
    11161387        freeOverlay(param, 0);
     1388        return 0;
    11171389}
    11181390
    1119 void o1_addToBgList() {
     1391int FWScript::o1_addToBgList() {
    11201392        byte param = getNextByte();
    11211393
    1122         debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param);
     1394        debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param);
    11231395        addToBGList(param);
     1396        return 0;
    11241397}
    11251398
    1126 void o1_loadMask1() {
     1399int FWScript::o1_loadMask1() {
    11271400        byte param = getNextByte();
    11281401
    1129         debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param);
     1402        debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
    11301403        loadOverlayElement(param, 1);
     1404        return 0;
    11311405}
    11321406
    1133 void o1_unloadMask1() {
     1407int FWScript::o1_unloadMask1() {
    11341408        byte param = getNextByte();
    11351409
    1136         debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param);
     1410        debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
    11371411        freeOverlay(param, 1);
     1412        return 0;
    11381413}
    11391414
    1140 void o1_loadMask4() {
     1415int FWScript::o1_loadMask4() {
    11411416        byte param = getNextByte();
    11421417
    1143         debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param);
     1418        debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
    11441419        loadOverlayElement(param, 4);
     1420        return 0;
    11451421}
    11461422
    1147 void o1_unloadMask4() {
     1423int FWScript::o1_unloadMask4() {
    11481424        byte param = getNextByte();
    11491425
    1150         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param);
     1426        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
    11511427        freeOverlay(param, 4);
     1428        return 0;
    11521429}
    11531430
    1154 void o1_addSpriteFilledToBgList() {
     1431int FWScript::o1_addSpriteFilledToBgList() {
    11551432        byte param = getNextByte();
    11561433
    1157         debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param);
     1434        debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param);
    11581435        addSpriteFilledToBGList(param);
     1436        return 0;
    11591437}
    11601438
    1161 void o1_op1B() {
    1162         debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine);
     1439int FWScript::o1_op1B() {
     1440        debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
    11631441        freeBgIncrustList();
     1442        return 0;
    11641443}
    11651444
    1166 void o1_label() {
     1445int FWScript::o1_label() {
    11671446        byte labelIdx = getNextByte();
    11681447
    1169         debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx);
    1170         _currentScriptElement->stack[labelIdx] = _currentPosition;
     1448        debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx);
     1449        _labels[labelIdx] = _pos;
     1450        return 0;
    11711451}
    11721452
    1173 void o1_goto() {
     1453int FWScript::o1_goto() {
    11741454        byte labelIdx = getNextByte();
    11751455
    1176         assert(_currentScriptElement->stack[labelIdx] != -1);
     1456        assert(_labels[labelIdx] != -1);
    11771457
    1178         debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx);
    1179         _currentPosition = _currentScriptElement->stack[labelIdx];
     1458        debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx);
     1459        _pos = _labels[labelIdx];
     1460        return 0;
    11801461}
    11811462
    1182 void o1_gotoIfSup() {
     1463int FWScript::o1_gotoIfSup() {
    11831464        byte labelIdx = getNextByte();
    11841465
    1185         if (_currentScriptElement->compareResult == kCmpGT) {
    1186                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1466        if (_compare == kCmpGT) {
     1467                assert(_labels[labelIdx] != -1);
    11871468
    1188                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx);
    1189                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1469                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx);
     1470                _pos = _labels[labelIdx];
    11901471        } else {
    1191                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx);
     1472                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx);
    11921473        }
     1474        return 0;
    11931475}
    11941476
    1195 void o1_gotoIfSupEqu() {
     1477int FWScript::o1_gotoIfSupEqu() {
    11961478        byte labelIdx = getNextByte();
    11971479
    1198         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1199                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1480        if (_compare & (kCmpGT | kCmpEQ)) {
     1481                assert(_labels[labelIdx] != -1);
    12001482
    1201                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx);
    1202                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1483                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx);
     1484                _pos = _labels[labelIdx];
    12031485        } else {
    1204                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx);
     1486                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx);
    12051487        }
     1488        return 0;
    12061489}
    12071490
    1208 void o1_gotoIfInf() {
     1491int FWScript::o1_gotoIfInf() {
    12091492        byte labelIdx = getNextByte();
    12101493
    1211         if (_currentScriptElement->compareResult == kCmpLT) {
    1212                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1494        if (_compare == kCmpLT) {
     1495                assert(_labels[labelIdx] != -1);
    12131496
    1214                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx);
    1215                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1497                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx);
     1498                _pos = _labels[labelIdx];
    12161499        } else {
    1217                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx);
     1500                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx);
    12181501        }
     1502        return 0;
    12191503}
    12201504
    1221 void o1_gotoIfInfEqu() {
     1505int FWScript::o1_gotoIfInfEqu() {
    12221506        byte labelIdx = getNextByte();
    12231507
    1224         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1225                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1508        if (_compare & (kCmpLT | kCmpEQ)) {
     1509                assert(_labels[labelIdx] != -1);
    12261510
    1227                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx);
    1228                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1511                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx);
     1512                _pos = _labels[labelIdx];
    12291513        } else {
    1230                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx);
     1514                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx);
    12311515        }
     1516        return 0;
    12321517}
    12331518
    1234 void o1_gotoIfEqu() {
     1519int FWScript::o1_gotoIfEqu() {
    12351520        byte labelIdx = getNextByte();
    12361521
    1237         if (_currentScriptElement->compareResult == kCmpEQ) {
    1238                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1522        if (_compare == kCmpEQ) {
     1523                assert(_labels[labelIdx] != -1);
    12391524
    1240                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx);
    1241                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1525                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx);
     1526                _pos = _labels[labelIdx];
    12421527        } else {
    1243                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx);
     1528                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx);
    12441529        }
     1530        return 0;
    12451531}
    12461532
    1247 void o1_gotoIfDiff() {
     1533int FWScript::o1_gotoIfDiff() {
    12481534        byte labelIdx = getNextByte();
    12491535
    1250         if (_currentScriptElement->compareResult != kCmpEQ) {
    1251                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1536        if (_compare != kCmpEQ) {
     1537                assert(_labels[labelIdx] != -1);
    12521538
    1253                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx);
    1254                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1539                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx);
     1540                _pos = _labels[labelIdx];
    12551541        } else {
    1256                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx);
     1542                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx);
    12571543        }
     1544        return 0;
    12581545}
    12591546
    1260 void o1_removeLabel() {
     1547int FWScript::o1_removeLabel() {
    12611548        byte labelIdx = getNextByte();
    12621549
    1263         debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx);
    1264         _currentScriptElement->stack[labelIdx] = -1;
     1550        debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx);
     1551        _labels[labelIdx] = -1;
     1552        return 0;
    12651553}
    12661554
    1267 void o1_loop() {
     1555int FWScript::o1_loop() {
    12681556        byte varIdx = getNextByte();
    12691557        byte labelIdx = getNextByte();
    12701558
    1271         _currentScriptElement->localVars[varIdx]--;
     1559        _localVars[varIdx]--;
    12721560
    1273         if (_currentScriptElement->localVars[varIdx] >= 0) {
    1274                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1561        if (_localVars[varIdx] >= 0) {
     1562                assert(_labels[labelIdx] != -1);
    12751563
    1276                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx);
    1277                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1564                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx);
     1565                _pos = _labels[labelIdx];
    12781566        } else {
    1279                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx);
     1567                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx);
    12801568        }
     1569        return 0;
    12811570}
    12821571
    1283 void o1_startGlobalScript() {
     1572int FWScript::o1_startGlobalScript() {
    12841573        // OP_startScript
    12851574        byte param = getNextByte();
    12861575
    12871576        assert(param < NUM_MAX_SCRIPT);
    12881577
    1289         debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param);
     1578        debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param);
    12901579        addScriptToList0(param);
     1580        return 0;
    12911581}
    12921582
    1293 void o1_endGlobalScript() {
     1583int FWScript::o1_endGlobalScript() {
    12941584        byte scriptIdx = getNextByte();
    12951585
    1296         debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx);
    1297         stopGlobalScript(scriptIdx);
     1586        debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
     1587
     1588        ScriptList::iterator it = globalScripts.begin();
     1589
     1590        for (; it != globalScripts.end(); ++it) {
     1591                if ((*it)->index() == scriptIdx) {
     1592                        (*it)->_index = -1;
     1593                }
     1594        }
     1595
     1596        return 0;
    12981597}
    12991598
    1300 void o1_loadAnim() {
     1599int FWScript::o1_loadAnim() {
    13011600        // OP_loadResource
    13021601        const char *param = getNextString();
    13031602
    1304         debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param);
     1603        debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param);
    13051604        loadResource(param);
     1605        return 0;
    13061606}
    13071607
    1308 void o1_loadBg() {
     1608int FWScript::o1_loadBg() {
    13091609        const char *param = getNextString();
    13101610
    1311         debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param);
     1611        debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
    13121612
    13131613        loadBg(param);
    13141614        freeBgIncrustList();
    13151615        bgVar0 = 0;
     1616        return 0;
    13161617}
    13171618
    1318 void o1_loadCt() {
     1619int FWScript::o1_loadCt() {
    13191620        const char *param = getNextString();
    13201621
    1321         debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param);
     1622        debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
    13221623        loadCt(param);
     1624        return 0;
    13231625}
    13241626
    1325 void o1_loadPart() {
     1627int FWScript::o1_loadPart() {
    13261628        const char *param = getNextString();
    13271629
    1328         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     1630        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
    13291631        loadPart(param);
     1632        return 0;
    13301633}
    13311634
    1332 void o1_closePart() {
    1333         debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine);
     1635int FWScript::o1_closePart() {
     1636        debugC(5, kCineDebugScript, "Line: %d: closePart", _line);
    13341637        closePart();
     1638        return 0;
    13351639}
    13361640
    1337 void o1_loadNewPrcName() {
     1641int FWScript::o1_loadNewPrcName() {
    13381642        // OP_loadData
    13391643        byte param1 = getNextByte();
    13401644        const char *param2 = getNextString();
     
    13431647
    13441648        switch (param1) {
    13451649        case 0:
    1346                 debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2);
     1650                debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2);
    13471651                strcpy(newPrcName, param2);
    13481652                break;
    13491653        case 1:
    1350                 debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2);
     1654                debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2);
    13511655                strcpy(newRelName, param2);
    13521656                break;
    13531657        case 2:
    1354                 debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2);
     1658                debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2);
    13551659                strcpy(newObjectName, param2);
    13561660                break;
    13571661        case 3:
    1358                 debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2);
     1662                debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2);
    13591663                strcpy(newMsgName, param2);
    13601664                break;
    13611665        }
     1666        return 0;
    13621667}
    13631668
    1364 void o1_requestCheckPendingDataLoad() {
    1365         debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine);
     1669int FWScript::o1_requestCheckPendingDataLoad() {
     1670        debugC(5, kCineDebugScript, "Line: %d: request data load", _line);
    13661671        checkForPendingDataLoadSwitch = 1;
     1672        return 0;
    13671673}
    13681674
    1369 void o1_blitAndFade() {
    1370         debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine);
     1675int FWScript::o1_blitAndFade() {
     1676        debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
    13711677        // TODO: use real code
    13721678
    13731679        drawOverlays();
    13741680        fadeRequired = true;
    13751681        flip();
     1682        return 0;
    13761683}
    13771684
    1378 void o1_fadeToBlack() {
    1379         debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine);
     1685int FWScript::o1_fadeToBlack() {
     1686        debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
    13801687
    13811688        fadeToBlack();
     1689        return 0;
    13821690}
    13831691
    1384 void o1_transformPaletteRange() {
     1692int FWScript::o1_transformPaletteRange() {
    13851693        byte startColor = getNextByte();
    13861694        byte numColor = getNextByte();
    13871695        uint16 r = getNextWord();
    13881696        uint16 g = getNextWord();
    13891697        uint16 b = getNextWord();
    13901698
    1391         debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _currentLine, startColor, numColor, r, g, b);
     1699        debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
    13921700
    13931701        transformPaletteRange(startColor, numColor, r, g, b);
     1702        return 0;
    13941703}
    13951704
    1396 void o1_setDefaultMenuColor2() {
     1705int FWScript::o1_setDefaultMenuColor2() {
    13971706        byte param = getNextByte();
    13981707
    1399         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param);
     1708        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
    14001709        defaultMenuBoxColor2 = param;
     1710        return 0;
    14011711}
    14021712
    1403 void o1_palRotate() {
     1713int FWScript::o1_palRotate() {
    14041714        byte a = getNextByte();
    14051715        byte b = getNextByte();
    14061716        byte c = getNextByte();
    14071717
    1408         debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c);
     1718        debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
    14091719        palRotate(a, b, c);
     1720        return 0;
    14101721}
    14111722
    1412 void o1_break() {
    1413         debugC(5, kCineDebugScript, "Line: %d: break", _currentLine);
     1723/*!\brief Pause script
     1724 * \todo Make sure it works
     1725 */
     1726int FWScript::o1_break() {
     1727        debugC(5, kCineDebugScript, "Line: %d: break", _line);
    14141728
    1415         _currentScriptElement->scriptPosition = _currentPosition;
    1416         _closeScript = 1;
     1729        return 1;
    14171730}
    14181731
    1419 void o1_endScript() {
    1420         debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine);
     1732/*! \brief Terminate script
     1733 * \todo Make sure it works
     1734 */
     1735int FWScript::o1_endScript() {
     1736        debugC(5, kCineDebugScript, "Line: %d: endScript", _line);
    14211737
    1422         if (_currentScriptParams == 0) {
    1423                 endScript0(_currentScriptElement->scriptIdx);
    1424         } else {
    1425                 endScript1(_currentScriptElement->scriptIdx);
    1426         }
    1427 
    1428         _closeScript = 1;
     1738        return -1;
    14291739}
    14301740
    1431 void o1_message() {
     1741int FWScript::o1_message() {
    14321742        byte param1 = getNextByte();
    14331743        uint16 param2 = getNextWord();
    14341744        uint16 param3 = getNextWord();
    14351745        uint16 param4 = getNextWord();
    14361746        uint16 param5 = getNextWord();
    14371747
    1438         debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5);
     1748        debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5);
    14391749
    14401750        addMessage(param1, param2, param3, param4, param5);
     1751        return 0;
    14411752}
    14421753
    1443 void o1_loadGlobalVar() {
     1754int FWScript::o1_loadGlobalVar() {
    14441755        byte varIdx = getNextByte();
    14451756        byte varType = getNextByte();
    14461757
     
    14481759                byte dataIdx = getNextByte();
    14491760
    14501761                if (varType == 1) {
    1451                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    1452                         globalVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1762                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx);
     1763                        _globalVars[varIdx] = _localVars[dataIdx];
    14531764                } else {
    1454                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    1455                         globalVars[varIdx] = globalVars[dataIdx];
     1765                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1766                        _globalVars[varIdx] = _globalVars[dataIdx];
    14561767                }
    14571768        } else {
    14581769                uint16 value = getNextWord();
    14591770
    1460                 debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value);
    1461                 globalVars[varIdx] = value;
     1771                debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value);
     1772                _globalVars[varIdx] = value;
    14621773        }
     1774
     1775        return 0;
    14631776}
    14641777
    1465 void o1_compareGlobalVar() {
     1778int FWScript::o1_compareGlobalVar() {
    14661779        byte varIdx = getNextByte();
    14671780        byte varType = getNextByte();
    14681781
    14691782        if (varType) {
    14701783                byte value = getNextByte();
    14711784
    1472                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value);
    1473                 _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]);
     1785                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value);
     1786                _compare = compareVars(_globalVars[varIdx], _localVars[value]);
    14741787        } else {
    14751788                uint16 value = getNextWord();
    14761789
    1477                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value);
     1790                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
    14781791
    14791792                if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) {       // TODO: fix
    1480                         _currentScriptElement->compareResult = 1;
     1793                        _compare = 1;
    14811794                } else {
    1482                         _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value);
     1795                        _compare = compareVars(_globalVars[varIdx], value);
    14831796                }
    14841797        }
     1798
     1799        return 0;
    14851800}
    14861801
    1487 void o1_declareFunctionName() {
     1802int FWScript::o1_declareFunctionName() {
    14881803        const char *param = getNextString();
    14891804
    1490         debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param);
     1805        debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param);
     1806        return 0;
    14911807}
    14921808
    1493 void o1_freePartRange() {
     1809int FWScript::o1_freePartRange() {
    14941810        byte startIdx = getNextByte();
    14951811        byte numIdx = getNextByte();
    14961812
    14971813        assert(startIdx + numIdx <= NUM_MAX_ANIMDATA);
    14981814
    1499         debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx);
     1815        debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx);
    15001816        freeAnimDataRange(startIdx, numIdx);
     1817        return 0;
    15011818}
    15021819
    1503 void o1_unloadAllMasks() {
    1504         debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine);
     1820int FWScript::o1_unloadAllMasks() {
     1821        debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
    15051822        unloadAllMasks();
     1823        return 0;
    15061824}
    15071825
    1508 void o1_setScreenDimensions() {
     1826/*! \todo Implement this instruction
     1827 */
     1828int FWScript::o1_setScreenDimensions() {
    15091829        warning("STUB: o1_setScreenDimensions()");
    15101830        getNextWord();
    15111831        getNextWord();
    15121832        getNextWord();
    15131833        getNextWord();
    15141834        // setupScreenParam
     1835        return 0;
    15151836}
    15161837
    1517 void o1_displayBackground() {
     1838/*! \todo Implement this instruction
     1839 */
     1840int FWScript::o1_displayBackground() {
    15181841        warning("STUB: o1_displayBackground()");
     1842        return 0;
    15191843}
    15201844
    1521 void o1_initializeZoneData() {
    1522         debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine);
     1845int FWScript::o1_initializeZoneData() {
     1846        debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
    15231847
    15241848        for (int i = 0; i < NUM_MAX_ZONE; i++) {
    15251849                zoneData[i] = i;
    15261850        }
     1851        return 0;
    15271852}
    15281853
    1529 void o1_setZoneDataEntry() {
     1854int FWScript::o1_setZoneDataEntry() {
    15301855        byte zoneIdx = getNextByte();
    15311856        uint16 var = getNextWord();
    15321857
    1533         debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var);
     1858        debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
    15341859        zoneData[zoneIdx] = var;
     1860        return 0;
    15351861}
    15361862
    1537 void o1_getZoneDataEntry() {
     1863int FWScript::o1_getZoneDataEntry() {
    15381864        byte zoneIdx = getNextByte();
    15391865        byte var = getNextByte();
    15401866
    1541         _currentScriptElement->localVars[var] = zoneData[zoneIdx];
     1867        _localVars[var] = zoneData[zoneIdx];
     1868        return 0;
    15421869}
    15431870
    1544 void o1_setDefaultMenuColor() {
     1871int FWScript::o1_setDefaultMenuColor() {
    15451872        byte param = getNextByte();
    15461873
    1547         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param);
     1874        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
    15481875        defaultMenuBoxColor = param;
     1876        return 0;
    15491877}
    15501878
    1551 void o1_allowPlayerInput() {
    1552         debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine);
     1879int FWScript::o1_allowPlayerInput() {
     1880        debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line);
    15531881        allowPlayerInput = 1;
     1882        return 0;
    15541883}
    15551884
    1556 void o1_disallowPlayerInput() {
    1557         debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine);
     1885int FWScript::o1_disallowPlayerInput() {
     1886        debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line);
    15581887        allowPlayerInput = 0;
     1888        return 0;
    15591889}
    15601890
    1561 void o1_changeDataDisk() {
     1891int FWScript::o1_changeDataDisk() {
    15621892        byte newDisk = getNextByte();
    15631893
    1564         debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk);
     1894        debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk);
    15651895        checkDataDisk(newDisk);
     1896        return 0;
    15661897}
    15671898
    1568 void o1_loadMusic() {
     1899int FWScript::o1_loadMusic() {
    15691900        const char *param = getNextString();
    15701901
    1571         debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param);
     1902        debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param);
    15721903        g_sound->loadMusic(param);
     1904        return 0;
    15731905}
    15741906
    1575 void o1_playMusic() {
    1576         debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
     1907int FWScript::o1_playMusic() {
     1908        debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line);
    15771909        g_sound->playMusic();
     1910        return 0;
    15781911}
    15791912
    1580 void o1_fadeOutMusic() {
    1581         debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
     1913int FWScript::o1_fadeOutMusic() {
     1914        debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line);
    15821915        g_sound->fadeOutMusic();
     1916        return 0;
    15831917}
    15841918
    1585 void o1_stopSample() {
    1586         debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
     1919int FWScript::o1_stopSample() {
     1920        debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line);
    15871921        g_sound->stopMusic();
     1922        return 0;
    15881923}
    15891924
    1590 void o1_op71() {
     1925/*! \todo Implement this instruction
     1926 */
     1927int FWScript::o1_op71() {
    15911928        warning("STUB: o1_op71()");
    15921929        getNextByte();
    15931930        getNextWord();
     1931        return 0;
    15941932}
    15951933
    1596 void o1_op72() {
     1934/*! \todo Implement this instruction
     1935 */
     1936int FWScript::o1_op72() {
    15971937        warning("STUB: o1_op72()");
    15981938        getNextWord();
    15991939        getNextByte();
    16001940        getNextWord();
     1941        return 0;
    16011942}
    16021943
    1603 void o1_op73() {
     1944/*! \todo Implement this instruction
     1945 */
     1946int FWScript::o1_op73() {
    16041947        // I believe this opcode is identical to o1_op72(). In fact, Operation
    16051948        // Stealth doesn't even have it. It uses o1_op72() instead.
    16061949        warning("STUB: o1_op73()");
    16071950        getNextWord();
    16081951        getNextByte();
    16091952        getNextWord();
     1953        return 0;
    16101954}
    16111955
    1612 void o1_playSample() {
    1613         debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
     1956int FWScript::o1_playSample() {
     1957        debugC(5, kCineDebugScript, "Line: %d: playSample()", _line);
    16141958
    16151959        byte anim = getNextByte();
    16161960        byte channel = getNextByte();
     
    16221966        uint16 size = getNextWord();
    16231967
    16241968        if (!animDataTable[anim].ptr1) {
    1625                 return;
     1969                return 0;
    16261970        }
    16271971
    16281972        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
     
    16582002                        volume = 50;
    16592003                }
    16602004                if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
    1661                         return;
     2005                        return 0;
    16622006                }
    16632007                g_sound->stopMusic();
    16642008                if (size == 0xFFFF) {
     
    16672011                        g_sound->stopSound(channel);
    16682012                }
    16692013        }
     2014        return 0;
    16702015}
    16712016
    1672 void o1_disableSystemMenu() {
     2017int FWScript::o1_disableSystemMenu() {
    16732018        byte param = getNextByte();
    16742019
    1675         debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param);
     2020        debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
    16762021        disableSystemMenu = (param != 0);
     2022        return 0;
    16772023}
    16782024
    1679 void o1_loadMask5() {
     2025int FWScript::o1_loadMask5() {
    16802026        byte param = getNextByte();
    16812027
    1682         debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param);
     2028        debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
    16832029        loadOverlayElement(param, 5);
     2030        return 0;
    16842031}
    16852032
    1686 void o1_unloadMask5() {
     2033int FWScript::o1_unloadMask5() {
    16872034        byte param = getNextByte();
    16882035
    1689         debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param);
     2036        debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
    16902037        freeOverlay(param, 5);
     2038        return 0;
    16912039}
    16922040
    16932041// ------------------------------------------------------------------------
    16942042// OPERATION STEALTH opcodes
    16952043// ------------------------------------------------------------------------
    16962044
    1697 void o2_loadPart() {
     2045int FWScript::o2_loadPart() {
    16982046        const char *param = getNextString();
    16992047
    1700         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     2048        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
     2049        return 0;
    17012050}
    17022051
    1703 void o2_playSample() {
     2052int FWScript::o2_playSample() {
    17042053        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    17052054                // no-op in these versions
    17062055                getNextByte();
     
    17092058                getNextByte();
    17102059                getNextWord();
    17112060                getNextWord();
    1712                 return;
     2061                return 0;
    17132062        }
    1714         o1_playSample();
     2063        return o1_playSample();
    17152064}
    17162065
    1717 void o2_playSampleAlt() {
     2066int FWScript::o2_playSampleAlt() {
    17182067        byte num = getNextByte();
    17192068        byte channel = getNextByte();
    17202069        uint16 frequency = getNextWord();
     
    17352084                        g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0);
    17362085                }
    17372086        }
     2087        return 0;
    17382088}
    17392089
    1740 void o2_addSeqListElement() {
     2090int FWScript::o2_addSeqListElement() {
    17412091        byte param1 = getNextByte();
    17422092        byte param2 = getNextByte();
    17432093        byte param3 = getNextByte();
     
    17462096        uint16 param6 = getNextWord();
    17472097        uint16 param7 = getNextWord();
    17482098
    1749         debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7);
     2099        debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
    17502100        addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
     2101        return 0;
    17512102}
    17522103
    1753 void o2_removeSeq() {
     2104int FWScript::o2_removeSeq() {
    17542105        byte a = getNextByte();
    17552106        byte b = getNextByte();
    17562107
    1757         debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b);
     2108        debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
    17582109        removeSeq(a, 0, b);
     2110        return 0;
    17592111}
    17602112
    1761 void o2_op81() {
     2113/*! \todo Implement this instruction
     2114 */
     2115int FWScript::o2_op81() {
    17622116        warning("STUB: o2_op81()");
    17632117        // freeUnkList();
     2118        return 0;
    17642119}
    17652120
    1766 void o2_op82() {
     2121/*! \todo Implement this instruction
     2122 */
     2123int FWScript::o2_op82() {
    17672124        warning("STUB: o2_op82()");
    17682125        getNextByte();
    17692126        getNextByte();
    17702127        getNextWord();
     2128        return 0;
    17712129}
    17722130
    1773 void o2_isSeqRunning() {
     2131int FWScript::o2_isSeqRunning() {
    17742132        byte a = getNextByte();
    17752133        byte b = getNextByte();
    17762134
    1777         debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b);
     2135        debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
    17782136
    17792137        if (isSeqRunning(a, 0, b)) {
    1780                 _currentScriptElement->compareResult = 1;
     2138                _compare = 1;
    17812139        } else {
    1782                 _currentScriptElement->compareResult = 0;
     2140                _compare = 0;
    17832141        }
     2142        return 0;
    17842143}
    17852144
    1786 void o2_gotoIfSupNearest() {
     2145/*! \todo The assert may produce false positives and requires testing
     2146 */
     2147int FWScript::o2_gotoIfSupNearest() {
    17872148        byte labelIdx = getNextByte();
    17882149
    1789         if (_currentScriptElement->compareResult == kCmpGT) {
    1790                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2150        if (_compare == kCmpGT) {
     2151                assert(_labels[labelIdx] != -1);
    17912152
    1792                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx);
    1793                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2153                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
     2154                _pos = _script.getLabel(*_info, labelIdx, _pos);
    17942155        } else {
    1795                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx);
     2156                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
    17962157        }
     2158        return 0;
    17972159}
    17982160
    1799 void o2_gotoIfSupEquNearest() {
     2161/*! \todo The assert may produce false positives and requires testing
     2162 */
     2163int FWScript::o2_gotoIfSupEquNearest() {
    18002164        byte labelIdx = getNextByte();
    18012165
    1802         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1803                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2166        if (_compare & (kCmpGT | kCmpEQ)) {
     2167                assert(_labels[labelIdx] != -1);
    18042168
    1805                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx);
    1806                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2169                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
     2170                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18072171        } else {
    1808                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx);
     2172                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
    18092173        }
     2174        return 0;
    18102175}
    18112176
    1812 void o2_gotoIfInfNearest() {
     2177/*! \todo The assert may produce false positives and requires testing
     2178 */
     2179int FWScript::o2_gotoIfInfNearest() {
    18132180        byte labelIdx = getNextByte();
    18142181
    1815         if (_currentScriptElement->compareResult == kCmpLT) {
    1816                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2182        if (_compare == kCmpLT) {
     2183                assert(_labels[labelIdx] != -1);
    18172184
    1818                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx);
    1819                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2185                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
     2186                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18202187        } else {
    1821                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx);
     2188                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
    18222189        }
     2190        return 0;
    18232191}
    18242192
    1825 void o2_gotoIfInfEquNearest() {
     2193/*! \todo The assert may produce false positives and requires testing
     2194 */
     2195int FWScript::o2_gotoIfInfEquNearest() {
    18262196        byte labelIdx = getNextByte();
    18272197
    1828         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1829                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2198        if (_compare & (kCmpLT | kCmpEQ)) {
     2199                assert(_labels[labelIdx] != -1);
    18302200
    1831                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx);
    1832                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2201                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
     2202                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18332203        } else {
    1834                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx);
     2204                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
    18352205        }
     2206        return 0;
    18362207}
    18372208
    1838 void o2_gotoIfEquNearest() {
     2209/*! \todo The assert may produce false positives and requires testing
     2210 */
     2211int FWScript::o2_gotoIfEquNearest() {
    18392212        byte labelIdx = getNextByte();
    18402213
    1841         if (_currentScriptElement->compareResult == kCmpEQ) {
    1842                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2214        if (_compare == kCmpEQ) {
     2215                assert(_labels[labelIdx] != -1);
    18432216
    1844                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx);
    1845                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2217                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
     2218                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18462219        } else {
    1847                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx);
     2220                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
    18482221        }
     2222        return 0;
    18492223}
    18502224
    1851 void o2_gotoIfDiffNearest() {
     2225/*! \todo The assert may produce false positives and requires testing
     2226 */
     2227int FWScript::o2_gotoIfDiffNearest() {
    18522228        byte labelIdx = getNextByte();
    18532229
    1854         if (_currentScriptElement->compareResult != kCmpEQ) {
    1855                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2230        if (_compare != kCmpEQ) {
     2231                assert(_labels[labelIdx] != -1);
    18562232
    1857                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx);
    1858                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2233                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
     2234                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18592235        } else {
    1860                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx);
     2236                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
    18612237        }
     2238        return 0;
    18622239}
    18632240
    1864 void o2_startObjectScript() {
     2241int FWScript::o2_startObjectScript() {
    18652242        byte param = getNextByte();
    18662243
    1867         debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param);
     2244        debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
    18682245        runObjectScript(param);
     2246        return 0;
    18692247}
    18702248
    1871 void o2_stopObjectScript() {
     2249int FWScript::o2_stopObjectScript() {
    18722250        byte param = getNextByte();
    18732251
    1874         debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param);
    1875         stopObjectScript(param);
     2252        debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
     2253        ScriptList::iterator it = objectScripts.begin();
     2254
     2255        for (; it != objectScripts.end(); ++it) {
     2256                if ((*it)->index() == param) {
     2257                        (*it)->_index = -1;
     2258                }
     2259        }
     2260        return 0;
    18762261}
    18772262
    1878 void o2_op8D() {
     2263/*! \todo Implement this instruction
     2264 */
     2265int FWScript::o2_op8D() {
    18792266        warning("STUB: o2_op8D()");
    18802267        getNextWord();
    18812268        getNextWord();
     
    18862273        getNextWord();
    18872274        getNextWord();
    18882275        // _currentScriptElement->compareResult = ...
     2276        return 0;
    18892277}
    18902278
    1891 void o2_addBackground() {
     2279int FWScript::o2_addBackground() {
    18922280        byte param1 = getNextByte();
    18932281        const char *param2 = getNextString();
    18942282
    1895         debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1);
     2283        debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
    18962284        addBackground(param2, param1);
     2285        return 0;
    18972286}
    18982287
    1899 void o2_removeBackground() {
     2288int FWScript::o2_removeBackground() {
    19002289        byte param = getNextByte();
    19012290
    19022291        assert(param);
    19032292
    1904         debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param);
     2293        debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
    19052294
    19062295        if (additionalBgTable[param]) {
    19072296                free(additionalBgTable[param]);
     
    19172306        }
    19182307
    19192308        strcpy(currentBgName[param], "");
     2309        return 0;
    19202310}
    19212311
    1922 void o2_loadAbs() {
     2312int FWScript::o2_loadAbs() {
    19232313        byte param1 = getNextByte();
    19242314        const char *param2 = getNextString();
    19252315
    1926         debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2);
     2316        debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
    19272317        loadAbs(param2, param1);
     2318        return 0;
    19282319}
    19292320
    1930 void o2_loadBg() {
     2321int FWScript::o2_loadBg() {
    19312322        byte param = getNextByte();
    19322323
    19332324        assert(param <= 8);
    19342325
    1935         debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param);
     2326        debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
    19362327
    19372328        if (additionalBgTable[param]) {
    19382329                currentAdditionalBgIdx = param;
     
    19412332                //}
    19422333                fadeRequired = true;
    19432334        }
     2335        return 0;
    19442336}
    19452337
    1946 void o2_wasZoneChecked() {
     2338/*! \todo Implement this instruction
     2339 */
     2340int FWScript::o2_wasZoneChecked() {
    19472341        warning("STUB: o2_wasZoneChecked()");
     2342        return 0;
    19482343}
    19492344
    1950 void o2_op9B() {
     2345/*! \todo Implement this instruction
     2346 */
     2347int FWScript::o2_op9B() {
    19512348        warning("STUB: o2_op9B()");
    19522349        getNextWord();
    19532350        getNextWord();
     
    19572354        getNextWord();
    19582355        getNextWord();
    19592356        getNextWord();
     2357        return 0;
    19602358}
    19612359
    1962 void o2_op9C() {
     2360/*! \todo Implement this instruction
     2361 */
     2362int FWScript::o2_op9C() {
    19632363        warning("STUB: o2_op9C()");
    19642364        getNextWord();
    19652365        getNextWord();
    19662366        getNextWord();
    19672367        getNextWord();
     2368        return 0;
    19682369}
    19692370
    1970 void o2_useBgScroll() {
     2371int FWScript::o2_useBgScroll() {
    19712372        byte param = getNextByte();
    19722373
    19732374        assert(param <= 8);
    19742375
    1975         debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param);
     2376        debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
    19762377
    19772378        if (additionalBgTable[param]) {
    19782379                currentAdditionalBgIdx2 = param;
    19792380        }
     2381        return 0;
    19802382}
    19812383
    1982 void o2_setAdditionalBgVScroll() {
     2384int FWScript::o2_setAdditionalBgVScroll() {
    19832385        byte param1 = getNextByte();
    19842386
    19852387        if (param1) {
    19862388                byte param2 = getNextByte();
    19872389
    1988                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2);
    1989                 additionalBgVScroll = _currentScriptElement->localVars[param2];
     2390                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
     2391                additionalBgVScroll = _localVars[param2];
    19902392        } else {
    19912393                uint16 param2 = getNextWord();
    19922394
    1993                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2);
     2395                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
    19942396                additionalBgVScroll = param2;
    19952397        }
     2398        return 0;
    19962399}
    19972400
    1998 void o2_op9F() {
     2401/*! \todo Implement this instruction
     2402 */
     2403int FWScript::o2_op9F() {
    19992404        warning("o2_op9F()");
    20002405        getNextWord();
    20012406        getNextWord();
     2407        return 0;
    20022408}
    20032409
    2004 void o2_addGfxElementA0() {
     2410int FWScript::o2_addGfxElementA0() {
    20052411        uint16 param1 = getNextWord();
    20062412        uint16 param2 = getNextWord();
    20072413
    2008         debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2);
     2414        debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
    20092415        addGfxElementA0(param1, param2);
     2416        return 0;
    20102417}
    20112418
    2012 void o2_opA1() {
     2419/*! \todo Implement this instruction
     2420 */
     2421int FWScript::o2_opA1() {
    20132422        warning("STUB: o2_opA1()");
    20142423        getNextWord();
    20152424        getNextWord();
    20162425        // removeGfxElementA0( ... );
     2426        return 0;
    20172427}
    20182428
    2019 void o2_opA2() {
     2429/*! \todo Implement this instruction
     2430 */
     2431int FWScript::o2_opA2() {
    20202432        warning("STUB: o2_opA2()");
    20212433        getNextWord();
    20222434        getNextWord();
    20232435        // addGfxElementA2();
     2436        return 0;
    20242437}
    20252438
    2026 void o2_opA3() {
     2439/*! \todo Implement this instruction
     2440 */
     2441int FWScript::o2_opA3() {
    20272442        warning("STUB: o2_opA3()");
    20282443        getNextWord();
    20292444        getNextWord();
    20302445        // removeGfxElementA2();
     2446        return 0;
    20312447}
    20322448
    2033 void o2_loadMask22() {
     2449int FWScript::o2_loadMask22() {
    20342450        byte param = getNextByte();
    20352451
    2036         debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param);
     2452        debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
    20372453        loadOverlayElement(param, 22);
     2454        return 0;
    20382455}
    20392456
    2040 void o2_unloadMask22() {
     2457int FWScript::o2_unloadMask22() {
    20412458        byte param = getNextByte();
    20422459
    2043         debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param);
     2460        debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
    20442461        freeOverlay(param, 22);
     2462        return 0;
    20452463}
    20462464
    2047 // ------------------------------------------------------------------------
     2465//-----------------------------------------------------------------------
    20482466
    2049 void executeScript(prcLinkedListStruct *scriptElement, uint16 params) {
    2050         assert(scriptElement);
     2467void addGfxElementA0(int16 param1, int16 param2) {
     2468        overlayHeadElement *currentHead = &overlayHead;
     2469        overlayHeadElement *tempHead = currentHead;
     2470        overlayHeadElement *newElement;
    20512471
    2052         if (scriptElement->scriptIdx == -1) {
     2472        currentHead = tempHead->next;
     2473
     2474        while (currentHead) {
     2475                if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
     2476                        if (currentHead->type == 2 || currentHead->objIdx == 3) {
     2477                                break;
     2478                        }
     2479                }
     2480
     2481                tempHead = currentHead;
     2482                currentHead = currentHead->next;
     2483        }
     2484
     2485        if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
    20532486                return;
     2487
     2488        newElement = new overlayHeadElement;
     2489
     2490        newElement->next = tempHead->next;
     2491        tempHead->next = newElement;
     2492
     2493        newElement->objIdx = param1;
     2494        newElement->type = 20;
     2495
     2496        newElement->x = param2;
     2497        newElement->y = 0;
     2498        newElement->width = 0;
     2499        newElement->color = 0;
     2500
     2501        if (!currentHead)
     2502                currentHead = &overlayHead;
     2503
     2504        newElement->previous = currentHead->previous;
     2505
     2506        currentHead->previous = newElement;
     2507}
     2508
     2509void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
     2510        SeqListElement *currentHead = &seqList;
     2511        SeqListElement *tempHead = currentHead;
     2512
     2513        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2514                tempHead = currentHead;
     2515                currentHead = tempHead->next;
    20542516        }
    20552517
    2056         assert(scriptElement->scriptPtr);
     2518        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2519                currentHead->var4 = -1;
     2520        }
     2521}
    20572522
    2058         _currentScriptElement = scriptElement;
    2059         _currentScriptParams = params;
    2060         _currentScriptPtr = scriptElement->scriptPtr;
    2061         _currentPosition = scriptElement->scriptPosition;
     2523uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
     2524        SeqListElement *currentHead = &seqList;
     2525        SeqListElement *tempHead = currentHead;
    20622526
    2063         _closeScript = 0;
     2527        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2528                tempHead = currentHead;
     2529                currentHead = tempHead->next;
     2530        }
    20642531
    2065         while (!_closeScript) {
    2066                 _currentLine = _currentPosition;
     2532        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2533                return 1;
     2534        }
    20672535
    2068                 byte opcode = getNextByte();
     2536        return 0;
     2537}
    20692538
    2070                 if (opcode && opcode < _numOpcodes) {
    2071                         if (_opcodeTable[opcode - 1].proc)
    2072                                 (_opcodeTable[opcode - 1].proc) ();
    2073                         else
    2074                                 warning("Undefined opcode 0x%02X in executeScript", opcode - 1);
     2539void palRotate(byte a, byte b, byte c) {
     2540        if (c == 1) {
     2541                uint16 currentColor = c_palette[b];
     2542
     2543                for (int16 i = b; i > a; i--) {
     2544                        c_palette[i] = c_palette[i - 1];
    20752545                }
     2546
     2547                c_palette[a] = currentColor;
    20762548        }
    20772549}
    20782550
    2079 void executeList1(void) {
    2080         prcLinkedListStruct *currentHead = objScriptList.next;
     2551void addScriptToList0(uint16 idx) {
     2552        ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
     2553        assert(tmp);
     2554        globalScripts.push_back(tmp);
     2555}
    20812556
    2082         while (currentHead) {
    2083                 prcLinkedListStruct *tempHead;
     2557int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
     2558        byte *ptr = page + (y * width) + x / 2;
     2559        byte zoneVar;
    20842560
    2085                 tempHead = currentHead->next;
     2561        if (!(x % 2)) {
     2562                zoneVar = (*(ptr) >> 4) & 0xF;
     2563        } else {
     2564                zoneVar = (*(ptr)) & 0xF;
     2565        }
    20862566
    2087                 executeScript(currentHead, 1);
     2567        return zoneVar;
     2568}
    20882569
    2089                 currentHead = tempHead;
     2570int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
     2571        byte *ptr = page + (y * width) + x;
     2572        byte zoneVar;
     2573
     2574        zoneVar = (*(ptr)) & 0xF;
     2575
     2576        return zoneVar;
     2577}
     2578
     2579int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
     2580        int16 lx = objectTable[objIdx].x + x;
     2581        int16 ly = objectTable[objIdx].y + y;
     2582        int16 idx;
     2583
     2584        for (int16 i = 0; i < numZones; i++) {
     2585                idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     2586
     2587                assert(idx >= 0 && idx <= NUM_MAX_ZONE);
     2588
     2589                if (zoneData[idx] == zoneIdx) {
     2590                        return 1;
     2591                }
    20902592        }
     2593
     2594        return 0;
    20912595}
    20922596
    2093 void executeList0(void) {
    2094         prcLinkedListStruct *currentHead = globalScriptsHead.next;
     2597uint16 compareVars(int16 a, int16 b) {
     2598        uint16 flag = 0;
    20952599
    2096         while (currentHead) {
    2097                 prcLinkedListStruct *tempHead;
     2600        if (a == b) {
     2601                flag |= kCmpEQ;
     2602        } else if (a > b) {
     2603                flag |= kCmpGT;
     2604        } else if (a < b) {
     2605                flag |= kCmpLT;
     2606        }
    20982607
    2099                 executeScript(currentHead, 0);
     2608        return flag;
     2609}
    21002610
    2101                 tempHead = currentHead->next;
    2102                 currentHead = tempHead;
     2611void executeList1(void) {
     2612        ScriptList::iterator it = objectScripts.begin();
     2613        for (; it != objectScripts.end();) {
     2614                if ((*it)->index() < 0 || (*it)->execute() < 0) {
     2615                        it = objectScripts.erase(it);
     2616                } else {
     2617                        ++it;
     2618                }
    21032619        }
    21042620}
    21052621
     2622void executeList0(void) {
     2623        ScriptList::iterator it = globalScripts.begin();
     2624        for (; it != globalScripts.end();) {
     2625                if ((*it)->index() < 0 || (*it)->execute() < 0) {
     2626                        it = globalScripts.erase(it);
     2627                } else {
     2628                        ++it;
     2629                }
     2630        }
     2631}
     2632
     2633/*! \todo objectScripts.clear()?
     2634 */
    21062635void purgeList1(void) {
    21072636}
    21082637
     
    28043333                                sprintf(lineBuffer, "disallowPlayerInput()\n");
    28053334                                break;
    28063335                        }
    2807                 case OP_changeDataDisk:
     3336                case 0x6B:
    28083337                        {
    28093338                                byte newDisk;
    28103339
     
    28783407
    28793408                                if (opcode - 1 == 0x77) {
    28803409                                        sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    2881                                 else if (opcode - 1 == 0x78) {
     3410                                } else if (opcode - 1 == 0x78) {
    28823411                                        sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    28833412                                }
    28843413
  • engines/cine/main_loop.cpp

     
    192192                freeAnimDataTable();
    193193                resetMessageHead();
    194194                resetSeqList();
    195                 resetglobalScriptsHead();
    196                 resetObjectScriptHead();
    197195                resetBgIncrustList();
    198196
    199197                setTextWindow(0, 0, 20, 200);
     
    320318        g_sound->stopMusic();
    321319        freeAnimDataTable();
    322320        unloadAllMasks();
    323         freePrcLinkedList();
    324         releaseObjectScripts();
    325321        // if (g_cine->getGameType() == Cine::GType_OS) {
    326322        //      freeUnkList();
    327323        // }
  • engines/cine/cine.cpp

     
    124124                loadErrmessDat("errmess.dat");
    125125        }
    126126
     127        // in case ScummVM engines can be restarted in the future
     128        scriptTable.clear();
     129        relTable.clear();
     130        objectScripts.clear();
     131        globalScripts.clear();
     132
    127133        memset(objectTable, 0, sizeof(objectTable));
    128         memset(scriptTable, 0, sizeof(scriptTable));
    129134        memset(messageTable, 0, sizeof(messageTable));
    130         memset(relTable, 0, sizeof(relTable));
    131135
    132136        for (int i = 0; i < NUM_MAX_ANIMDATA; i++) {
    133137                animDataTable[i].ptr1 = animDataTable[i].ptr2 = NULL;
     
    138142        var8 = 0;
    139143        bgIncrustList = NULL;
    140144
    141         objScriptList.next = NULL;
    142         objScriptList.scriptPtr = NULL;
    143 
    144         globalScriptsHead.next = NULL;
    145         globalScriptsHead.scriptPtr = NULL;
    146 
    147145        var2 = var3 = var4 = var5 = 0;
    148146
    149         freePrcLinkedList();
    150 
    151147        _preLoad = false;
    152148        if (ConfMan.hasKey("save_slot")) {
    153149                char saveNameBuffer[256];
  • engines/cine/prc.cpp

     
    3333
    3434namespace Cine {
    3535
    36 prcLinkedListStruct globalScriptsHead;
    37 prcLinkedListStruct objScriptList;
     36ScriptList globalScripts;
     37ScriptList objectScripts;
    3838
    3939//char currentPrcName[20];
    4040
    41 void resetglobalScriptsHead(void) {
    42         globalScriptsHead.next = NULL;
    43         globalScriptsHead.scriptIdx = -1;
    44 }
    45 
    46 void freePrcLinkedList(void) {
    47         prcLinkedListStruct *currentHead = globalScriptsHead.next;
    48 
    49         while (currentHead) {
    50                 prcLinkedListStruct *temp;
    51 
    52                 assert(currentHead);
    53 
    54                 temp = currentHead->next;
    55 
    56                 delete currentHead;
    57 
    58                 currentHead = temp;
    59         }
    60 
    61         resetglobalScriptsHead();
    62 }
    63 
     41/*! \todo Is script size of 0 valid?
     42 * \todo Fix script dump code
     43 */
    6444void loadPrc(const char *pPrcName) {
    6545        byte i;
    6646        uint16 numScripts;
     
    6848
    6949        assert(pPrcName);
    7050
    71         for (i = 0; i < NUM_MAX_SCRIPT; i++) {
    72                 if (scriptTable[i].ptr) {
    73                         assert(scriptTable[i].ptr);
    74                         free(scriptTable[i].ptr);
    75                         scriptTable[i].ptr = NULL;
    76                         scriptTable[i].size = 0;
    77                 }
    78         }
     51        globalScripts.clear();
     52        scriptTable.clear();
    7953
    8054        // This is copy protection. Used to hang the machine
    8155        if (!scumm_stricmp(pPrcName, "L201.ANI")) {
     
    10074        assert(numScripts <= NUM_MAX_SCRIPT);
    10175
    10276        for (i = 0; i < numScripts; i++) {
    103                 scriptTable[i].size = READ_BE_UINT16(scriptPtr); scriptPtr += 2;
     77                RawScriptPtr tmp(new RawScript(READ_BE_UINT16(scriptPtr)));
     78                scriptPtr += 2;
     79                assert(tmp);
     80                scriptTable.push_back(tmp);
    10481        }
    10582
    10683        for (i = 0; i < numScripts; i++) {
    107                 uint16 size = scriptTable[i].size;
     84                uint16 size = scriptTable[i]->size();
     85                // TODO: delete the test?
    10886                if (size) {
    109                         scriptTable[i].ptr = (byte *) malloc(size);
    110                         assert(scriptTable[i].ptr);
    111                         memcpy(scriptTable[i].ptr, scriptPtr, size);
     87                        scriptTable[i]->setData(*scriptInfo, scriptPtr);
    11288                        scriptPtr += size;
    113                         computeScriptStack(scriptTable[i].ptr, scriptTable[i].stack, size);
    11489                }
    11590        }
    11691
  • engines/cine/rel.h

     
    2626#ifndef CINE_REL_H
    2727#define CINE_REL_H
    2828
     29#include "cine/script.h"
    2930namespace Cine {
    3031
    31 struct RelObjectScript {
    32         byte *data;
    33         uint16 size;
    34         uint16 obj1Param1;
    35         uint16 obj1Param2;
    36         uint16 obj2Param;
    37         uint16 runCount;
    38 };
     32extern RawObjectScriptArray relTable;
    3933
    40 #define NUM_MAX_REL 255
    41 
    42 extern RelObjectScript relTable[NUM_MAX_REL];
    43 
    44 void releaseObjectScripts(void);
    45 void resetObjectScriptHead(void);
    46 
    4734void loadRel(char *pRelName);
    4835
    4936} // End of namespace Cine