Ticket #8841: anim.patch

File anim.patch, 186.4 KB (added by SF/next_ghost, 16 years ago)

animData class and Operation Stealth fixes

  • 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_removeGfxElementA0();
     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/part.h

     
    3535        uint32 unpackedSize;
    3636};
    3737
    38 struct AnimData {
    39         uint16 width;
    40         uint16 var1;
    41         uint16 bpp;
    42         uint16 height;
    43 
    44         byte *ptr1;
    45         byte *ptr2;
    46         int16 fileIdx;
    47         int16 frameIdx;
    48         char name[10];
    49 
    50         // Not part of the data, but used when saving/restoring it.
    51         bool refresh;
    52 };
    53 
    5438#define NUM_MAX_PARTDATA 255
    55 #define NUM_MAX_ANIMDATA 255
    5639
    57 extern AnimData *animDataTable;
    5840extern PartBuffer *partBuffer;
    5941
    6042void loadPart(const char *partName);
  • 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/bg_list.cpp

     
    4141void addToBGList(int16 objIdx, bool addList) {
    4242        int16 x = objectTable[objIdx].x;
    4343        int16 y = objectTable[objIdx].y;
    44         int16 width = animDataTable[objectTable[objIdx].frame].var1;
    45         int16 height = animDataTable[objectTable[objIdx].frame].height;
    46 //      int16 part = objectTable[objIdx].part;
     44        int16 width = animDataTable[objectTable[objIdx].frame].var1();
     45        int16 height = animDataTable[objectTable[objIdx].frame].height();
     46        const byte *data = animDataTable[objectTable[objIdx].frame].data();
     47        const byte *mask = animDataTable[objectTable[objIdx].frame].mask();
     48        int16 part = objectTable[objIdx].part;
    4749
    4850        if (g_cine->getGameType() == GType_OS) {
    49                 drawSpriteRaw2(animDataTable[objectTable[objIdx].frame].ptr1, objectTable[objIdx].part, width, height, page2Raw, x, y);
     51                drawSpriteRaw2(data, part, width, height, page2Raw, x, y);
    5052        } else {
    51                 drawSpriteRaw(animDataTable[objectTable[objIdx].frame].ptr1, animDataTable[objectTable[objIdx].frame].ptr2, width, height, page2Raw, x, y);
     53                drawSpriteRaw(data, mask, width, height, page2Raw, x, y);
    5254        }
    5355
    54         if (addList)
     56        if (addList) {
    5557                createBgIncrustListElement(objIdx, 0);
     58        }
    5659}
    5760
    5861void addSpriteFilledToBGList(int16 objIdx, bool addList) {
    5962        int16 x = objectTable[objIdx].x;
    6063        int16 y = objectTable[objIdx].y;
    61         int16 width = animDataTable[objectTable[objIdx].frame].width;
    62         int16 height = animDataTable[objectTable[objIdx].frame].height;
     64        int16 width = animDataTable[objectTable[objIdx].frame].width();
     65        int16 height = animDataTable[objectTable[objIdx].frame].height();
     66        const byte *data = animDataTable[objectTable[objIdx].frame].data();
    6367
    64         if (animDataTable[objectTable[objIdx].frame].ptr1) {
    65                 gfxFillSprite(animDataTable[objectTable[objIdx].frame].ptr1, width / 2, height, page2Raw, x, y);
     68        if (data) {
     69                gfxFillSprite(data, width / 2, height, page2Raw, x, y);
    6670        }
    6771
    68         if (addList)
     72        if (addList) {
    6973                createBgIncrustListElement(objIdx, 1);
     74        }
    7075}
    7176
    7277void createBgIncrustListElement(int16 objIdx, int16 param) {
     
    8994
    9095        bgIncrustPtr->objIdx = objIdx;
    9196        bgIncrustPtr->param = param;
    92     bgIncrustPtr->x = objectTable[objIdx].x;
    93     bgIncrustPtr->y = objectTable[objIdx].y;
    94     bgIncrustPtr->frame = objectTable[objIdx].frame;
    95     bgIncrustPtr->part = objectTable[objIdx].part;
     97        bgIncrustPtr->x = objectTable[objIdx].x;
     98        bgIncrustPtr->y = objectTable[objIdx].y;
     99        bgIncrustPtr->frame = objectTable[objIdx].frame;
     100        bgIncrustPtr->part = objectTable[objIdx].part;
    96101}
    97102
    98103void freeBgIncrustList(void) {
     
    136141
    137142        bgIncrustPtr->objIdx = fHandle->readUint16BE();
    138143        bgIncrustPtr->param = fHandle->readUint16BE();
    139     bgIncrustPtr->x = fHandle->readUint16BE();
    140     bgIncrustPtr->y = fHandle->readUint16BE();
    141     bgIncrustPtr->frame = fHandle->readUint16BE();
    142     bgIncrustPtr->part = fHandle->readUint16BE();
     144        bgIncrustPtr->x = fHandle->readUint16BE();
     145        bgIncrustPtr->y = fHandle->readUint16BE();
     146        bgIncrustPtr->frame = fHandle->readUint16BE();
     147        bgIncrustPtr->part = fHandle->readUint16BE();
    143148}
    144149
    145150void reincrustAllBg(void) {
  • engines/cine/anim.cpp

     
    2323 *
    2424 */
    2525
     26/*! \file
     27 * \todo Make resource manager class and make load* functions its members
     28 */
    2629
    2730#include "common/endian.h"
    2831#include "common/stream.h"
     
    4649        uint16 field_E;
    4750};
    4851
    49 static uint16 animDataCount = 0;
     52animData animDataTable[NUM_MAX_ANIMDATA];
    5053
    51 AnimHeaderStruct animHeader;
    52 
    53 static const AnimDataEntry animData[] = {
     54static const AnimDataEntry transparencyData[] = {
    5455        {"ALPHA", 0xF},
    5556        {"TITRE2", 0xF},
    5657        {"ET", 0xC},
     
    184185        {"FIN", 0x9},
    185186};
    186187
    187 static void freeAnimData(byte idx) {
    188         assert(idx < NUM_MAX_ANIMDATA);
    189         if (animDataTable[idx].ptr1) {
    190                 free(animDataTable[idx].ptr1);
    191                 free(animDataTable[idx].ptr2);
    192                 memset(&animDataTable[idx], 0, sizeof(AnimData));
    193                 animDataTable[idx].fileIdx = -1;
    194                 animDataTable[idx].frameIdx = -1;
    195                 if (animDataCount > 0)
    196                         animDataCount--;
    197         }
    198 }
     188void convertMask(byte *dest, const byte *source, int16 width, int16 height);
     189void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
     190void convert8BBP(byte *dest, const byte *source, int16 width, int16 height);
     191void convert8BBP2(byte *dest, byte *source, int16 width, int16 height);
    199192
    200 void freeAnimDataRange(byte startIdx, byte numIdx) {
    201         for (byte i = 0; i < numIdx; i++) {
    202                 freeAnimData(i + startIdx);
    203         }
    204 }
     193animData::animData() : _width(0), _height(0), _bpp(0), _var1(0), _data(NULL),
     194        _mask(NULL), _fileIdx(-1), _frameIdx(-1), _size(0) {
    205195
    206 void freeAnimDataTable() {
    207         freeAnimDataRange(0, NUM_MAX_ANIMDATA);
     196        memset(_name, 0, 10);
    208197}
    209198
    210 static byte getAnimTransparentColor(const char *animName) {
    211         char name[15];
     199/*! \brief Copy constructor
     200 */
     201animData::animData(const animData &src) : _width(src._width),
     202        _height(src._height), _bpp(src._bpp), _var1(src._var1),
     203        _data(NULL), _mask(NULL), _fileIdx(src._fileIdx),
     204        _frameIdx(src._frameIdx), _size(src._size) {
    212205
    213         removeExtention(name, animName);
    214 
    215         for (int i = 0; i < ARRAYSIZE(animData); i++) {
    216                 if (!strcmp(name, animData[i].name)) {
    217                         return animData[i].color;
    218                 }
     206        if (src._data) {
     207                _data = new byte[_size];
     208                assert(_data);
     209                memcpy(_data, src._data, _size*sizeof(byte));
    219210        }
    220         return 0;
    221 }
    222211
    223 int16 allocFrame(uint16 width, uint16 height, int8 isMask) {
    224         uint16 i;
    225         uint32 frameSize;
    226 
    227         for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
    228                 if (!animDataTable[i].ptr1)
    229                         break;
     212        if(src._mask) {
     213                _mask = new byte[_size];
     214                assert(_mask);
     215                memcpy(_mask, src._mask, _size*sizeof(byte));
    230216        }
    231217
    232         if (i == NUM_MAX_ANIMDATA)
    233                 return -1;
     218        memset(_name, 0, 10);
     219        strcpy(_name, src._name);
     220}
    234221
    235         if (!isMask) {          // sprite + generated mask
    236                 frameSize = width * height;
     222/*! \brief Destructor
     223 */
     224animData::~animData() {
     225        clear();
     226}
    237227
    238                 animDataTable[i].ptr1 = (byte *)malloc(frameSize);
    239                 animDataTable[i].ptr2 = (byte *)malloc(frameSize);
    240         } else {
    241                 // mask
    242                 frameSize = width * height * 8;
     228/*! \brief Assingment operator
     229 */
     230animData &animData::operator=(const animData &src) {
     231        animData tmp = src;
     232        byte *ptr;
    243233
    244                 animDataTable[i].ptr1 = (byte *)malloc(frameSize);
    245                 animDataTable[i].ptr2 = NULL;
    246         }
     234        _width = tmp._width;
     235        _height = tmp._height;
     236        _bpp = tmp._bpp;
     237        _var1 = tmp._var1;
    247238
    248         animDataTable[i].width = width;
    249         animDataTable[i].var1 = width >> 3;
    250         animDataTable[i].bpp = 4;
    251         animDataTable[i].height = height;
     239        ptr = _data;
     240        _data = tmp._data;
     241        tmp._data = ptr;
    252242
    253         animDataTable[i].fileIdx = -1;
    254         animDataTable[i].frameIdx = -1;
     243        ptr = _mask;
     244        _mask = tmp._mask;
     245        tmp._mask = ptr;
    255246
    256         animDataCount++;
     247        _fileIdx = tmp._fileIdx;
     248        _frameIdx = tmp._frameIdx;
     249        memset(_name, 0, 10);
     250        strcpy(_name, tmp._name);
     251        _size = tmp._size;
    257252
    258         return i;
     253        return *this;
    259254}
    260255
    261 int16 reserveFrame(uint16 width, uint16 height, uint16 type, int16 idx) {
    262         uint16 i;
    263         uint32 frameSize;
     256/*! \brief Load and decode image frame
     257 * \param d Encoded image data
     258 * \param type Encoding type
     259 * \param w Image width
     260 * \param h Image height
     261 * \param file Data file index in bundle
     262 * \param frame Image frame index
     263 * \param n Part name
     264 * \param transparent Transparent color (for ANIM_MASKSPRITE)
     265 */
     266void animData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
     267        int16 frame, const char *n, byte transparent) {
    264268
    265         if (idx >= 0) {
    266                 i = (uint16) idx;
    267         } else {
    268                 for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
    269                         if (!animDataTable[i].ptr1)
    270                                 break;
    271                 }
     269        assert(d);
    272270
    273                 if (i == NUM_MAX_ANIMDATA)
    274                         return -1;
     271        if (_data) {
     272                clear();
    275273        }
    276274
    277         frameSize = width * height;
     275        _width = w * 2;
     276        _height = h;
     277        _var1 = _width >> 3;
     278        _data = NULL;
     279        _mask = NULL;
     280        _fileIdx = file;
     281        _frameIdx = frame;
     282        memset(_name, 0, 10);
     283        strcpy(_name, n);
    278284
    279         if (type == 4) {                // 256 color sprites
    280                 frameSize *= 2;
    281                 type = 8;
    282                 width *= 2;
    283         }
     285        switch (type) {
     286        case ANIM_RAW:
     287                _width = w;
     288                _var1 = w >> 3;
     289                _bpp = 4;
     290                _size = w * h;
     291                _data = new byte[_size];
     292                assert(_data);
     293                memcpy(_data, d, _size*sizeof(byte));
     294                break;
    284295
    285         if (type == 5) {
    286                 frameSize += 16;
    287         }
     296        case ANIM_MASK:
     297                _bpp = 1;
     298                _size = w * h * 8;
     299                _data = new byte[_size];
     300                assert(_data);
     301                convertMask(_data, d, w, h);
     302                break;
    288303
    289         frameSize *= 2;
     304        case ANIM_SPRITE:
     305                _bpp = 4;
     306                _size = w * h * 2;
     307                _data = new byte[_size];
     308                assert(_data);
     309                gfxConvertSpriteToRaw(_data, d, w, h);
     310                break;
    290311
    291         animDataTable[i].ptr1 = (byte *)malloc(frameSize);
     312        case ANIM_MASKSPRITE:
     313                _bpp = 4;
     314                _size = w * h * 2;
     315                _data = new byte[_size];
     316                _mask = new byte[_size];
     317                assert(_data && _mask);
     318                gfxConvertSpriteToRaw(_data, d, w, h);
     319                generateMask(_data, _mask, _size, transparent);
     320                break;
    292321
    293         assert(animDataTable[i].ptr1);
     322        case ANIM_PALSPRITE:
     323                _bpp = 5;
     324                _size = w * h * 2;
     325                _data = new byte[_size];
     326                assert(_data);
     327                convert8BBP(_data, d, w, h);
     328                break;
    294329
    295         animDataTable[i].width = width;
     330        case ANIM_FULLSPRITE:
     331                _bpp = 8;
     332                _var1 = _width >> 4;
     333                _size = w * h;
     334                _data = new byte[_size];
     335                assert(_data);
     336                convert8BBP2(_data, d, w, h);
     337                break;
    296338
    297         if (type == 5) {
    298                 animDataTable[i].var1 = width / 8;
    299         } else {
    300                 animDataTable[i].var1 = width / 16;
     339        default:
     340                error("animData::load: unknown image type");
    301341        }
     342}
    302343
    303         animDataTable[i].bpp = type;
     344/*! \brief Reset image
     345 */
     346void animData::clear() {
     347        delete[] _data;
     348        delete [] _mask;
    304349
    305         animDataTable[i].height = height;
     350        _width = 0;
     351        _height = 0;
     352        _bpp = 0;
     353        _var1 = 0;
     354        _data = NULL;
     355        _mask = NULL;
     356        _fileIdx = -1;
     357        _frameIdx = -1;
     358        memset(_name, 0, 10);
     359        _size = 0;
     360}
    306361
    307         animDataTable[i].fileIdx = -1;
    308         animDataTable[i].frameIdx = -1;
     362/*! \brief Write image identifiers to savefile
     363 * \param fHandle Savefile open for writing
     364 */
     365void animData::save(Common::OutSaveFile &fHandle) const {
     366        fHandle.writeUint16BE(_width);
     367        fHandle.writeUint16BE(_var1);
     368        fHandle.writeUint16BE(_bpp);
     369        fHandle.writeUint16BE(_height);
     370        // The save file format looks like Delphine guys
     371        // hacked it together 10 minutes before release deadline...
     372        // Just because I write pointers to a file doesn't mean
     373        // anyone should actually read those values back!
     374        fHandle.writeUint32BE((uint32)_data);
     375        fHandle.writeUint32BE((uint32)_mask);
     376        fHandle.writeUint16BE(_fileIdx);
     377        fHandle.writeUint16BE(_frameIdx);
     378        fHandle.write(_name, 10);
     379}
    309380
    310         animDataCount++;
     381/*! \brief Clear part of animDataTable
     382 * \param startIdx First image frame to be cleared
     383 * \param numIdx Number of image frames to be cleared
     384 */
     385void freeAnimDataRange(byte startIdx, byte numIdx) {
     386        for (byte i = 0; i < numIdx; i++) {
     387                animDataTable[startIdx + i].clear();
     388        }
     389}
    311390
    312         return i;
     391/*! \brief Clear whole animDataTable
     392 */
     393void freeAnimDataTable() {
     394        freeAnimDataRange(0, NUM_MAX_ANIMDATA);
    313395}
    314396
    315 void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) {
     397/*! \brief Find transparent color index for image
     398 * \brief animName Image file name
     399 */
     400static byte getAnimTransparentColor(const char *animName) {
     401        char name[15];
     402
     403        removeExtention(name, animName);
     404
     405        for (int i = 0; i < ARRAYSIZE(transparencyData); i++) {
     406                if (!strcmp(name, transparencyData[i].name)) {
     407                        return transparencyData[i].color;
     408                }
     409        }
     410        return 0;
     411}
     412
     413/*! \brief Generate mask for image
     414 * \param[in] sprite Image data
     415 * \param[out] mask Image mask
     416 * \param size Image data length
     417 * \param transparency Transparent color index
     418 */
     419void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency) {
    316420        for (uint16 i = 0; i < size; i++) {
    317421                if (*(sprite++) != transparency) {
    318422                        *(mask++) = 0;
     
    322426        }
    323427}
    324428
    325 void convertMask(byte * dest, byte * source, int16 width, int16 height) {
     429/*! \brief Decode 1bpp mask
     430 * \param[out] dest Decoded mask
     431 * \param[in] source Encoded mask
     432 * \param width Mask width
     433 * \param height Mask height
     434 */
     435void convertMask(byte *dest, const byte *source, int16 width, int16 height) {
    326436        int16 i, j;
    327437        byte maskEntry;
    328438
     
    335445        }
    336446}
    337447
    338 void convert4BBP(byte * dest, byte * source, int16 width, int16 height) {
     448/*! \brief Decode 4bpp sprite
     449 * \param[out] dest Decoded image
     450 * \param[in] source Encoded image
     451 * \param width Image width
     452 * \param height Image height
     453 */
     454void convert4BBP(byte *dest, const byte *source, int16 width, int16 height) {
    339455        byte maskEntry;
    340456
    341457        for (int16 i = 0; i < width * height; i++) {
     
    345461        }
    346462}
    347463
    348 void loadAnimHeader(Common::MemoryReadStream readS) {
     464/*! \brief Read image header
     465 * \param[out] animHeader Image header reference
     466 * \param readS Input stream open for reading
     467 */
     468void loadAnimHeader(AnimHeaderStruct &animHeader, Common::MemoryReadStream readS) {
    349469        animHeader.field_0 = readS.readByte();
    350470        animHeader.field_1 = readS.readByte();
    351471        animHeader.field_2 = readS.readByte();
     
    366486        animHeader.field_14 = readS.readUint16BE();
    367487}
    368488
     489/*! \brief Find next empty space animDataTable
     490 * \param start First index to check
     491 */
     492int emptyAnimSpace(int start = 0) {
     493        for (; start < NUM_MAX_ANIMDATA; start++) {
     494                if (!animDataTable[start].data()) {
     495                        return start;
     496                }
     497        }
     498
     499        return -1;
     500}
     501
     502/*! \brief Load SPL data into animDataTable
     503 * \param resourceName SPL filename
     504 * \param idx Target index in animDataTable
     505 */
    369506void loadSpl(const char *resourceName, int16 idx) {
    370507        int16 foundFileIdx = findFileInBundle(resourceName);
    371         int16 entry;
     508        int entry;
    372509        byte *dataPtr = readBundleFile(foundFileIdx);
    373510
    374         if (idx >= 0) {
    375                 entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
    376                 memcpy(animDataTable[entry].ptr1, dataPtr, partBuffer[foundFileIdx].unpackedSize);
    377         } else {
    378                 entry = allocFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, -1);
    379                 assert(entry != -1);
    380                 memcpy(animDataTable[entry].ptr1, dataPtr, (uint16) partBuffer[foundFileIdx].unpackedSize);
     511        entry = idx < 0 ? emptyAnimSpace() : idx;
     512        assert(entry >= 0);
     513        animDataTable[entry].load(dataPtr, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
    381514
    382                 animDataTable[entry].fileIdx = foundFileIdx;
    383                 animDataTable[entry].frameIdx = 0;
    384                 strcpy(animDataTable[entry].name, currentPartName);
    385         }
    386 
    387515        free(dataPtr);
    388516}
    389517
     518/*! \brief Load 1bpp mask
     519 * \param resourceName Mask filename
     520 */
    390521void loadMsk(const char *resourceName) {
    391522        int16 foundFileIdx = findFileInBundle(resourceName);
    392         int16 entry;
     523        int entry = 0;
    393524        byte *dataPtr = readBundleFile(foundFileIdx);
    394525        byte *ptr;
     526        AnimHeaderStruct animHeader;
    395527
    396528        Common::MemoryReadStream readS(dataPtr, 0x16);
    397         loadAnimHeader(readS);
     529        loadAnimHeader(animHeader, readS);
    398530        ptr = dataPtr + 0x16;
    399531
    400         for (int16 i = 0; i < animHeader.numFrames; i++) {
    401                 entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 1);
    402 
    403                 assert(entry != -1);
    404 
    405                 convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth, animHeader.frameHeight);
     532        for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
     533                entry = emptyAnimSpace(entry);
     534                assert(entry >= 0);
     535                animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
    406536                ptr += animHeader.frameWidth * animHeader.frameHeight;
    407 
    408                 animDataTable[entry].fileIdx = foundFileIdx;
    409                 animDataTable[entry].frameIdx = i;
    410                 strcpy(animDataTable[entry].name, currentPartName);
    411537        }
    412538
    413539        free(dataPtr);
    414540}
    415541
     542/*! \brief Load animation
     543 * \param resourceName Animation filename
     544 */
    416545void loadAni(const char *resourceName) {
    417546        int16 foundFileIdx = findFileInBundle(resourceName);
    418         int16 entry;
     547        int entry = 0;
    419548        byte *dataPtr = readBundleFile(foundFileIdx);
    420         byte *ptr, *animPtr;
     549        byte *ptr;
    421550        byte transparentColor;
    422         uint32 fullSize;
     551        AnimHeaderStruct animHeader;
    423552
    424553        Common::MemoryReadStream readS(dataPtr, 0x16);
    425         loadAnimHeader(readS);
     554        loadAnimHeader(animHeader, readS);
    426555        ptr = dataPtr + 0x16;
    427556
    428557        transparentColor = getAnimTransparentColor(resourceName);
    429558
    430         fullSize = animHeader.frameWidth * animHeader.frameHeight;
     559        for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
     560                entry = emptyAnimSpace(entry);
     561                assert(entry >= 0);
    431562
    432         for (int16 i = 0; i < animHeader.numFrames; i++) {
    433                 entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 0);
    434 
    435                 assert(entry != -1);
    436 
    437563                // special case transparency handling
    438564                if (!strcmp(resourceName, "L2202.ANI")) {
    439                         if (i < 2) {
    440                                 transparentColor = 0;
    441                         } else {
    442                                 transparentColor = 7;
    443                         }
     565                        transparentColor = i < 2 ? 0 : 7;
     566                } else if (!strcmp(resourceName, "L4601.ANI")) {
     567                        transparentColor = i < 1 ? 0xE : 0;
    444568                }
    445569
    446                 if (!strcmp(resourceName, "L4601.ANI")) {
    447                         if (i < 1) {
    448                                 transparentColor = 0xE;
    449                         } else {
    450                                 transparentColor = 0;
    451                         }
    452                 }
    453 
    454                 animPtr = (byte *)malloc(fullSize);
    455 
    456                 memcpy(animPtr, ptr, fullSize);
    457                 ptr += fullSize;
    458 
    459                 gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr, animHeader.frameWidth, animHeader.frameHeight);
    460 
    461                 generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2, animHeader.frameWidth * 2 * animHeader.frameHeight, transparentColor);
    462 
    463                 free(animPtr);
    464 
    465                 animDataTable[entry].fileIdx = foundFileIdx;
    466                 animDataTable[entry].frameIdx = i;
    467                 strcpy(animDataTable[entry].name, currentPartName);
     570                animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
     571                ptr += animHeader.frameWidth * animHeader.frameHeight;
    468572        }
    469573
    470574        free(dataPtr);
    471575}
    472576
    473 void convert8BBP(byte * dest, byte * source, int16 width, int16 height) {
    474         byte table[16];
     577/*! \brief Decode 16 color image with palette
     578 * \param[out] dest Decoded image
     579 * \param[in] source Encoded image
     580 * \param width Image width
     581 * \param height Image height
     582 */
     583void convert8BBP(byte *dest, const byte *source, int16 width, int16 height) {
     584        const byte *table = source;
    475585        byte color;
    476586
    477         memcpy(table, source, 16);
    478587        source += 16;
    479588
    480589        for (uint16 i = 0; i < width * height; i++) {
     
    485594        }
    486595}
    487596
    488 void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) {
    489         uint16 i, j, k, m;
     597/*! \brief Decode 8bit image
     598 * \param[out] dest Decoded image
     599 * \param[in] source Encoded image
     600 * \param width Image width
     601 * \param height Image height
     602 * \attention Data in source are destroyed during decoding
     603 */
     604void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
     605        uint16 i, j;
     606        int k, m;
    490607        byte color;
    491608
    492609        for (j = 0; j < (width * height) / 16; j++) {
    493610                // m = 0: even bits, m = 1: odd bits
    494                 for (m = 0; m < 2; m++) {
     611                for (m = 0; m <= 1; m++) {
    495612                        for (i = 0; i < 8; i++) {
    496613                                color = 0;
    497                                 for (k = 14 + m; k >= 0 + m; k = k - 2) {
     614                                for (k = 14 + m; k >= 0; k -= 2) {
    498615                                        color |= ((*(source + k) & 0x080) >> 7);
    499616                                        *(source + k) <<= 1;
    500617                                        if (k > 0 + m)
     
    508625        }       // end j
    509626}
    510627
     628/*! \brief Load image set
     629 * \param resourceName Image set filename
     630 * \param idx Target index in animDataTable
     631 */
    511632void loadSet(const char *resourceName, int16 idx) {
    512633        AnimHeader2Struct header2;
    513         uint32 fullSize;
    514634        uint16 numSpriteInAnim;
    515635        int16 foundFileIdx = findFileInBundle(resourceName);
    516         int16 entry, typeParam;
     636        int16 entry = idx >= 0 ? idx : 0;
    517637        byte *ptr, *startOfDataPtr, *dataPtr, *origDataPtr;
    518         byte table[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
     638        int type;
    519639
    520640        origDataPtr = dataPtr = readBundleFile(foundFileIdx);
    521641        assert(!memcmp(dataPtr, "SET", 3));
     
    526646
    527647        startOfDataPtr = ptr + numSpriteInAnim * 0x10;
    528648
    529         for (int16 i = 0; i < numSpriteInAnim; i++) {
    530                 typeParam = 0;
    531 
     649        for (int16 i = 0; i < numSpriteInAnim; i++, entry++) {
    532650                Common::MemoryReadStream readS(ptr, 0x10);
    533651
    534652                header2.field_0 = readS.readUint32BE();
     
    541659
    542660                ptr += 0x10;
    543661
    544                 fullSize = header2.width * header2.height;
     662                entry = idx < 0 ? emptyAnimSpace(entry) : idx + i;
     663                assert(entry >= 0);
    545664
    546                 if (header2.type == 5) {
    547                         fullSize += 16;
    548                 }
    549 
    550                 if (header2.type == 4) {
    551                         header2.type = 5;
    552                         typeParam = 1;
    553                 }
    554 
    555                 if (idx >= 0)
    556                         entry = reserveFrame(header2.width * 2, header2.height, header2.type, idx + i);
    557                 else
    558                         entry = reserveFrame(header2.width * 2, header2.height, header2.type, -1);
    559 
    560                 assert(entry != -1);
    561 
    562665                dataPtr = startOfDataPtr + header2.field_0;
    563666
    564                 if (typeParam) {
    565                         memcpy(animDataTable[entry].ptr1, table, 0x10);
    566                         gfxConvertSpriteToRaw(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
    567                         //memcpy(animDataTable[entry].ptr1 + 0x10, dataPtr, fullSize);
     667                if (header2.type == 1) {
     668                        type = ANIM_MASK;
     669                } else if (header2.type == 4) {
     670                        type = ANIM_SPRITE;
     671                } else if (header2.type == 5) {
     672                        type = ANIM_PALSPRITE;
    568673                } else {
    569                         if (header2.type == 1) {
    570                                 convert4BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
    571                         } else if (header2.type == 5) {
    572                                 convert8BBP(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
    573                         } else if (header2.type == 4) {
    574                                 error("loadSet: header2.type == 4");
    575                         } else {
    576                                 convert8BBP2(animDataTable[entry].ptr1, dataPtr, header2.width, header2.height);
    577                         }
     674                        type = ANIM_FULLSPRITE;
    578675                }
    579676
    580                 animDataTable[entry].fileIdx = foundFileIdx;
    581                 animDataTable[entry].frameIdx = i;
    582                 strcpy(animDataTable[entry].name, currentPartName);
     677                animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
    583678        }
    584679
    585680        free(origDataPtr);
    586681}
    587682
     683/*! \brief Load SEQ data into animDataTable
     684 * \param resourceName SEQ data filename
     685 * \param idx Target index in animDataTable
     686 */
    588687void loadSeq(const char *resourceName, int16 idx) {
    589688        int16 foundFileIdx = findFileInBundle(resourceName);
    590689        byte *dataPtr = readBundleFile(foundFileIdx);
    591         int16 entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
     690        int entry = idx < 0 ? emptyAnimSpace() : idx;
    592691
    593         memcpy(animDataTable[entry].ptr1, dataPtr + 0x16, (uint16) partBuffer[foundFileIdx].unpackedSize - 0x16);
     692        animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
    594693        free(dataPtr);
    595694}
    596695
     
    624723        error("loadResource: Cannot determine type for '%s'", resourceName);
    625724}
    626725
     726/*! \todo There seems to be some additional resource file that is not loaded
     727 */
    627728void loadAbs(const char *resourceName, uint16 idx) {
    628729        /* byte isMask = 0; */
    629730        /* byte isSpl = 0; */
     
    632733                loadSet(resourceName, idx);
    633734                return;
    634735        } else if (strstr(resourceName, ".H32")) {
     736                warning("Ignoring file %s (load at %d)", resourceName, idx);
    635737                return;
    636738        } else if (strstr(resourceName, ".SEQ")) {
    637739                loadSeq(resourceName, idx);
    638740                return;
    639741        } else if (strstr(resourceName, ".SPL")) {
    640                 loadSpl(resourceName, idx);
     742                warning("Ignoring file %s (load at %d)", resourceName, idx);
     743//              loadSpl(resourceName, idx);
    641744                return;
    642745        } else if (strstr(resourceName, ".AMI")) {
     746                warning("Ignoring file %s (load at %d)", resourceName, idx);
    643747                return;
    644748        } else if (strstr(resourceName, ".ANI")) {
     749                warning("Ignoring file %s (load at %d)", resourceName, idx);
    645750                return;
    646751        }
    647752
    648753        error("loadAbs: Cannot determine type for '%s'", resourceName);
    649754}
    650755
    651 void loadResourcesFromSave() {
    652         int16 currentAnim, foundFileIdx, fullSize, entry, i;
     756/*! \brief Load animDataTable from save
     757 * \param fHandle Savefile open for reading
     758 * \param broken Broken/correct file format switch
     759 * \todo Add Operation Stealth savefile support
     760 *
     761 * Unlike the old code, this one actually rebuilds the table one frame
     762 * at a time.
     763 */
     764void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
     765        int16 currentAnim, foundFileIdx;
    653766        int8 isMask = 0, isSpl = 0;
    654         byte *dataPtr, *ptr, *animPtr;
    655         char animName[256], part[256];
     767        byte *dataPtr, *ptr;
     768        char *animName, part[256];
    656769        byte transparentColor;
    657         AnimData *currentPtr;
     770        animData *currentPtr;
     771        AnimHeaderStruct animHeader;
    658772
     773        uint16 width, height, bpp, var1;
     774        int16  frame;
     775        char name[10];
     776        int type;
     777
    659778        strcpy(part, currentPartName);
    660779
    661780        for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim++) {
    662781                currentPtr = &animDataTable[currentAnim];
    663                 if (currentPtr->refresh && currentPtr->fileIdx != -1) {
    664                         if (strcmp(currentPartName, currentPtr->name)) {
    665                                 closePart();
    666                                 loadPart(currentPtr->name);
    667                         }
    668782
    669                         foundFileIdx = currentPtr->fileIdx;
     783                width = fHandle.readUint16BE();
     784                var1 = fHandle.readUint16BE();
     785                bpp = fHandle.readUint16BE();
     786                height = fHandle.readUint16BE();
    670787
    671                         strcpy(animName, partBuffer[foundFileIdx].partName);
    672                         ptr = dataPtr = readBundleFile(foundFileIdx);
    673 
    674                         isSpl  = (strstr(animName, ".SPL")) ? 1 : 0;
    675                         isMask = (strstr(animName, ".MSK")) ? 1 : 0;
    676 
    677                         if (isSpl) {
    678                                 animHeader.frameWidth = (uint16) partBuffer[foundFileIdx].unpackedSize;
    679                                 animHeader.frameHeight = 1;
    680                                 animHeader.numFrames = 1;
    681                                 isMask = -1;
    682                         } else {
    683                                 Common::MemoryReadStream readS(ptr, 0x22);
    684 
    685                                 loadAnimHeader(readS);
    686 
    687                                 ptr += 0x16;
     788                if (!broken) {
     789                        if (!fHandle.readUint32BE()) {
     790                                fHandle.skip(18);
     791                                continue;
    688792                        }
     793                        fHandle.readUint32BE();
     794                }
    689795
    690                         {
    691                                 fullSize = animHeader.frameWidth * animHeader.frameHeight;
     796                foundFileIdx = fHandle.readSint16BE();
     797                frame = fHandle.readSint16BE();
     798                fHandle.read(name, 10);
    692799
    693                                 loadRelatedPalette(animName);
     800                if (foundFileIdx < 0 || (broken && !fHandle.readByte())) {
     801                        continue;
     802                }
    694803
    695                                 transparentColor = getAnimTransparentColor(animName);
     804                if (strcmp(currentPartName, name)) {
     805                        closePart();
     806                        loadPart(name);
     807                }
    696808
    697                                 for (i = 0; i < animHeader.numFrames; i++) { // load all the frames
    698                                         // special case transparency handling
    699                                         if (!strcmp(animName, "L2202.ANI")) {
    700                                                 if (i < 2) {
    701                                                         transparentColor = 0;
    702                                                 } else {
    703                                                         transparentColor = 7;
    704                                                 }
    705                                         }
     809                animName = partBuffer[foundFileIdx].partName;
     810                ptr = dataPtr = readBundleFile(foundFileIdx);
    706811
    707                                         if (!strcmp(animName, "L4601.ANI")) {
    708                                                 if (i < 1) {
    709                                                         transparentColor = 0xE;
    710                                                 } else {
    711                                                         transparentColor = 0;
    712                                                 }
    713                                         }
     812                isSpl  = (strstr(animName, ".SPL")) ? 1 : 0;
     813                isMask = (strstr(animName, ".MSK")) ? 1 : 0;
    714814
    715                                         currentPtr[i].ptr1 = NULL;
    716                                         entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, isMask);
     815                if (isSpl) {
     816                        width = (uint16) partBuffer[foundFileIdx].unpackedSize;
     817                        height = 1;
     818                        frame = 0;
     819                        type = ANIM_RAW;
     820                } else {
     821                        Common::MemoryReadStream readS(ptr, 0x16);
     822                        loadAnimHeader(animHeader, readS);
     823                        ptr += 0x16;
    717824
    718                                         currentPtr->fileIdx = foundFileIdx;
     825                        width = animHeader.frameWidth;
     826                        height = animHeader.frameHeight;
    719827
    720                                         assert(entry != -1);
     828                        if (isMask) {
     829                                type = ANIM_MASK;
     830                        } else {
     831                                type = ANIM_MASKSPRITE;
    721832
    722                                         if (isSpl) {
    723                                                 memcpy(animDataTable[entry].ptr1, ptr, fullSize);
    724                                                 ptr += fullSize;
    725                                         } else {
    726                                                 if (!isMask) {
    727                                                         animPtr = (byte *)malloc(fullSize);
    728                                                         memcpy(animPtr, ptr, fullSize);
    729                                                         ptr += fullSize;
     833                                loadRelatedPalette(animName);
     834                                transparentColor = getAnimTransparentColor(animName);
    730835
    731                                                         gfxConvertSpriteToRaw(animDataTable[entry].ptr1, animPtr,
    732                                                                                 animHeader.frameWidth, animHeader.frameHeight);
    733                                                         generateMask(animDataTable[entry].ptr1, animDataTable[entry].ptr2,
    734                                                                                 animHeader.frameWidth * 2 *animHeader.frameHeight, transparentColor);
    735 
    736                                                         free(animPtr);
    737                                                 } else {
    738                                                         convertMask(animDataTable[entry].ptr1, ptr, animHeader.frameWidth,
    739                                                                                 animHeader.frameHeight);
    740                                                         ptr += fullSize;
    741                                                 }
    742                                         }
    743 
    744                                         //animDataTable[entry].fileIdx = foundFileIdx; // Only when reading from bundles
    745 
    746                                         animDataTable[entry].frameIdx = i;
    747                                         strcpy(animDataTable[entry].name, currentPartName);
     836                                // special case transparency handling
     837                                if (!strcmp(animName, "L2202.ANI")) {
     838                                        transparentColor = (frame < 2) ? 0 : 7;
     839                                } else if (!strcmp(animName, "L4601.ANI")) {
     840                                        transparentColor = (frame < 1) ? 0xE : 0;
    748841                                }
    749842                        }
     843                }
    750844
    751                         free(dataPtr);
    752                 }
     845                ptr += frame * width * height;
     846                currentPtr->load(ptr, type, width, height, foundFileIdx, frame, name, transparentColor);
     847                free(dataPtr);
    753848        }
    754849
    755850        loadPart(part);
  • 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) {
     
    250196                                part = objectTable[currentHead->objIdx].part;
    251197
    252198                                if (currentHead->type == 0) {
    253                                         threshold = animDataTable[frame].var1;
     199                                        threshold = animDataTable[frame].var1();
    254200                                } else {
    255                                         threshold = animDataTable[frame].width / 2;
     201                                        threshold = animDataTable[frame].width() / 2;
    256202                                }
    257203
    258                                 height = animDataTable[frame].height;
     204                                height = animDataTable[frame].height();
    259205
    260206                                xdif = x - objX;
    261207                                ydif = y - objY;
    262208
    263209                                if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) {
    264                                         if (animDataTable[frame].ptr1) {
     210                                        if (animDataTable[frame].data()) {
    265211                                                if (g_cine->getGameType() == Cine::GType_OS)
    266212                                                        return currentHead->objIdx;
    267213
    268214                                                if (currentHead->type == 0)     { // use generated mask
    269                                                         if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr2, animDataTable[frame].width)) {
     215                                                        if (gfxGetBit(x - objX, y - objY, animDataTable[frame].mask(), animDataTable[frame].width())) {
    270216                                                                return currentHead->objIdx;
    271217                                                        }
    272218                                                } else if (currentHead->type == 1) { // is mask
    273                                                         if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr1, animDataTable[frame].width * 4)) {
     219                                                        if (gfxGetBit(x - objX, y - objY, animDataTable[frame].data(), animDataTable[frame].width() * 4)) {
    274220                                                                return currentHead->objIdx;
    275221                                                        }
    276222                                                }
     
    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;
     319/*! \brief Savefile format tester
     320 * \param fHandle Savefile to check
     321 *
     322 * This function seeks through savefile and tries to guess if it's the original
     323 * savegame format or broken format from ScummVM 0.10/0.11
     324 * The test is incomplete but this should cover 99.99% of cases.
     325 * If anyone makes a savefile which could confuse this test, assert will
     326 * report it
     327 */
     328bool brokenSave(Common::InSaveFile &fHandle) {
     329        // Backward seeking not supported in compressed savefiles
     330        // if you really want it, finish it yourself
     331        return false;
    375332
    376         if (isGlobal)
    377                 currentHead = globalScriptsHead.next;
    378         else
    379                 currentHead = objScriptList.next;
     333        // fixed size part: 14093 bytes (12308 bytes in broken save)
     334        // animDataTable begins at byte 6431
    380335
    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;
     336        int filesize = fHandle.size();
     337        int startpos = fHandle.pos();
     338        int pos, tmp;
     339        bool correct = false, broken = false;
     340
     341        // check for correct format
     342        while (filesize > 14093) {
     343                pos = 14093;
     344
     345                fHandle.seek(pos);
     346                tmp = fHandle.readUint16BE();
     347                pos += 2 + tmp * 206;
     348                if (pos >= filesize) break;
     349
     350                fHandle.seek(pos);
     351                tmp = fHandle.readUint16BE();
     352                pos += 2 + tmp * 206;
     353                if (pos >= filesize) break;
     354
     355                fHandle.seek(pos);
     356                tmp = fHandle.readUint16BE();
     357                pos += 2 + tmp * 20;
     358                if (pos >= filesize) break;
     359
     360                fHandle.seek(pos);
     361                tmp = fHandle.readUint16BE();
     362                pos += 2 + tmp * 20;
     363
     364                if (pos == filesize) correct = true;
     365                break;
    387366        }
     367        debugN(5, "brokenSave: correct format check %s: size=%d, pos=%d",
     368                correct ? "passed" : "failed", filesize, pos);
     369
     370        // check for broken format
     371        while (filesize > 12308) {
     372                pos = 12308;
     373
     374                fHandle.seek(pos);
     375                tmp = fHandle.readUint16BE();
     376                pos += 2 + tmp * 206;
     377                if (pos >= filesize) break;
     378
     379                fHandle.seek(pos);
     380                tmp = fHandle.readUint16BE();
     381                pos += 2 + tmp * 206;
     382                if (pos >= filesize) break;
     383
     384                fHandle.seek(pos);
     385                tmp = fHandle.readUint16BE();
     386                pos += 2 + tmp * 20;
     387                if (pos >= filesize) break;
     388
     389                fHandle.seek(pos);
     390                tmp = fHandle.readUint16BE();
     391                pos += 2 + tmp * 20;
     392
     393                if (pos == filesize) broken = true;
     394                break;
     395        }
     396        debugN(5, "brokenSave: broken format check %s: size=%d, pos=%d",
     397                broken ? "passed" : "failed", filesize, pos);
     398
     399        // there's a very small chance that both cases will match
     400        // if anyone runs into it, you'll have to walk through
     401        // the animDataTable and try to open part file for each entry
     402        if (!correct && !broken) {
     403                error("brokenSave: file format check failed");
     404        } else if (correct && broken) {
     405                error("brokenSave: both file formats seem to apply");
     406        }
     407
     408        fHandle.seek(startpos);
     409        debugN(5, "brokenSave: detected %s file format\n",
     410                correct ? "correct" : "broken");
     411
     412        return broken;
    388413}
    389414
    390415bool CineEngine::makeLoad(char *saveName) {
    391416        int16 i;
    392417        int16 size;
     418        bool broken;
    393419        Common::InSaveFile *fHandle;
    394420
    395421        fHandle = g_saveFileMan->openForLoading(saveName);
     
    408434        // if (g_cine->getGameType() == Cine::GType_OS) {
    409435        //      freeUnkList();
    410436        // }
    411         freePrcLinkedList();
    412         releaseObjectScripts();
    413437        freeBgIncrustList();
    414438        closePart();
    415439
    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         }
     440        objectScripts.clear();
     441        globalScripts.clear();
     442        relTable.clear();
     443        scriptTable.clear();
    426444
    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 
    435445        for (i = 0; i < NUM_MAX_MESSAGE; i++) {
    436446                messageTable[i].len = 0;
    437447
     
    478488
    479489        checkForPendingDataLoadSwitch = 0;
    480490
     491        broken = brokenSave(*fHandle);
     492
    481493        currentDisk = fHandle->readUint16BE();
    482494
    483495        fHandle->read(currentPartName, 13);
     
    491503        fHandle->read(currentBgName[0], 13);
    492504        fHandle->read(currentCtName, 13);
    493505
     506        checkDataDisk(currentDisk);
     507
     508        if (strlen(currentPartName)) {
     509                loadPart(currentPartName);
     510        }
     511
     512        if (strlen(currentPrcName)) {
     513                loadPrc(currentPrcName);
     514        }
     515
     516        if (strlen(currentRelName)) {
     517                loadRel(currentRelName);
     518        }
     519
    494520        fHandle->readUint16BE();
    495521        fHandle->readUint16BE();
    496522
     
    540566        fHandle->readUint16BE();
    541567        fHandle->readUint16BE();
    542568
    543         for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
    544                 animDataTable[i].width = fHandle->readUint16BE();
    545                 animDataTable[i].var1 = fHandle->readUint16BE();
    546                 animDataTable[i].bpp = fHandle->readUint16BE();
    547                 animDataTable[i].height = fHandle->readUint16BE();
    548                 animDataTable[i].ptr1 = NULL;
    549                 animDataTable[i].ptr2 = NULL;
    550                 animDataTable[i].fileIdx = fHandle->readSint16BE();
    551                 animDataTable[i].frameIdx = fHandle->readSint16BE();
    552                 fHandle->read(animDataTable[i].name, 10);
    553                 animDataTable[i].refresh = (fHandle->readByte() != 0);
    554         }
     569        loadResourcesFromSave(*fHandle, broken);
    555570
    556571        // TODO: handle screen params (really required ?)
    557572        fHandle->readUint16BE();
     
    583598
    584599        delete fHandle;
    585600
    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 
    602601        if (strlen(currentMsgName)) {
    603602                loadMsg(currentMsgName);
    604603        }
     
    611610                loadCt(currentCtName);
    612611        }
    613612
    614         loadResourcesFromSave();
    615613        reincrustAllBg();
    616614
    617615        setMouseCursor(MOUSE_CURSOR_NORMAL);
     
    702700        fHandle->writeUint16BE(0x1E);
    703701
    704702        for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
    705                 fHandle->writeUint16BE(animDataTable[i].width);
    706                 fHandle->writeUint16BE(animDataTable[i].var1);
    707                 fHandle->writeUint16BE(animDataTable[i].bpp);
    708                 fHandle->writeUint16BE(animDataTable[i].height);
    709                 fHandle->writeSint16BE(animDataTable[i].fileIdx);
    710                 fHandle->writeSint16BE(animDataTable[i].frameIdx);
    711                 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);
     703                animDataTable[i].save(*fHandle);
    720704        }
    721705
    722706        fHandle->writeUint16BE(0);  // Screen params, unhandled
     
    727711        fHandle->writeUint16BE(0);
    728712
    729713        {
    730                 int16 numScript = 0;
    731                 prcLinkedListStruct *currentHead = globalScriptsHead.next;
    732 
    733                 while (currentHead) {
    734                         numScript++;
    735                         currentHead = currentHead->next;
     714                ScriptList::iterator it;
     715                fHandle->writeUint16BE(globalScripts.size());
     716                for (it = globalScripts.begin(); it != globalScripts.end(); ++it) {
     717                        (*it)->save(*fHandle);
    736718                }
    737719
    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;
     720                fHandle->writeUint16BE(objectScripts.size());
     721                for (it = objectScripts.begin(); it != objectScripts.end(); ++it) {
     722                        (*it)->save(*fHandle);
    755723                }
    756724        }
    757725
    758726        {
    759727                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;
    789728                overlayHeadElement *currentHead = overlayHead.next;
    790729
    791730                while (currentHead) {
     
    17261665        return var_5E;
    17271666}
    17281667
    1729 void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr,
    1730                                 byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
     1668void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr,
     1669                                const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    17311670        byte *ptr = NULL;
    17321671        byte *msk = NULL;
    17331672        byte i = 0;
     
    17541693
    17551694                        maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;
    17561695
    1757                         maskWidth = animDataTable[maskSpriteIdx].width / 2;
    1758                         maskHeight = animDataTable[maskSpriteIdx].height;
    1759                         gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++);
     1696                        maskWidth = animDataTable[maskSpriteIdx].width() / 2;
     1697                        maskHeight = animDataTable[maskSpriteIdx].height();
     1698                        gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++);
    17601699#ifdef DEBUG_SPRITE_MASK
    1761                         gfxFillSprite(animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, page, maskX, maskY, 1);
     1700                        gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
    17621701#endif
    17631702                }
    17641703
     
    17901729                                if (i > 200) {
    17911730                                        memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320);
    17921731                                } else {
    1793                                         memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i) * 320, 320);
     1732                                        memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320);
    17941733                                }
    17951734                        }
    17961735                }
     
    19121851
    19131852void drawOverlays(void) {
    19141853        uint16 partVar1, partVar2;
    1915         AnimData *pPart;
     1854        animData *pPart;
    19161855        overlayHeadElement *currentOverlay, *nextOverlay;
    19171856        int16 x, y;
    19181857        objectStruct *objPtr;
     
    19421881                                        if (g_cine->getGameType() == Cine::GType_OS) {
    19431882                                                pPart = &animDataTable[objPtr->frame];
    19441883
    1945                                                 partVar1 = pPart->var1;
    1946                                                 partVar2 = pPart->height;
     1884                                                partVar1 = pPart->var1();
     1885                                                partVar2 = pPart->height();
    19471886
    1948                                                 if (pPart->ptr1) {
    1949                                                         // NOTE: is the mask supposed to be in ptr1? Shouldn't that be ptr2, like below?
    1950                                                         drawSprite(currentOverlay, pPart->ptr1, pPart->ptr1, partVar1, partVar2, page1Raw, x, y);
     1887                                                if (pPart->data()) {
     1888                                                        // NOTE: is the mask supposed to be in data()? Shouldn't that be mask(), like below?
     1889                                                        // OS sprites don't use masks, see drawSprite() -- next_ghost
     1890                                                        drawSprite(currentOverlay, pPart->data(), pPart->data(), partVar1, partVar2, page1Raw, x, y);
    19511891                                                }
    19521892                                        } else {
    19531893                                                part = objPtr->part;
     
    19561896
    19571897                                                pPart = &animDataTable[objPtr->frame];
    19581898
    1959                                                 partVar1 = pPart->var1;
    1960                                                 partVar2 = pPart->height;
     1899                                                partVar1 = pPart->var1();
     1900                                                partVar2 = pPart->height();
    19611901
    1962                                                 if (pPart->ptr1) {
    1963                                                         drawSprite(currentOverlay, pPart->ptr1, pPart->ptr2, partVar1, partVar2, page1Raw, x, y);
     1902                                                if (pPart->data()) {
     1903                                                        drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y);
    19641904                                                }
    19651905                                        }
    19661906                                }
     
    20131953                                x = objPtr->x;
    20141954                                y = objPtr->y;
    20151955
     1956
    20161957                                if (objPtr->frame >= 0) {
    20171958                                        part = objPtr->part;
    20181959
     
    20201961
    20211962                                        pPart = &animDataTable[objPtr->frame];
    20221963
    2023                                         partVar1 = pPart->width / 2;
    2024                                         partVar2 = pPart->height;
     1964                                        partVar1 = pPart->width() / 2;
     1965                                        partVar2 = pPart->height();
    20251966
    2026                                         if (pPart->ptr1) {
    2027                                                 gfxFillSprite(pPart->ptr1, partVar1, partVar2, page1Raw, x, y);
     1967                                        if (pPart->data()) {
     1968                                                gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y);
    20281969                                        }
    20291970                                }
    20301971                                break;
     
    20431984                                if (objPtr->frame >= 0) {
    20441985                                        if (var5 <= 8) {
    20451986                                                if (additionalBgTable[var5]) {
    2046                                                         if (animDataTable[objPtr->frame].bpp == 1) {
     1987                                                        if (animDataTable[objPtr->frame].bpp() == 1) {
    20471988                                                                int16 x2;
    20481989                                                                int16 y2;
    20491990
    2050                                                                 x2 = animDataTable[objPtr->frame].width / 2;
    2051                                                                 y2 = animDataTable[objPtr->frame].height;
     1991                                                                x2 = animDataTable[objPtr->frame].width() / 2;
     1992                                                                y2 = animDataTable[objPtr->frame].height();
    20521993
    2053                                                                 if (animDataTable[objPtr->frame].ptr1) {
     1994                                                                if (animDataTable[objPtr->frame].data()) {
    20541995                                                                        // drawSpriteRaw(animDataTable[objPtr->frame].ptr1, animDataTable[objPtr->frame].ptr1, x2, y2,
    20551996                                                                        //                              additionalBgTable[currentAdditionalBgIdx], x, y);
    20561997                                                                }
     
    20752016
    20762017void checkForPendingDataLoad(void) {
    20772018        if (newPrcName[0] != 0) {
    2078                 freePrcLinkedList();
    2079                 resetglobalScriptsHead();
    2080 
    20812019                loadPrc(newPrcName);
    20822020
    20832021                strcpy(currentPrcName, newPrcName);
     
    20872025        }
    20882026
    20892027        if (newRelName[0] != 0) {
    2090                 releaseObjectScripts();
    2091                 resetObjectScriptHead();
    2092 
    20932028                loadRel(newRelName);
    20942029
    20952030                strcpy(currentRelName, newRelName);
     
    23152250#endif
    23162251}
    23172252
    2318 uint16 addAni(uint16 param1, uint16 param2, byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
    2319         byte *currentPtr = ptr;
    2320         byte *ptrData;
    2321         byte *ptr2;
     2253uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
     2254        const byte *currentPtr = ptr;
     2255        const byte *ptrData;
     2256        const byte *ptr2;
    23222257        int16 di;
    23232258
    23242259        assert(ptr);
     
    23602295void processSeqListElement(SeqListElement *element) {
    23612296        int16 x = objectTable[element->var6].x;
    23622297        int16 y = objectTable[element->var6].y;
    2363         byte *ptr1 = animDataTable[element->varA].ptr1;
     2298        const byte *ptr1 = animDataTable[element->varA].data();
    23642299        int16 var_10;
    23652300        int16 var_4;
    23662301        int16 var_2;
  • engines/cine/gfx.h

     
    3737extern uint16 c_palette[256];
    3838extern byte colorMode256;
    3939extern byte palette256[256 * 3];
     40extern byte newPalette[256 * 3];
     41extern byte newColorMode;
    4042
    4143void gfxInit();
    4244void gfxDestroy();
     
    4648void transformPaletteRange(byte startColor, byte numColor, int8 r, int8 g, int8 b);
    4749void gfxFlipPage(void);
    4850
    49 void gfxDrawMaskedSprite(byte *ptr, byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
    50 void gfxFillSprite(byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
     51void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
     52void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
    5153
    52 void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
     54void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    5355    int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx);
    5456
    5557void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
     
    5759
    5860void gfxResetPage(byte *pagePtr);
    5961
    60 int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width);
     62int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width);
    6163
    6264void gfxResetRawPage(byte *pageRaw);
    6365void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h);
    6466void gfxCopyRawPage(byte *source, byte * dest);
    6567void gfxFlipRawPage(byte *frontBuffer);
    66 void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
     68void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
    6769void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
    68 void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
     70void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
    6971
     72void fadeFromBlack(void);
    7073void fadeToBlack(void);
    7174
    72 void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
     75// wtf?!
     76//void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
    7377void gfxWaitVBL(void);
    7478void gfxRedrawMouseCursor(void);
    7579
  • 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);
     46void removeGfxElementA0(int16 idx, int16 param);
    4347
    44 struct Opcode {
    45         void (*proc)();
    46         const char *args;
     48const Opcode FWScript::_opcodeTable[] = {
     49        /* 00 */
     50        { &FWScript::o1_modifyObjectParam, "bbw" },
     51        { &FWScript::o1_getObjectParam, "bbb" },
     52        { &FWScript::o1_addObjectParam, "bbw" },
     53        { &FWScript::o1_subObjectParam, "bbw" },
     54        /* 04 */
     55        { &FWScript::o1_add2ObjectParam, "bbw" },
     56        { &FWScript::o1_sub2ObjectParam, "bbw" },
     57        { &FWScript::o1_compareObjectParam, "bbw" },
     58        { &FWScript::o1_setupObject, "bwwww" },
     59        /* 08 */
     60        { &FWScript::o1_checkCollision, "bwwww" },
     61        { &FWScript::o1_loadVar, "bc" },
     62        { &FWScript::o1_addVar, "bc" },
     63        { &FWScript::o1_subVar, "bc" },
     64        /* 0C */
     65        { &FWScript::o1_mulVar, "bc" },
     66        { &FWScript::o1_divVar, "bc" },
     67        { &FWScript::o1_compareVar, "bc" },
     68        { &FWScript::o1_modifyObjectParam2, "bbb" },
     69        /* 10 */
     70        { 0, 0 },
     71        { 0, 0 },
     72        { 0, 0 },
     73        { &FWScript::o1_loadMask0, "b" },
     74        /* 14 */
     75        { &FWScript::o1_unloadMask0, "b" },
     76        { &FWScript::o1_addToBgList, "b" },
     77        { &FWScript::o1_loadMask1, "b" },
     78        { &FWScript::o1_unloadMask1, "b" },
     79        /* 18 */
     80        { &FWScript::o1_loadMask4, "b" },
     81        { &FWScript::o1_unloadMask4, "b" },
     82        { &FWScript::o1_addSpriteFilledToBgList, "b" },
     83        { &FWScript::o1_op1B, "" },
     84        /* 1C */
     85        { 0, 0 },
     86        { &FWScript::o1_label, "l" },
     87        { &FWScript::o1_goto, "b" },
     88        { &FWScript::o1_gotoIfSup, "b" },
     89        /* 20 */
     90        { &FWScript::o1_gotoIfSupEqu, "b" },
     91        { &FWScript::o1_gotoIfInf, "b" },
     92        { &FWScript::o1_gotoIfInfEqu, "b" },
     93        { &FWScript::o1_gotoIfEqu, "b" },
     94        /* 24 */
     95        { &FWScript::o1_gotoIfDiff, "b" },
     96        { &FWScript::o1_removeLabel, "b" },
     97        { &FWScript::o1_loop, "bb" },
     98        { 0, 0 },
     99        /* 28 */
     100        { 0, 0 },
     101        { 0, 0 },
     102        { 0, 0 },
     103        { 0, 0 },
     104        /* 2C */
     105        { 0, 0 },
     106        { 0, 0 },
     107        { 0, 0 },
     108        { 0, 0 },
     109        /* 30 */
     110        { 0, 0 },
     111        { &FWScript::o1_startGlobalScript, "b" },
     112        { &FWScript::o1_endGlobalScript, "b" },
     113        { 0, 0 },
     114        /* 34 */
     115        { 0, 0 },
     116        { 0, 0 },
     117        { 0, 0 },
     118        { 0, 0 },
     119        /* 38 */
     120        { 0, 0 },
     121        { 0, 0 },
     122        { 0, 0 },
     123        { &FWScript::o1_loadAnim, "s" },
     124        /* 3C */
     125        { &FWScript::o1_loadBg, "s" },
     126        { &FWScript::o1_loadCt, "s" },
     127        { 0, 0 },
     128        { &FWScript::o1_loadPart, "s" },
     129        /* 40 */
     130        { &FWScript::o1_closePart, "" },
     131        { &FWScript::o1_loadNewPrcName, "bs" },
     132        { &FWScript::o1_requestCheckPendingDataLoad, "" },
     133        { 0, 0 },
     134        /* 44 */
     135        { 0, 0 },
     136        { &FWScript::o1_blitAndFade, "" },
     137        { &FWScript::o1_fadeToBlack, "" },
     138        { &FWScript::o1_transformPaletteRange, "bbwww" },
     139        /* 48 */
     140        { 0, 0 },
     141        { &FWScript::o1_setDefaultMenuColor2, "b" },
     142        { &FWScript::o1_palRotate, "bbb" },
     143        { 0, 0 },
     144        /* 4C */
     145        { 0, 0 },
     146        { 0, 0 },
     147        { 0, 0 },
     148        { &FWScript::o1_break, "" },
     149        /* 50 */
     150        { &FWScript::o1_endScript, "x" },
     151        { &FWScript::o1_message, "bwwww" },
     152        { &FWScript::o1_loadGlobalVar, "bc" },
     153        { &FWScript::o1_compareGlobalVar, "bc" },
     154        /* 54 */
     155        { 0, 0 },
     156        { 0, 0 },
     157        { 0, 0 },
     158        { 0, 0 },
     159        /* 58 */
     160        { 0, 0 },
     161        { &FWScript::o1_declareFunctionName, "s" },
     162        { &FWScript::o1_freePartRange, "bb" },
     163        { &FWScript::o1_unloadAllMasks, "" },
     164        // 5C */
     165        { 0, 0 },
     166        { 0, 0 },
     167        { 0, 0 },
     168        { 0, 0 },
     169        /* 60 */
     170        { 0, 0 },
     171        { 0, 0 },
     172        { 0, 0 },
     173        { &FWScript::o1_setScreenDimensions, "wwww" },
     174        /* 64 */
     175        { &FWScript::o1_displayBackground, "" },
     176        { &FWScript::o1_initializeZoneData, "" },
     177        { &FWScript::o1_setZoneDataEntry, "bw" },
     178        { &FWScript::o1_getZoneDataEntry, "bb" },
     179        /* 68 */
     180        { &FWScript::o1_setDefaultMenuColor, "b" },
     181        { &FWScript::o1_allowPlayerInput, "" },
     182        { &FWScript::o1_disallowPlayerInput, "" },
     183        { &FWScript::o1_changeDataDisk, "b" },
     184        /* 6C */
     185        { 0, 0 },
     186        { &FWScript::o1_loadMusic, "s" },
     187        { &FWScript::o1_playMusic, "" },
     188        { &FWScript::o1_fadeOutMusic, "" },
     189        /* 70 */
     190        { &FWScript::o1_stopSample, "" },
     191        { &FWScript::o1_op71, "bw" },
     192        { &FWScript::o1_op72, "wbw" },
     193        { &FWScript::o1_op73, "wbw" },
     194        /* 74 */
     195        { 0, 0 },
     196        { 0, 0 },
     197        { 0, 0 },
     198        { &FWScript::o1_playSample, "bbwbww" },
     199        /* 78 */
     200        { &FWScript::o1_playSample, "bbwbww" },
     201        { &FWScript::o1_disableSystemMenu, "b" },
     202        { &FWScript::o1_loadMask5, "b" },
     203        { &FWScript::o1_unloadMask5, "b" }
    47204};
     205const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable);
    48206
    49 const Opcode *_opcodeTable;
    50 int _numOpcodes;
    51207
    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         };
     208const Opcode OSScript::_opcodeTable[] = {
     209        /* 00 */
     210        { &FWScript::o1_modifyObjectParam, "bbw" },
     211        { &FWScript::o1_getObjectParam, "bbb" },
     212        { &FWScript::o1_addObjectParam, "bbw" },
     213        { &FWScript::o1_subObjectParam, "bbw" },
     214        /* 04 */
     215        { &FWScript::o1_add2ObjectParam, "bbw" },
     216        { &FWScript::o1_sub2ObjectParam, "bbw" },
     217        { &FWScript::o1_compareObjectParam, "bbw" },
     218        { &FWScript::o1_setupObject, "bwwww" },
     219        /* 08 */
     220        { &FWScript::o1_checkCollision, "bwwww" },
     221        { &FWScript::o1_loadVar, "bc" },
     222        { &FWScript::o1_addVar, "bc" },
     223        { &FWScript::o1_subVar, "bc" },
     224        /* 0C */
     225        { &FWScript::o1_mulVar, "bc" },
     226        { &FWScript::o1_divVar, "bc" },
     227        { &FWScript::o1_compareVar, "bc" },
     228        { &FWScript::o1_modifyObjectParam2, "bbb" },
     229        /* 10 */
     230        { 0, 0 },
     231        { 0, 0 },
     232        { 0, 0 },
     233        { &FWScript::o1_loadMask0, "b" },
     234        /* 14 */
     235        { &FWScript::o1_unloadMask0, "b" },
     236        { &FWScript::o1_addToBgList, "b" },
     237        { &FWScript::o1_loadMask1, "b" },
     238        { &FWScript::o1_unloadMask1, "b" },
     239        /* 18 */
     240        { &FWScript::o1_loadMask4, "b" },
     241        { &FWScript::o1_unloadMask4, "b" },
     242        { &FWScript::o1_addSpriteFilledToBgList, "b" },
     243        { &FWScript::o1_op1B, "" },
     244        /* 1C */
     245        { 0, 0 },
     246        { &FWScript::o1_label, "l" },
     247        { &FWScript::o1_goto, "b" },
     248        { &FWScript::o1_gotoIfSup, "b" },
     249        /* 20 */
     250        { &FWScript::o1_gotoIfSupEqu, "b" },
     251        { &FWScript::o1_gotoIfInf, "b" },
     252        { &FWScript::o1_gotoIfInfEqu, "b" },
     253        { &FWScript::o1_gotoIfEqu, "b" },
     254        /* 24 */
     255        { &FWScript::o1_gotoIfDiff, "b" },
     256        { &FWScript::o1_removeLabel, "b" },
     257        { &FWScript::o1_loop, "bb" },
     258        { 0, 0 },
     259        /* 28 */
     260        { 0, 0 },
     261        { 0, 0 },
     262        { 0, 0 },
     263        { 0, 0 },
     264        /* 2C */
     265        { 0, 0 },
     266        { 0, 0 },
     267        { 0, 0 },
     268        { 0, 0 },
     269        /* 30 */
     270        { 0, 0 },
     271        { &FWScript::o1_startGlobalScript, "b" },
     272        { &FWScript::o1_endGlobalScript, "b" },
     273        { 0, 0 },
     274        /* 34 */
     275        { 0, 0 },
     276        { 0, 0 },
     277        { 0, 0 },
     278        { 0, 0 },
     279        /* 38 */
     280        { 0, 0 },
     281        { 0, 0 },
     282        { 0, 0 },
     283        { &FWScript::o1_loadAnim, "s" },
     284        /* 3C */
     285        { &FWScript::o1_loadBg, "s" },
     286        { &FWScript::o1_loadCt, "s" },
     287        { 0, 0 },
     288        { &FWScript::o2_loadPart, "s" },
     289        /* 40 */
     290        { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
     291        { &FWScript::o1_loadNewPrcName, "bs" },
     292        { &FWScript::o1_requestCheckPendingDataLoad, "" },
     293        { 0, 0 },
     294        /* 44 */
     295        { 0, 0 },
     296        { &FWScript::o1_blitAndFade, "" },
     297        { &FWScript::o1_fadeToBlack, "" },
     298        { &FWScript::o1_transformPaletteRange, "bbwww" },
     299        /* 48 */
     300        { 0, 0 },
     301        { &FWScript::o1_setDefaultMenuColor2, "b" },
     302        { &FWScript::o1_palRotate, "bbb" },
     303        { 0, 0 },
     304        /* 4C */
     305        { 0, 0 },
     306        { 0, 0 },
     307        { 0, 0 },
     308        { &FWScript::o1_break, "" },
     309        /* 50 */
     310        { &FWScript::o1_endScript, "x" },
     311        { &FWScript::o1_message, "bwwww" },
     312        { &FWScript::o1_loadGlobalVar, "bc" },
     313        { &FWScript::o1_compareGlobalVar, "bc" },
     314        /* 54 */
     315        { 0, 0 },
     316        { 0, 0 },
     317        { 0, 0 },
     318        { 0, 0 },
     319        /* 58 */
     320        { 0, 0 },
     321        { &FWScript::o1_declareFunctionName, "s" },
     322        { &FWScript::o1_freePartRange, "bb" },
     323        { &FWScript::o1_unloadAllMasks, "" },
     324        // 5C */
     325        { 0, 0 },
     326        { 0, 0 },
     327        { 0, 0 },
     328        { 0, 0 },
     329        /* 60 */
     330        { 0, 0 },
     331        { 0, 0 },
     332        { 0, 0 },
     333        { &FWScript::o1_setScreenDimensions, "wwww" },
     334        /* 64 */
     335        { &FWScript::o1_displayBackground, "" },
     336        { &FWScript::o1_initializeZoneData, "" },
     337        { &FWScript::o1_setZoneDataEntry, "bw" },
     338        { &FWScript::o1_getZoneDataEntry, "bb" },
     339        /* 68 */
     340        { &FWScript::o1_setDefaultMenuColor, "b" },
     341        { &FWScript::o1_allowPlayerInput, "" },
     342        { &FWScript::o1_disallowPlayerInput, "" },
     343        { &FWScript::o1_changeDataDisk, "b" },
     344        /* 6C */
     345        { 0, 0 },
     346        { &FWScript::o1_loadMusic, "s" },
     347        { &FWScript::o1_playMusic, "" },
     348        { &FWScript::o1_fadeOutMusic, "" },
     349        /* 70 */
     350        { &FWScript::o1_stopSample, "" },
     351        { &FWScript::o1_op71, "bw" },
     352        { &FWScript::o1_op72, "wbw" },
     353        { &FWScript::o1_op72, "wbw" },
     354        /* 74 */
     355        { 0, 0 },
     356        { 0, 0 },
     357        { 0, 0 },
     358        { &FWScript::o2_playSample, "bbwbww" },
     359        /* 78 */
     360        { &FWScript::o2_playSampleAlt, "bbwbww" },
     361        { &FWScript::o1_disableSystemMenu, "b" },
     362        { &FWScript::o1_loadMask5, "b" },
     363        { &FWScript::o1_unloadMask5, "b" },
     364        /* 7C */
     365        { 0, 0 },
     366        { 0, 0 },
     367        { 0, 0 },
     368        { &FWScript::o2_addSeqListElement, "bbbbwww" },
     369        /* 80 */
     370        { &FWScript::o2_removeSeq, "bb" },
     371        { &FWScript::o2_op81, "" },
     372        { &FWScript::o2_op82, "bbw" },
     373        { &FWScript::o2_isSeqRunning, "bb" },
     374        /* 84 */
     375        { &FWScript::o2_gotoIfSupNearest, "b" },
     376        { &FWScript::o2_gotoIfSupEquNearest, "b" },
     377        { &FWScript::o2_gotoIfInfNearest, "b" },
     378        { &FWScript::o2_gotoIfInfEquNearest, "b" },
     379        /* 88 */
     380        { &FWScript::o2_gotoIfEquNearest, "b" },
     381        { &FWScript::o2_gotoIfDiffNearest, "b" },
     382        { 0, 0 },
     383        { &FWScript::o2_startObjectScript, "b" },
     384        /* 8C */
     385        { &FWScript::o2_stopObjectScript, "b" },
     386        { &FWScript::o2_op8D, "wwwwwwww" },
     387        { &FWScript::o2_addBackground, "bs" },
     388        { &FWScript::o2_removeBackground, "b" },
     389        /* 90 */
     390        { &FWScript::o2_loadAbs, "bs" },
     391        { &FWScript::o2_loadBg, "b" },
     392        { 0, 0 },
     393        { 0, 0 },
     394        /* 94 */
     395        { 0, 0 },
     396        { &FWScript::o1_changeDataDisk, "b" },
     397        { 0, 0 },
     398        { 0, 0 },
     399        /* 98 */
     400        { 0, 0 },
     401        { 0, 0 },
     402        { &FWScript::o2_wasZoneChecked, "" },
     403        { &FWScript::o2_op9B, "wwwwwwww" },
     404        /* 9C */
     405        { &FWScript::o2_op9C, "wwww" },
     406        { &FWScript::o2_useBgScroll, "b" },
     407        { &FWScript::o2_setAdditionalBgVScroll, "c" },
     408        { &FWScript::o2_op9F, "ww" },
     409        /* A0 */
     410        { &FWScript::o2_addGfxElementA0, "ww" },
     411        { &FWScript::o2_removeGfxElementA0, "ww" },
     412        { &FWScript::o2_opA2, "ww" },
     413        { &FWScript::o2_opA3, "ww" },
     414        /* A4 */
     415        { &FWScript::o2_loadMask22, "b" },
     416        { &FWScript::o2_unloadMask22, "b" },
     417        { 0, 0 },
     418        { 0, 0 },
     419        /* A8 */
     420        { 0, 0 },
     421        { &FWScript::o1_changeDataDisk, "b" }
     422};
     423const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable);
    210424
    211         // TODO: We need to verify the Operation Stealth opcodes.
     425FWScriptInfo *scriptInfo; ///< Script factory
     426RawScriptArray scriptTable; ///< Table of script bytecode
    212427
    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 
     428/*! \todo: replace with script subsystem
     429 */
     430void setupOpcodes() {
     431        static FWScriptInfo fw;
     432        static OSScriptInfo os;
    429433        if (g_cine->getGameType() == Cine::GType_FW) {
    430                 _opcodeTable = opcodeTableFW;
    431                 _numOpcodes = ARRAYSIZE(opcodeTableFW);
     434                scriptInfo = &fw;
    432435        } else {
    433                 _opcodeTable = opcodeTableOS;
    434                 _numOpcodes = ARRAYSIZE(opcodeTableOS);
     436                scriptInfo = &os;
    435437        }
    436438}
    437439
    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
     440/*! \brief Allocate empty array
     441 * \param len Size of array
     442 *
     443 * Explicit to prevent var=0 instead of var[i]=0 typos.
     444 */
    457445ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) {
    458446        assert(_vars);
    459447        reset();
    460448}
    461449
    462 // read game save, for later use
     450/*! \brief Allocate array and read contents from savefile
     451 * \param fHandle Savefile open for reading
     452 * \param len Size of array
     453 */
    463454ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len)
    464455        : _size(len), _vars(new int16[len]) {
    465456
     
    468459        load(fHandle);
    469460}
    470461
    471 // copy constructor
     462/*! \brief Copy constructor
     463 */
    472464ScriptVars::ScriptVars(const ScriptVars &src) : _size(src._size), _vars(new int16[_size]) {
    473465        assert(_vars);
    474466        memcpy(_vars, src._vars, _size * sizeof(int16));
    475467}
    476468
     469/*! \brief Destructor
     470 */
    477471ScriptVars::~ScriptVars(void) {
    478472        delete[] _vars;
    479473}
    480474
     475/*! \brief Assignment operator
     476 */
    481477ScriptVars &ScriptVars::operator=(const ScriptVars &src) {
    482478        ScriptVars tmp(src);
    483479        int16 *tmpvars = _vars;
     
    489485        return *this;
    490486}
    491487
    492 // array access
     488/*! \brief Direct array item access
     489 * \param idx Item index
     490 * \return Reference to item
     491 */
    493492int16 &ScriptVars::operator[](unsigned int idx) {
    494         debugN(5, "assert(%d < %d)", idx, _size);
     493        debugN(5, "assert(%d < %d)\n", idx, _size);
    495494        assert(idx < _size);
    496495        return _vars[idx];
    497496}
    498497
     498/*! \brief Direct read-only array item access
     499 * \param idx Item index
     500 * \return Copy of item
     501 */
    499502int16 ScriptVars::operator[](unsigned int idx) const {
    500503        debugN(5, "assert(%d < %d)\n", idx, _size);
    501504        assert(idx < _size);
    502505        return _vars[idx];
    503506}
    504507
    505 // dump to savefile
    506 void ScriptVars::save(Common::OutSaveFile &fHandle) {
     508/*! \brief Savefile writer
     509 * \param fHandle Savefile open for writing
     510 */
     511void ScriptVars::save(Common::OutSaveFile &fHandle) const {
    507512        save(fHandle, _size);
    508513}
    509514
    510 // globalVars[255] is not written to savefiles...
    511 void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) {
     515/*! \brief Savefile writer with data length limit
     516 * \param fHandle Savefile open for writing
     517 * \param len Length of data to be written (len <= _size)
     518 */
     519void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const {
    512520        debugN(5, "assert(%d <= %d)\n", len, _size);
    513521        assert(len <= _size);
    514522        for (unsigned int i = 0; i < len; i++) {
     
    516524        }
    517525}
    518526
    519 // read from savefile
     527/*! \brief Restore array from savefile
     528 * \param fHandle Savefile open for reading
     529 */
    520530void ScriptVars::load(Common::InSaveFile &fHandle) {
    521531        load(fHandle, _size);
    522532}
    523533
     534/*! \brief Restore part of array from savefile
     535 * \param fHandle Savefile open for reading
     536 * \param len Length of data to be read
     537 */
    524538void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) {
    525539        debugN(5, "assert(%d <= %d)\n", len, _size);
    526540        assert(len <= _size);
     
    529543        }
    530544}
    531545
     546/*! \brief Reset all values to 0
     547 */
    532548void ScriptVars::reset(void) {
    533549        memset( _vars, 0, _size * sizeof(int16));
    534550}
    535551
    536 void addGfxElementA0(int16 param1, int16 param2) {
    537         overlayHeadElement *currentHead = &overlayHead;
    538         overlayHeadElement *tempHead = currentHead;
    539         overlayHeadElement *newElement;
     552/*! \brief Constructor for partial loading
     553 * \param s Size of bytecode which will be added later
     554 *
     555 * This constructor _MUST_ be followed by setdata() method call before the
     556 * instance can be used. It leaves the instance in partially invalid state.
     557 */
     558RawScript::RawScript(uint16 s) : _size(s), _data(NULL),
     559        _labels(SCRIPT_STACK_SIZE) { }
    540560
    541         currentHead = tempHead->next;
     561/*! \brief Complete constructor
     562 * \param data Script bytecode
     563 * \param s Bytecode length
     564 */
     565RawScript::RawScript(const FWScriptInfo &info, const byte *data, uint16 s) :
     566        _size(s), _data(NULL), _labels(SCRIPT_STACK_SIZE) {
    542567
    543         while (currentHead) {
    544                 if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
    545                         if (currentHead->type == 2 || currentHead->objIdx == 3) {
    546                                 break;
    547                         }
    548                 }
     568        setData(info, data);
     569}
    549570
    550                 tempHead = currentHead;
    551                 currentHead = currentHead->next;
    552         }
     571/*! \brief Copy constructor
     572 */
     573RawScript::RawScript(const RawScript &src) : _size(src._size),
     574        _data(new byte[_size+1]), _labels(src._labels) {
    553575
    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;
     576        assert(_data);
     577        memcpy(_data, src._data, _size+1);
    576578}
    577579
    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         }
     580/*! \brief Destructor
     581 */
     582RawScript::~RawScript(void) {
     583        delete[] _data;
    590584}
    591585
    592 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
    593         SeqListElement *currentHead = &seqList;
    594         SeqListElement *tempHead = currentHead;
     586/*! \brief Assignment operator
     587 */
     588RawScript &RawScript::operator=(const RawScript &src) {
     589        assert(src._data);
     590        byte *tmp = new byte[src._size+1];
    595591
    596         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    597                 tempHead = currentHead;
    598                 currentHead = tempHead->next;
    599         }
     592        assert(tmp);
     593        _labels = src._labels;
     594        _size = src._size;
    600595
    601         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    602                 return 1;
    603         }
     596        delete[] _data;
     597        _data = tmp;
     598        memcpy(_data, src._data, _size);
     599        _data[_size] = 0;
    604600
    605         return 0;
     601        return *this;
    606602}
    607603
    608 ScriptStruct scriptTable[NUM_MAX_SCRIPT];
     604/*! \brief Get the next label in bytecode
     605 * \param info Script info instance
     606 * \param offset Starting offset
     607 * \return Index of the next label in bytecode or _size on end of bytecode
     608 *
     609 * computeScriptStackSub replacement
     610 */
     611uint16 RawScript::getNextLabel(const FWScriptInfo &info, uint16 offset) const {
     612        assert(_data);
     613        uint16 pos = offset;
    609614
    610 void stopGlobalScript(uint16 scriptIdx) {
    611         prcLinkedListStruct *currentHead = &globalScriptsHead;
    612         prcLinkedListStruct *tempHead = currentHead;
     615        while (pos < _size) {
     616                uint8 opcode = _data[pos];
     617                pos++;
     618                const char *ptr = info.opcodeInfo(opcode);
    613619
    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) {
     620                if (!ptr) {
    647621                        continue;
    648622                }
    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) {
     623
     624                for (; *ptr; ++ptr) {
     625                        switch (*ptr) {
    655626                        case 'b': // byte
    656                                 position++;
     627                                pos++;
    657628                                break;
    658629                        case 'w': // word
    659                                 position += 2;
     630                                pos += 2;
    660631                                break;
    661632                        case 'c': { // byte != 0 ? byte : word
    662                                         uint8 test = scriptPtr[position];
    663                                         position++;
     633                                        uint8 test = _data[pos];
     634                                        pos++;
    664635                                        if (test) {
    665                                                 position++;
     636                                                pos++;
    666637                                        } else {
    667                                                 position += 2;
     638                                                pos += 2;
    668639                                        }
    669640                                }
    670641                                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;
     642                        case 'l': // label
     643                                return pos;
    683644                        case 's': // string
    684                                 while (scriptPtr[position++] != 0);
     645                                while (_data[pos++] != 0);
    685646                                break;
    686647                        case 'x': // exit script
    687                                 return position;
     648                                // this is a little change from the original
     649                                // code, I want to know if it breaks something
     650                                assert(pos >= _size-1);
     651                                return _size;
    688652                        }
    689653                }
    690654        }
    691         return position;
     655        return _size;
    692656}
    693657
    694 void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) {
    695         computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0);
    696 }
     658/*! \brief Calculate initial script labels
     659 * \param info Script info instance
     660 *
     661 * computeScriptStack replacement
     662 */
     663void RawScript::computeLabels(const FWScriptInfo &info) {
     664        assert(_data);
     665        uint16 pos = 0;
     666        int i;
    697667
    698 uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) {
    699         return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition);
     668        // reset labels
     669        for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
     670                _labels[i] = -1;
     671        }
     672
     673        // parse bytecode
     674        while ((pos = getNextLabel(info, pos)) < _size) {
     675                i = _data[pos];
     676                _labels[i] = ++pos;
     677        }
    700678}
    701679
    702 void palRotate(byte a, byte b, byte c) {
    703         if (c == 1) {
    704                 uint16 currentColor = c_palette[b];
     680/*! \brief find the next label from current position
     681 * \param info Script info instance
     682 * \param index Label index to look for
     683 * \param offset Current position in script
     684 * \return Position of next instruction following the label
     685 *
     686 * computeScriptStackFromScript replacement
     687 */
     688uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
     689        const {
    705690
    706                 for (int16 i = b; i > a; i--) {
    707                         c_palette[i] = c_palette[i - 1];
     691        assert(_data);
     692        uint16 pos = offset;
     693
     694        while ((pos = getNextLabel(info, pos)) < _size) {
     695                if (_data[pos++] == index) {
     696                        return pos;
    708697                }
     698        }
    709699
    710                 c_palette[a] = currentColor;
    711         }
     700        return _size;
    712701}
    713702
    714 void addScriptToList0(uint16 idx) {
    715         uint16 i;
    716         prcLinkedListStruct *pNewElement;
    717         prcLinkedListStruct *currentHead = &globalScriptsHead;
    718         prcLinkedListStruct *tempHead = currentHead;
     703/*! \brief Copy bytecode and calculate labels
     704 * \param data Bytecode to copy, must be _size long
     705 */
     706void RawScript::setData(const FWScriptInfo &info, const byte *data) {
     707        assert(!_data); // this function should be called only once per instance
     708        _data = new byte[_size+1];
    719709
    720         assert(idx <= NUM_MAX_SCRIPT);
     710        assert(data && _data);
     711        memcpy(_data, data, _size * sizeof(byte));
     712        _data[_size] = 0;
    721713
    722         currentHead = tempHead->next;
     714        computeLabels(info);
     715}
    723716
    724         while (currentHead) {
    725                 tempHead = currentHead;
     717/*! \brief Initial script labels
     718 * \return Precalculated script labels
     719 */
     720const ScriptVars &RawScript::labels(void) const {
     721        assert(_data);
     722        return _labels;
     723}
    726724
    727                 assert(tempHead);
     725/*! \brief One byte of bytecode
     726 * \param pos Index in bytecode
     727 * \return Byte from bytecode
     728 */
     729byte RawScript::getByte(unsigned int pos) const {
     730        assert(_data && pos < _size);
    728731
    729                 currentHead = tempHead->next;
    730         }
     732        return _data[pos];
     733}
    731734
    732         pNewElement = new prcLinkedListStruct;
     735/*! \brief One word of bytecode
     736 * \param pos Index of the first byte in bytecode
     737 * \return Word of bytecode
     738 */
     739uint16 RawScript::getWord(unsigned int pos) const {
     740        assert(_data && pos+1 < _size);
    733741
    734         assert(pNewElement);
     742        return READ_BE_UINT16(_data + pos);
     743}
    735744
    736         pNewElement->next = tempHead->next;
    737         tempHead->next = pNewElement;
     745/*! \brief String in bytecode
     746 * \param pos Index of the first char in string
     747 * \return Pointer to part of bytecode
     748 */
     749const char *RawScript::getString(unsigned int pos) const {
     750        assert(_data && pos < _size);
    738751
    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         }
     752        return (const char*)(_data+pos);
     753}
    743754
    744         pNewElement->compareResult = 0;
    745         pNewElement->scriptPosition = 0;
     755/*! \brief Constructor for partial loading
     756 * \param size Size of bytecode which will be added later
     757 * \param p1 First object script parameter
     758 * \param p2 Second object script parameter
     759 * \param p3 Third object script parameter
     760 *
     761 * This constructor _MUST_ be followed by setdata() method call before the
     762 * instance can be used. It leaves the instance in partially invalid state.
     763 */
     764RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
     765        : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
     766{ }
    746767
    747         pNewElement->scriptPtr = scriptTable[idx].ptr;
    748         pNewElement->scriptIdx = idx;
     768/*! \brief Complete constructor
     769 * \param data Script bytecode
     770 * \param s Bytecode length
     771 * \param p1 First object script parameter
     772 * \param p2 Second object script parameter
     773 * \param p3 Third object script parameter
     774 */
     775RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
     776        uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
     777        _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
     778
     779/*! \brief Contructor for global scripts
     780 * \param script Script bytecode reference
     781 * \param idx Script bytecode index
     782 */
     783FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
     784        _pos(0), _line(0), _compare(0), _index(idx),
     785        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     786        _globalVars(globalVars), _info(new FWScriptInfo) { }
     787
     788/*! \brief Copy constructor
     789 */
     790FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
     791        _line(src._line), _compare(src._compare), _index(src._index),
     792        _labels(src._labels), _localVars(src._localVars),
     793        _globalVars(src._globalVars), _info(new FWScriptInfo) { }
     794
     795/*! \brief Contructor for global scripts in derived classes
     796 * \param script Script bytecode reference
     797 * \param idx Script bytecode index
     798 */
     799FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
     800        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     801        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     802        _globalVars(globalVars), _info(info) { }
     803
     804/*! \brief Constructor for object scripts in derived classes
     805 * \param script Script bytecode reference
     806 * \param idx Script bytecode index
     807 */
     808FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
     809        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     810        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     811        _globalVars(globalVars), _info(info) {
     812
     813        _localVars[0] = script.run();
    749814}
    750815
    751 int16 endScript0(uint16 scriptIdx) {
    752         prcLinkedListStruct *currentHead = &globalScriptsHead;
    753         prcLinkedListStruct *tempHead = currentHead;
     816/*! \brief Copy constructor for derived classes
     817 */
     818FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
     819        _script(src._script), _pos(src._pos), _line(src._line),
     820        _compare(src._compare), _index(src._index), _labels(src._labels),
     821        _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
    754822
    755         //assert(scriptIdx <= NUM_MAX_SCRIPT);
     823FWScript::~FWScript(void) {
     824        delete _info;
     825}
    756826
    757         currentHead = tempHead->next;
     827/*! \brief Read next byte from bytecode
     828 * \return Byte from bytecode
     829 */
     830byte FWScript::getNextByte() {
     831        byte val = _script.getByte(_pos);
     832        _pos++;
     833        return val;
     834}
    758835
    759         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    760                 tempHead = currentHead;
    761                 currentHead = tempHead->next;
    762         }
     836/*! \brief Read next word from bytecode
     837 * \return Word from bytecode
     838 */
     839uint16 FWScript::getNextWord() {
     840        uint16 val = _script.getWord(_pos);
     841        _pos += 2;
     842        return val;
     843}
    763844
    764         if (!currentHead) {
    765                 return -1;
    766         }
     845/*! \brief Read next string from bytecode
     846 * \return Pointer to string
     847 */
     848const char *FWScript::getNextString() {
     849        const char *val = _script.getString(_pos);
     850        _pos += strlen(val) + 1;
     851        return val;
     852}
    767853
    768         if (currentHead->scriptIdx != scriptIdx) {
    769                 return -1;
     854/*! \brief Restore script state from savefile
     855 * \param labels Restored script labels
     856 * \param local Restored local script variables
     857 * \param compare Restored last comparison result
     858 * \param pos Restored script position
     859 */
     860void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     861        assert(pos < _script.size());
     862        _labels = labels;
     863        _localVars = local;
     864        _compare = compare;
     865        _pos = _line = pos;
     866}
     867
     868/*! \brief Execute script
     869 * \return <0 on script termination, >0 on script pause
     870 *
     871 * executeScript replacement.
     872 * Instruction handler must return 0 if the script should continue or
     873 * nonzero with the same meaning as return value of this function
     874 */
     875int FWScript::execute() {
     876        int ret = 0;
     877
     878        while (!ret) {
     879                _line = _pos;
     880                byte opcode = getNextByte();
     881                opFunc handler = _info->opcodeHandler(opcode);
     882
     883                if (handler) {
     884                        ret = (this->*handler)();
     885                }
    770886        }
    771887
    772         currentHead->scriptIdx = -1;
     888        return ret;
     889}
    773890
    774         return 0;
     891/*! \brief Save script to savefile
     892 * \param fHandle Savefile handle
     893 */
     894void FWScript::save(Common::OutSaveFile &fHandle) const {
     895        _labels.save(fHandle);
     896        _localVars.save(fHandle);
     897        fHandle.writeUint16BE(_compare);
     898        fHandle.writeUint16BE(_pos);
     899        // data order sucks...
     900        fHandle.writeUint16BE(_index);
    775901}
    776902
    777 int16 endScript1(uint16 scriptIdx) {
    778         prcLinkedListStruct *currentHead = &objScriptList;
    779         prcLinkedListStruct *tempHead = currentHead;
     903/*! \brief Contructor for global scripts
     904 * \param script Script bytecode reference
     905 * \param idx Script bytecode index
     906 */
     907OSScript::OSScript(const RawScript &script, int16 idx) :
     908        FWScript(script, idx, new OSScriptInfo) {}
    780909
    781         currentHead = tempHead->next;
     910/*! \brief Constructor for object scripts
     911 * \param script Script bytecode reference
     912 * \param idx Script bytecode index
     913 */
     914OSScript::OSScript(RawObjectScript &script, int16 idx) :
     915        FWScript(script, idx, new OSScriptInfo) {}
    782916
    783         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    784                 tempHead = currentHead;
    785                 currentHead = tempHead->next;
    786         }
     917/*! \brief Copy constructor
     918 */
     919OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
    787920
    788         if (!currentHead) {
    789                 return -1;
     921/*! \brief Restore script state from savefile
     922 * \param labels Restored script labels
     923 * \param local Restored local script variables
     924 * \param compare Restored last comparison result
     925 * \param pos Restored script position
     926 */
     927void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     928        FWScript::load(labels, local, compare, pos);
     929}
     930/*! \brief Get opcode info string
     931 * \param opcode Opcode to look for in opcode table
     932 */
     933const char *FWScriptInfo::opcodeInfo(byte opcode) const {
     934        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     935                return NULL;
    790936        }
    791937
    792         if (currentHead->scriptIdx != scriptIdx) {
    793                 return -1;
     938        if (!FWScript::_opcodeTable[opcode - 1].args) {
     939                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1);
     940                return NULL;
    794941        }
    795942
    796         currentHead->scriptIdx = -1;
    797 
    798         return 0;
     943        return FWScript::_opcodeTable[opcode - 1].args;
    799944}
    800945
    801 int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
    802         byte *ptr = page + (y * width) + x / 2;
    803         byte zoneVar;
     946/*! \brief Get opcode handler pointer
     947 * \param opcode Opcode to look for in opcode table
     948 */
     949opFunc FWScriptInfo::opcodeHandler(byte opcode) const {
     950        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     951                return NULL;
     952        }
    804953
    805         if (!(x % 2)) {
    806                 zoneVar = (*(ptr) >> 4) & 0xF;
    807         } else {
    808                 zoneVar = (*(ptr)) & 0xF;
     954        if (!FWScript::_opcodeTable[opcode - 1].proc) {
     955                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1);
     956                return NULL;
    809957        }
    810958
    811         return zoneVar;
     959        return FWScript::_opcodeTable[opcode - 1].proc;
    812960}
    813961
    814 int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
    815         byte *ptr = page + (y * width) + x;
    816         byte zoneVar;
     962/*! \brief Create new FWScript instance
     963 * \param script Script bytecode
     964 * \param index Bytecode index
     965 */
     966FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const {
     967        return new FWScript(script, index);
     968}
    817969
    818         zoneVar = (*(ptr)) & 0xF;
     970/*! \brief Create new FWScript instance
     971 * \param script Object script bytecode
     972 * \param index Bytecode index
     973 */
     974FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const {
     975        return new FWScript(script, index);
     976}
    819977
    820         return zoneVar;
     978/*! \brief Load saved FWScript instance
     979 * \param script Script bytecode
     980 * \param index Bytecode index
     981 * \param local Local variables
     982 * \param labels Script labels
     983 * \param compare Last compare result
     984 * \param pos Position in script
     985 */
     986FWScript *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     987        FWScript *tmp = new FWScript(script, index);
     988        assert(tmp);
     989        tmp->load(labels, local, compare, pos);
     990        return tmp;
    821991}
    822992
    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;
     993/*! \brief Load saved FWScript instance
     994 * \param script Object script bytecode
     995 * \param index Bytecode index
     996 * \param local Local variables
     997 * \param labels Script labels
     998 * \param compare Last compare result
     999 * \param pos Position in script
     1000 */
     1001FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1002        FWScript *tmp = new FWScript(script, index);
     1003        assert(tmp);
     1004        tmp->load(labels, local, compare, pos);
     1005        return tmp;
     1006}
    8271007
    828         for (int16 i = 0; i < numZones; i++) {
    829                 idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     1008/*! \brief Get opcode info string
     1009 * \param opcode Opcode to look for in opcode table
     1010 */
     1011const char *OSScriptInfo::opcodeInfo(byte opcode) const {
     1012        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1013                return NULL;
     1014        }
    8301015
    831                 assert(idx >= 0 && idx <= NUM_MAX_ZONE);
    832 
    833                 if (zoneData[idx] == zoneIdx) {
    834                         return 1;
    835                 }
     1016        if (!OSScript::_opcodeTable[opcode - 1].args) {
     1017                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
     1018                return NULL;
    8361019        }
    8371020
    838         return 0;
     1021        return OSScript::_opcodeTable[opcode - 1].args;
    8391022}
    8401023
    841 uint16 compareVars(int16 a, int16 b) {
    842         uint16 flag = 0;
     1024/*! \brief Get opcode handler pointer
     1025 * \param opcode Opcode to look for in opcode table
     1026 */
     1027opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
     1028        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1029                return NULL;
     1030        }
    8431031
    844         if (a == b) {
    845                 flag |= kCmpEQ;
    846         } else if (a > b) {
    847                 flag |= kCmpGT;
    848         } else if (a < b) {
    849                 flag |= kCmpLT;
     1032        if (!OSScript::_opcodeTable[opcode - 1].proc) {
     1033                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
     1034                return NULL;
    8501035        }
    8511036
    852         return flag;
     1037        return OSScript::_opcodeTable[opcode - 1].proc;
    8531038}
    8541039
     1040/*! \brief Create new OSScript instance
     1041 * \param script Script bytecode
     1042 * \param index Bytecode index
     1043 */
     1044FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
     1045        return new OSScript(script, index);
     1046}
     1047
     1048/*! \brief Create new OSScript instance
     1049 * \param script Object script bytecode
     1050 * \param index Bytecode index
     1051 */
     1052FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
     1053        return new OSScript(script, index);
     1054}
     1055
     1056/*! \brief Load saved OSScript instance
     1057 * \param script Script bytecode
     1058 * \param index Bytecode index
     1059 * \param local Local variables
     1060 * \param labels Script labels
     1061 * \param compare Last compare result
     1062 * \param pos Position in script
     1063 */
     1064FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1065        OSScript *tmp = new OSScript(script, index);
     1066        assert(tmp);
     1067        tmp->load(labels, local, compare, pos);
     1068        return tmp;
     1069}
     1070
     1071/*! \brief Load saved OSScript instance
     1072 * \param script Object script bytecode
     1073 * \param index Bytecode index
     1074 * \param local Local variables
     1075 * \param labels Script labels
     1076 * \param compare Last compare result
     1077 * \param pos Position in script
     1078 */
     1079FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1080        OSScript *tmp = new OSScript(script, index);
     1081        assert(tmp);
     1082        tmp->load(labels, local, compare, pos);
     1083        return tmp;
     1084}
     1085
    8551086// ------------------------------------------------------------------------
    8561087// FUTURE WARS opcodes
    8571088// ------------------------------------------------------------------------
    8581089
    859 void o1_modifyObjectParam() {
     1090int FWScript::o1_modifyObjectParam() {
    8601091        byte objIdx = getNextByte();
    8611092        byte paramIdx = getNextByte();
    8621093        int16 newValue = getNextWord();
    8631094
    864         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1095        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8651096
    8661097        modifyObjectParam(objIdx, paramIdx, newValue);
     1098        return 0;
    8671099}
    8681100
    869 void o1_getObjectParam() {
     1101int FWScript::o1_getObjectParam() {
    8701102        byte objIdx = getNextByte();
    8711103        byte paramIdx = getNextByte();
    8721104        byte newValue = getNextByte();
    8731105
    874         debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue);
     1106        debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue);
    8751107
    876         _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1108        _localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1109        return 0;
    8771110}
    8781111
    879 void o1_addObjectParam() {
     1112int FWScript::o1_addObjectParam() {
    8801113        byte objIdx = getNextByte();
    8811114        byte paramIdx = getNextByte();
    8821115        int16 newValue = getNextWord();
    8831116
    884         debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1117        debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8851118
    8861119        addObjectParam(objIdx, paramIdx, newValue);
     1120        return 0;
    8871121}
    8881122
    889 void o1_subObjectParam() {
     1123int FWScript::o1_subObjectParam() {
    8901124        byte objIdx = getNextByte();
    8911125        byte paramIdx = getNextByte();
    8921126        int16 newValue = getNextWord();
    8931127
    894         debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1128        debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8951129
    8961130        subObjectParam(objIdx, paramIdx, newValue);
     1131        return 0;
    8971132}
    8981133
    899 void o1_add2ObjectParam() {
    900         getNextByte();
    901         getNextByte();
    902         getNextWord();
    903         warning("STUB: o1_add2ObjectParam()");
     1134/*! \todo Implement this instruction
     1135 */
     1136int FWScript::o1_add2ObjectParam() {
     1137        uint16 a = getNextByte();
     1138        uint16 b = getNextByte();
     1139        uint16 c = getNextWord();
     1140        warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c);
     1141        return 0;
    9041142}
    9051143
    906 void o1_sub2ObjectParam() {
    907         getNextByte();
    908         getNextByte();
    909         getNextWord();
    910         warning("STUB: o1_sub2ObjectParam()");
     1144/*! \todo Implement this instruction
     1145 */
     1146int FWScript::o1_sub2ObjectParam() {
     1147        uint16 a = getNextByte();
     1148        uint16 b = getNextByte();
     1149        uint16 c = getNextWord();
     1150        warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c);
     1151        return 0;
    9111152}
    9121153
    913 void o1_compareObjectParam() {
     1154int FWScript::o1_compareObjectParam() {
    9141155        byte objIdx = getNextByte();
    9151156        byte param1 = getNextByte();
    9161157        int16 param2 = getNextWord();
    9171158
    918         debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2);
     1159        debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2);
    9191160
    920         _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2);
     1161        _compare = compareObjectParam(objIdx, param1, param2);
     1162        return 0;
    9211163}
    9221164
    923 void o1_setupObject() {
     1165int FWScript::o1_setupObject() {
    9241166        byte objIdx = getNextByte();
    9251167        int16 param1 = getNextWord();
    9261168        int16 param2 = getNextWord();
    9271169        int16 param3 = getNextWord();
    9281170        int16 param4 = getNextWord();
    9291171
    930         debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1172        debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9311173
    9321174        setupObject(objIdx, param1, param2, param3, param4);
     1175        return 0;
    9331176}
    9341177
    935 void o1_checkCollision() {
     1178int FWScript::o1_checkCollision() {
    9361179        byte objIdx = getNextByte();
    9371180        int16 param1 = getNextWord();
    9381181        int16 param2 = getNextWord();
    9391182        int16 param3 = getNextWord();
    9401183        int16 param4 = getNextWord();
    9411184
    942         debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1185        debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9431186
    944         _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4);
     1187        _compare = checkCollision(objIdx, param1, param2, param3, param4);
     1188        return 0;
    9451189}
    9461190
    947 void o1_loadVar() {
     1191int FWScript::o1_loadVar() {
    9481192        byte varIdx = getNextByte();
    9491193        byte varType = getNextByte();
    9501194
     
    9541198
    9551199                switch (varType) {
    9561200                case 1:
    957                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    958                         _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1201                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx);
     1202                        _localVars[varIdx] = _localVars[dataIdx];
    9591203                        break;
    9601204                case 2:
    961                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    962                         _currentScriptElement->localVars[varIdx] = globalVars[dataIdx];
     1205                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1206                        _localVars[varIdx] = _globalVars[dataIdx];
    9631207                        break;
    9641208                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;
     1209                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx);
     1210                        getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16);
     1211                        _localVars[varIdx] = var;
    9681212                        break;
    9691213                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;
     1214                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx);
     1215                        getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var);
     1216                        _localVars[varIdx] = var;
    9731217                        break;
    9741218                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);
     1219                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx);
     1220                        _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
    9771221                        break;
    9781222                case 8:
    979                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx);
    980                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize;
     1223                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
     1224                        _localVars[varIdx] = partBuffer[dataIdx].packedSize;
    9811225                        break;
    9821226                case 9:
    983                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx);
    984                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
     1227                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
     1228                        _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
    9851229                        break;
    9861230                default:
    9871231                        error("executeScript: o1_loadVar: Unknown variable type %d", varType);
     
    9891233        } else {
    9901234                int16 value = getNextWord();
    9911235
    992                 debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value);
    993                 _currentScriptElement->localVars[varIdx] = value;
     1236                debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value);
     1237                _localVars[varIdx] = value;
    9941238        }
     1239
     1240        return 0;
    9951241}
    9961242
    997 void o1_addVar() {
     1243int FWScript::o1_addVar() {
    9981244        byte varIdx = getNextByte();
    9991245        byte varType = getNextByte();
    10001246
    10011247        if (varType) {
    10021248                byte dataIdx = getNextByte();
    10031249
    1004                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx);
    1005                 _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx];
     1250                if (varType == 1) {
     1251                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx);
     1252                        _localVars[varIdx] += _localVars[dataIdx];
     1253                } else if (varType == 2) {
     1254                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx);
     1255                        _localVars[varIdx] += _globalVars[dataIdx];
     1256                }
    10061257        } else {
    10071258                int16 value = getNextWord();
    10081259
    1009                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value);
    1010                 _currentScriptElement->localVars[varIdx] += value;
     1260                debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value);
     1261                _localVars[varIdx] += value;
    10111262        }
     1263
     1264        return 0;
    10121265}
    10131266
    1014 void o1_subVar() {
     1267int FWScript::o1_subVar() {
    10151268        byte varIdx = getNextByte();
    10161269        byte varType = getNextByte();
    10171270
    10181271        if (varType) {
    10191272                byte dataIdx = getNextByte();
    10201273
    1021                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx);
    1022                 _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx];
     1274                if (varType == 1) {
     1275                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx);
     1276                        _localVars[varIdx] -= _localVars[dataIdx];
     1277                } else if (varType == 2) {
     1278                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx);
     1279                        _localVars[varIdx] -= _globalVars[dataIdx];
     1280                }
     1281
    10231282        } else {
    10241283                int16 value = getNextWord();
    10251284
    1026                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value);
    1027                 _currentScriptElement->localVars[varIdx] -= value;
     1285                debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value);
     1286                _localVars[varIdx] -= value;
    10281287        }
     1288
     1289        return 0;
    10291290}
    10301291
    1031 void o1_mulVar() {
     1292int FWScript::o1_mulVar() {
    10321293        byte varIdx = getNextByte();
    10331294        byte varType = getNextByte();
    10341295
    10351296        if (varType) {
    10361297                byte dataIdx = getNextByte();
    10371298
    1038                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx);
    1039                 _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx];
     1299                if (varType == 1) {
     1300                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx);
     1301                        _localVars[varIdx] *= _localVars[dataIdx];
     1302                } else if (varType == 2) {
     1303                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx);
     1304                        _localVars[varIdx] *= _globalVars[dataIdx];
     1305                }
    10401306        } else {
    10411307                int16 value = getNextWord();
    10421308
    1043                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value);
    1044                 _currentScriptElement->localVars[varIdx] *= value;
     1309                debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value);
     1310                _localVars[varIdx] *= value;
    10451311        }
     1312
     1313        return 0;
    10461314}
    10471315
    1048 void o1_divVar() {
     1316int FWScript::o1_divVar() {
    10491317        byte varIdx = getNextByte();
    10501318        byte varType = getNextByte();
    10511319
    10521320        if (varType) {
    10531321                byte dataIdx = getNextByte();
    10541322
    1055                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx);
    1056                 _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx];
     1323                if (varType == 1) {
     1324                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx);
     1325                        _localVars[varIdx] /= _localVars[dataIdx];
     1326                } else if (varType == 2) {
     1327                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx);
     1328                        _localVars[varIdx] /= _globalVars[dataIdx];
     1329                }
    10571330        } else {
    10581331                int16 value = getNextWord();
    10591332
    1060                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value);
    1061                 _currentScriptElement->localVars[varIdx] /= value;
     1333                debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value);
     1334                _localVars[varIdx] /= value;
    10621335        }
     1336
     1337        return 0;
    10631338}
    10641339
    1065 void o1_compareVar() {
     1340int FWScript::o1_compareVar() {
    10661341        byte varIdx = getNextByte();
    10671342        byte varType = getNextByte();
    10681343
    10691344        if (varType) {
    10701345                byte dataIdx = getNextByte();
    10711346
    1072                 // printf("Val: %d\n", dataIdx);
    1073 
    10741347                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]);
     1348                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx);
     1349                        _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]);
    10801350                } 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]);
     1351                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx);
     1352                        _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]);
    10851353                }
    10861354        } else {
    10871355                int16 value = getNextWord();
    10881356
    1089                 debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value);
    1090                 _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value);
     1357                debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value);
     1358                _compare = compareVars(_localVars[varIdx], value);
    10911359        }
     1360
     1361        return 0;
    10921362}
    10931363
    1094 void o1_modifyObjectParam2() {
     1364int FWScript::o1_modifyObjectParam2() {
    10951365        byte objIdx = getNextByte();
    10961366        byte paramIdx = getNextByte();
    10971367        byte newValue = getNextByte();
    10981368
    1099         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue);
     1369        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue);
    11001370
    1101         modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]);
     1371        modifyObjectParam(objIdx, paramIdx, _localVars[newValue]);
     1372        return 0;
    11021373}
    11031374
    1104 void o1_loadMask0() {
     1375int FWScript::o1_loadMask0() {
    11051376        // OP_loadV7Element
    11061377        byte param = getNextByte();
    11071378
    1108         debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param);
     1379        debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
    11091380        loadOverlayElement(param, 0);
     1381        return 0;
    11101382}
    11111383
    1112 void o1_unloadMask0() {
     1384int FWScript::o1_unloadMask0() {
    11131385        byte param = getNextByte();
    11141386
    1115         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param);
     1387        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
    11161388        freeOverlay(param, 0);
     1389        return 0;
    11171390}
    11181391
    1119 void o1_addToBgList() {
     1392int FWScript::o1_addToBgList() {
    11201393        byte param = getNextByte();
    11211394
    1122         debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param);
     1395        debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param);
    11231396        addToBGList(param);
     1397        return 0;
    11241398}
    11251399
    1126 void o1_loadMask1() {
     1400int FWScript::o1_loadMask1() {
    11271401        byte param = getNextByte();
    11281402
    1129         debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param);
     1403        debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
    11301404        loadOverlayElement(param, 1);
     1405        return 0;
    11311406}
    11321407
    1133 void o1_unloadMask1() {
     1408int FWScript::o1_unloadMask1() {
    11341409        byte param = getNextByte();
    11351410
    1136         debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param);
     1411        debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
    11371412        freeOverlay(param, 1);
     1413        return 0;
    11381414}
    11391415
    1140 void o1_loadMask4() {
     1416int FWScript::o1_loadMask4() {
    11411417        byte param = getNextByte();
    11421418
    1143         debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param);
     1419        debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
    11441420        loadOverlayElement(param, 4);
     1421        return 0;
    11451422}
    11461423
    1147 void o1_unloadMask4() {
     1424int FWScript::o1_unloadMask4() {
    11481425        byte param = getNextByte();
    11491426
    1150         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param);
     1427        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
    11511428        freeOverlay(param, 4);
     1429        return 0;
    11521430}
    11531431
    1154 void o1_addSpriteFilledToBgList() {
     1432int FWScript::o1_addSpriteFilledToBgList() {
    11551433        byte param = getNextByte();
    11561434
    1157         debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param);
     1435        debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param);
    11581436        addSpriteFilledToBGList(param);
     1437        return 0;
    11591438}
    11601439
    1161 void o1_op1B() {
    1162         debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine);
     1440int FWScript::o1_op1B() {
     1441        debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
    11631442        freeBgIncrustList();
     1443        return 0;
    11641444}
    11651445
    1166 void o1_label() {
     1446int FWScript::o1_label() {
    11671447        byte labelIdx = getNextByte();
    11681448
    1169         debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx);
    1170         _currentScriptElement->stack[labelIdx] = _currentPosition;
     1449        debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx);
     1450        _labels[labelIdx] = _pos;
     1451        return 0;
    11711452}
    11721453
    1173 void o1_goto() {
     1454int FWScript::o1_goto() {
    11741455        byte labelIdx = getNextByte();
    11751456
    1176         assert(_currentScriptElement->stack[labelIdx] != -1);
     1457        assert(_labels[labelIdx] != -1);
    11771458
    1178         debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx);
    1179         _currentPosition = _currentScriptElement->stack[labelIdx];
     1459        debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx);
     1460        _pos = _labels[labelIdx];
     1461        return 0;
    11801462}
    11811463
    1182 void o1_gotoIfSup() {
     1464int FWScript::o1_gotoIfSup() {
    11831465        byte labelIdx = getNextByte();
    11841466
    1185         if (_currentScriptElement->compareResult == kCmpGT) {
    1186                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1467        if (_compare == kCmpGT) {
     1468                assert(_labels[labelIdx] != -1);
    11871469
    1188                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx);
    1189                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1470                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx);
     1471                _pos = _labels[labelIdx];
    11901472        } else {
    1191                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx);
     1473                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx);
    11921474        }
     1475        return 0;
    11931476}
    11941477
    1195 void o1_gotoIfSupEqu() {
     1478int FWScript::o1_gotoIfSupEqu() {
    11961479        byte labelIdx = getNextByte();
    11971480
    1198         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1199                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1481        if (_compare & (kCmpGT | kCmpEQ)) {
     1482                assert(_labels[labelIdx] != -1);
    12001483
    1201                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx);
    1202                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1484                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx);
     1485                _pos = _labels[labelIdx];
    12031486        } else {
    1204                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx);
     1487                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx);
    12051488        }
     1489        return 0;
    12061490}
    12071491
    1208 void o1_gotoIfInf() {
     1492int FWScript::o1_gotoIfInf() {
    12091493        byte labelIdx = getNextByte();
    12101494
    1211         if (_currentScriptElement->compareResult == kCmpLT) {
    1212                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1495        if (_compare == kCmpLT) {
     1496                assert(_labels[labelIdx] != -1);
    12131497
    1214                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx);
    1215                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1498                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx);
     1499                _pos = _labels[labelIdx];
    12161500        } else {
    1217                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx);
     1501                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx);
    12181502        }
     1503        return 0;
    12191504}
    12201505
    1221 void o1_gotoIfInfEqu() {
     1506int FWScript::o1_gotoIfInfEqu() {
    12221507        byte labelIdx = getNextByte();
    12231508
    1224         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1225                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1509        if (_compare & (kCmpLT | kCmpEQ)) {
     1510                assert(_labels[labelIdx] != -1);
    12261511
    1227                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx);
    1228                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1512                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx);
     1513                _pos = _labels[labelIdx];
    12291514        } else {
    1230                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx);
     1515                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx);
    12311516        }
     1517        return 0;
    12321518}
    12331519
    1234 void o1_gotoIfEqu() {
     1520int FWScript::o1_gotoIfEqu() {
    12351521        byte labelIdx = getNextByte();
    12361522
    1237         if (_currentScriptElement->compareResult == kCmpEQ) {
    1238                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1523        if (_compare == kCmpEQ) {
     1524                assert(_labels[labelIdx] != -1);
    12391525
    1240                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx);
    1241                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1526                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx);
     1527                _pos = _labels[labelIdx];
    12421528        } else {
    1243                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx);
     1529                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx);
    12441530        }
     1531        return 0;
    12451532}
    12461533
    1247 void o1_gotoIfDiff() {
     1534int FWScript::o1_gotoIfDiff() {
    12481535        byte labelIdx = getNextByte();
    12491536
    1250         if (_currentScriptElement->compareResult != kCmpEQ) {
    1251                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1537        if (_compare != kCmpEQ) {
     1538                assert(_labels[labelIdx] != -1);
    12521539
    1253                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx);
    1254                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1540                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx);
     1541                _pos = _labels[labelIdx];
    12551542        } else {
    1256                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx);
     1543                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx);
    12571544        }
     1545        return 0;
    12581546}
    12591547
    1260 void o1_removeLabel() {
     1548int FWScript::o1_removeLabel() {
    12611549        byte labelIdx = getNextByte();
    12621550
    1263         debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx);
    1264         _currentScriptElement->stack[labelIdx] = -1;
     1551        debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx);
     1552        _labels[labelIdx] = -1;
     1553        return 0;
    12651554}
    12661555
    1267 void o1_loop() {
     1556int FWScript::o1_loop() {
    12681557        byte varIdx = getNextByte();
    12691558        byte labelIdx = getNextByte();
    12701559
    1271         _currentScriptElement->localVars[varIdx]--;
     1560        _localVars[varIdx]--;
    12721561
    1273         if (_currentScriptElement->localVars[varIdx] >= 0) {
    1274                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1562        if (_localVars[varIdx] >= 0) {
     1563                assert(_labels[labelIdx] != -1);
    12751564
    1276                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx);
    1277                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1565                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx);
     1566                _pos = _labels[labelIdx];
    12781567        } else {
    1279                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx);
     1568                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx);
    12801569        }
     1570        return 0;
    12811571}
    12821572
    1283 void o1_startGlobalScript() {
     1573int FWScript::o1_startGlobalScript() {
    12841574        // OP_startScript
    12851575        byte param = getNextByte();
    12861576
    12871577        assert(param < NUM_MAX_SCRIPT);
    12881578
    1289         debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param);
     1579        debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param);
    12901580        addScriptToList0(param);
     1581        return 0;
    12911582}
    12921583
    1293 void o1_endGlobalScript() {
     1584int FWScript::o1_endGlobalScript() {
    12941585        byte scriptIdx = getNextByte();
    12951586
    1296         debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx);
    1297         stopGlobalScript(scriptIdx);
     1587        debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
     1588
     1589        ScriptList::iterator it = globalScripts.begin();
     1590
     1591        for (; it != globalScripts.end(); ++it) {
     1592                if ((*it)->index() == scriptIdx) {
     1593                        (*it)->_index = -1;
     1594                }
     1595        }
     1596
     1597        return 0;
    12981598}
    12991599
    1300 void o1_loadAnim() {
     1600int FWScript::o1_loadAnim() {
    13011601        // OP_loadResource
    13021602        const char *param = getNextString();
    13031603
    1304         debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param);
     1604        debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param);
    13051605        loadResource(param);
     1606        return 0;
    13061607}
    13071608
    1308 void o1_loadBg() {
     1609int FWScript::o1_loadBg() {
    13091610        const char *param = getNextString();
    13101611
    1311         debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param);
     1612        debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
    13121613
    13131614        loadBg(param);
    13141615        freeBgIncrustList();
    13151616        bgVar0 = 0;
     1617        return 0;
    13161618}
    13171619
    1318 void o1_loadCt() {
     1620int FWScript::o1_loadCt() {
    13191621        const char *param = getNextString();
    13201622
    1321         debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param);
     1623        debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
    13221624        loadCt(param);
     1625        return 0;
    13231626}
    13241627
    1325 void o1_loadPart() {
     1628int FWScript::o1_loadPart() {
    13261629        const char *param = getNextString();
    13271630
    1328         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     1631        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
    13291632        loadPart(param);
     1633        return 0;
    13301634}
    13311635
    1332 void o1_closePart() {
    1333         debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine);
     1636int FWScript::o1_closePart() {
     1637        debugC(5, kCineDebugScript, "Line: %d: closePart", _line);
    13341638        closePart();
     1639        return 0;
    13351640}
    13361641
    1337 void o1_loadNewPrcName() {
     1642int FWScript::o1_loadNewPrcName() {
    13381643        // OP_loadData
    13391644        byte param1 = getNextByte();
    13401645        const char *param2 = getNextString();
     
    13431648
    13441649        switch (param1) {
    13451650        case 0:
    1346                 debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2);
     1651                debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2);
    13471652                strcpy(newPrcName, param2);
    13481653                break;
    13491654        case 1:
    1350                 debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2);
     1655                debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2);
    13511656                strcpy(newRelName, param2);
    13521657                break;
    13531658        case 2:
    1354                 debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2);
     1659                debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2);
    13551660                strcpy(newObjectName, param2);
    13561661                break;
    13571662        case 3:
    1358                 debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2);
     1663                debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2);
    13591664                strcpy(newMsgName, param2);
    13601665                break;
    13611666        }
     1667        return 0;
    13621668}
    13631669
    1364 void o1_requestCheckPendingDataLoad() {
    1365         debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine);
     1670int FWScript::o1_requestCheckPendingDataLoad() {
     1671        debugC(5, kCineDebugScript, "Line: %d: request data load", _line);
    13661672        checkForPendingDataLoadSwitch = 1;
     1673        return 0;
    13671674}
    13681675
    1369 void o1_blitAndFade() {
    1370         debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine);
     1676int FWScript::o1_blitAndFade() {
     1677        debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
    13711678        // TODO: use real code
    13721679
    13731680        drawOverlays();
    13741681        fadeRequired = true;
    13751682        flip();
     1683
     1684//      fadeFromBlack();
     1685        return 0;
    13761686}
    13771687
    1378 void o1_fadeToBlack() {
    1379         debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine);
     1688int FWScript::o1_fadeToBlack() {
     1689        debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
    13801690
    13811691        fadeToBlack();
     1692        return 0;
    13821693}
    13831694
    1384 void o1_transformPaletteRange() {
     1695int FWScript::o1_transformPaletteRange() {
    13851696        byte startColor = getNextByte();
    13861697        byte numColor = getNextByte();
    13871698        uint16 r = getNextWord();
    13881699        uint16 g = getNextWord();
    13891700        uint16 b = getNextWord();
    13901701
    1391         debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _currentLine, startColor, numColor, r, g, b);
     1702        debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
    13921703
    13931704        transformPaletteRange(startColor, numColor, r, g, b);
     1705        return 0;
    13941706}
    13951707
    1396 void o1_setDefaultMenuColor2() {
     1708int FWScript::o1_setDefaultMenuColor2() {
    13971709        byte param = getNextByte();
    13981710
    1399         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param);
     1711        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
    14001712        defaultMenuBoxColor2 = param;
     1713        return 0;
    14011714}
    14021715
    1403 void o1_palRotate() {
     1716int FWScript::o1_palRotate() {
    14041717        byte a = getNextByte();
    14051718        byte b = getNextByte();
    14061719        byte c = getNextByte();
    14071720
    1408         debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c);
     1721        debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
    14091722        palRotate(a, b, c);
     1723        return 0;
    14101724}
    14111725
    1412 void o1_break() {
    1413         debugC(5, kCineDebugScript, "Line: %d: break", _currentLine);
     1726/*!\brief Pause script
     1727 * \todo Make sure it works
     1728 */
     1729int FWScript::o1_break() {
     1730        debugC(5, kCineDebugScript, "Line: %d: break", _line);
    14141731
    1415         _currentScriptElement->scriptPosition = _currentPosition;
    1416         _closeScript = 1;
     1732        return 1;
    14171733}
    14181734
    1419 void o1_endScript() {
    1420         debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine);
     1735/*! \brief Terminate script
     1736 * \todo Make sure it works
     1737 */
     1738int FWScript::o1_endScript() {
     1739        debugC(5, kCineDebugScript, "Line: %d: endScript", _line);
    14211740
    1422         if (_currentScriptParams == 0) {
    1423                 endScript0(_currentScriptElement->scriptIdx);
    1424         } else {
    1425                 endScript1(_currentScriptElement->scriptIdx);
    1426         }
    1427 
    1428         _closeScript = 1;
     1741        return -1;
    14291742}
    14301743
    1431 void o1_message() {
     1744int FWScript::o1_message() {
    14321745        byte param1 = getNextByte();
    14331746        uint16 param2 = getNextWord();
    14341747        uint16 param3 = getNextWord();
    14351748        uint16 param4 = getNextWord();
    14361749        uint16 param5 = getNextWord();
    14371750
    1438         debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5);
     1751        debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5);
    14391752
    14401753        addMessage(param1, param2, param3, param4, param5);
     1754        return 0;
    14411755}
    14421756
    1443 void o1_loadGlobalVar() {
     1757int FWScript::o1_loadGlobalVar() {
    14441758        byte varIdx = getNextByte();
    14451759        byte varType = getNextByte();
    14461760
     
    14481762                byte dataIdx = getNextByte();
    14491763
    14501764                if (varType == 1) {
    1451                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    1452                         globalVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1765                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx);
     1766                        _globalVars[varIdx] = _localVars[dataIdx];
    14531767                } else {
    1454                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    1455                         globalVars[varIdx] = globalVars[dataIdx];
     1768                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1769                        _globalVars[varIdx] = _globalVars[dataIdx];
    14561770                }
    14571771        } else {
    14581772                uint16 value = getNextWord();
    14591773
    1460                 debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value);
    1461                 globalVars[varIdx] = value;
     1774                debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value);
     1775                _globalVars[varIdx] = value;
    14621776        }
     1777
     1778        return 0;
    14631779}
    14641780
    1465 void o1_compareGlobalVar() {
     1781int FWScript::o1_compareGlobalVar() {
    14661782        byte varIdx = getNextByte();
    14671783        byte varType = getNextByte();
    14681784
    14691785        if (varType) {
    14701786                byte value = getNextByte();
    14711787
    1472                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value);
    1473                 _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]);
     1788                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value);
     1789                _compare = compareVars(_globalVars[varIdx], _localVars[value]);
    14741790        } else {
    14751791                uint16 value = getNextWord();
    14761792
    1477                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value);
     1793                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
    14781794
    14791795                if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) {       // TODO: fix
    1480                         _currentScriptElement->compareResult = 1;
     1796                        _compare = 1;
    14811797                } else {
    1482                         _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value);
     1798                        _compare = compareVars(_globalVars[varIdx], value);
    14831799                }
    14841800        }
     1801
     1802        return 0;
    14851803}
    14861804
    1487 void o1_declareFunctionName() {
     1805int FWScript::o1_declareFunctionName() {
    14881806        const char *param = getNextString();
    14891807
    1490         debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param);
     1808        debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param);
     1809        return 0;
    14911810}
    14921811
    1493 void o1_freePartRange() {
     1812int FWScript::o1_freePartRange() {
    14941813        byte startIdx = getNextByte();
    14951814        byte numIdx = getNextByte();
    14961815
    14971816        assert(startIdx + numIdx <= NUM_MAX_ANIMDATA);
    14981817
    1499         debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx);
     1818        debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx);
    15001819        freeAnimDataRange(startIdx, numIdx);
     1820        return 0;
    15011821}
    15021822
    1503 void o1_unloadAllMasks() {
    1504         debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine);
     1823int FWScript::o1_unloadAllMasks() {
     1824        debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
    15051825        unloadAllMasks();
     1826        return 0;
    15061827}
    15071828
    1508 void o1_setScreenDimensions() {
    1509         warning("STUB: o1_setScreenDimensions()");
    1510         getNextWord();
    1511         getNextWord();
    1512         getNextWord();
    1513         getNextWord();
     1829/*! \todo Implement this instruction
     1830 */
     1831int FWScript::o1_setScreenDimensions() {
     1832        uint16 a = getNextWord();
     1833        uint16 b = getNextWord();
     1834        uint16 c = getNextWord();
     1835        uint16 d = getNextWord();
     1836        warning("STUB: o1_setScreenDimensions(%x, %x, %x, %x)", a, b, c, d);
    15141837        // setupScreenParam
     1838        return 0;
    15151839}
    15161840
    1517 void o1_displayBackground() {
     1841/*! \todo Implement this instruction
     1842 */
     1843int FWScript::o1_displayBackground() {
    15181844        warning("STUB: o1_displayBackground()");
     1845        return 0;
    15191846}
    15201847
    1521 void o1_initializeZoneData() {
    1522         debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine);
     1848int FWScript::o1_initializeZoneData() {
     1849        debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
    15231850
    15241851        for (int i = 0; i < NUM_MAX_ZONE; i++) {
    15251852                zoneData[i] = i;
    15261853        }
     1854        return 0;
    15271855}
    15281856
    1529 void o1_setZoneDataEntry() {
     1857int FWScript::o1_setZoneDataEntry() {
    15301858        byte zoneIdx = getNextByte();
    15311859        uint16 var = getNextWord();
    15321860
    1533         debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var);
     1861        debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
    15341862        zoneData[zoneIdx] = var;
     1863        return 0;
    15351864}
    15361865
    1537 void o1_getZoneDataEntry() {
     1866int FWScript::o1_getZoneDataEntry() {
    15381867        byte zoneIdx = getNextByte();
    15391868        byte var = getNextByte();
    15401869
    1541         _currentScriptElement->localVars[var] = zoneData[zoneIdx];
     1870        _localVars[var] = zoneData[zoneIdx];
     1871        return 0;
    15421872}
    15431873
    1544 void o1_setDefaultMenuColor() {
     1874int FWScript::o1_setDefaultMenuColor() {
    15451875        byte param = getNextByte();
    15461876
    1547         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param);
     1877        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
    15481878        defaultMenuBoxColor = param;
     1879        return 0;
    15491880}
    15501881
    1551 void o1_allowPlayerInput() {
    1552         debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine);
     1882int FWScript::o1_allowPlayerInput() {
     1883        debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line);
    15531884        allowPlayerInput = 1;
     1885        return 0;
    15541886}
    15551887
    1556 void o1_disallowPlayerInput() {
    1557         debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine);
     1888int FWScript::o1_disallowPlayerInput() {
     1889        debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line);
    15581890        allowPlayerInput = 0;
     1891        return 0;
    15591892}
    15601893
    1561 void o1_changeDataDisk() {
     1894int FWScript::o1_changeDataDisk() {
    15621895        byte newDisk = getNextByte();
    15631896
    1564         debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk);
     1897        debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk);
    15651898        checkDataDisk(newDisk);
     1899        return 0;
    15661900}
    15671901
    1568 void o1_loadMusic() {
     1902int FWScript::o1_loadMusic() {
    15691903        const char *param = getNextString();
    15701904
    1571         debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param);
     1905        debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param);
    15721906        g_sound->loadMusic(param);
     1907        return 0;
    15731908}
    15741909
    1575 void o1_playMusic() {
    1576         debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
     1910int FWScript::o1_playMusic() {
     1911        debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line);
    15771912        g_sound->playMusic();
     1913        return 0;
    15781914}
    15791915
    1580 void o1_fadeOutMusic() {
    1581         debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
     1916int FWScript::o1_fadeOutMusic() {
     1917        debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line);
    15821918        g_sound->fadeOutMusic();
     1919        return 0;
    15831920}
    15841921
    1585 void o1_stopSample() {
    1586         debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
     1922int FWScript::o1_stopSample() {
     1923        debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line);
    15871924        g_sound->stopMusic();
     1925        return 0;
    15881926}
    15891927
    1590 void o1_op71() {
    1591         warning("STUB: o1_op71()");
    1592         getNextByte();
    1593         getNextWord();
     1928/*! \todo Implement this instruction
     1929 */
     1930int FWScript::o1_op71() {
     1931        byte a = getNextByte();
     1932        uint16 b = getNextWord();
     1933        warning("STUB: o1_op71(%x, %x)", a, b);
     1934        return 0;
    15941935}
    15951936
    1596 void o1_op72() {
    1597         warning("STUB: o1_op72()");
    1598         getNextWord();
    1599         getNextByte();
    1600         getNextWord();
     1937/*! \todo Implement this instruction
     1938 */
     1939int FWScript::o1_op72() {
     1940        uint16 a = getNextWord();
     1941        byte b = getNextByte();
     1942        uint16 c = getNextWord();
     1943        warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
     1944        return 0;
    16011945}
    16021946
    1603 void o1_op73() {
     1947/*! \todo Implement this instruction
     1948 */
     1949int FWScript::o1_op73() {
    16041950        // I believe this opcode is identical to o1_op72(). In fact, Operation
    16051951        // Stealth doesn't even have it. It uses o1_op72() instead.
    1606         warning("STUB: o1_op73()");
    1607         getNextWord();
    1608         getNextByte();
    1609         getNextWord();
     1952        uint16 a = getNextWord();
     1953        byte b = getNextByte();
     1954        uint16 c = getNextWord();
     1955        warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
     1956        return 0;
    16101957}
    16111958
    1612 void o1_playSample() {
    1613         debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
     1959int FWScript::o1_playSample() {
     1960        debugC(5, kCineDebugScript, "Line: %d: playSample()", _line);
    16141961
    16151962        byte anim = getNextByte();
    16161963        byte channel = getNextByte();
     
    16211968        int16 volume = getNextWord();
    16221969        uint16 size = getNextWord();
    16231970
    1624         if (!animDataTable[anim].ptr1) {
    1625                 return;
     1971        const byte *data = animDataTable[anim].data();
     1972
     1973        if (!data) {
     1974                return 0;
    16261975        }
    16271976
    16281977        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    16291978                if (size == 0xFFFF) {
    1630                         size = animDataTable[anim].width * animDataTable[anim].height;
     1979                        size = animDataTable[anim].width() * animDataTable[anim].height();
    16311980                }
    16321981                if (channel < 10) { // || _currentOpcode == 0x78
    16331982                        int channel1, channel2;
     
    16381987                                channel1 = 2;
    16391988                                channel2 = 3;
    16401989                        }
    1641                         g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat);
    1642                         g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size,  1, volume,  0, repeat);
     1990                        g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
     1991                        g_sound->playSound(channel2, freq, data, size,  1, volume,  0, repeat);
    16431992                } else {
    16441993                        channel -= 10;
    16451994                        if (volume > 63) {
    16461995                                volume = 63;
    16471996                        }
    1648                         g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat);
     1997                        g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat);
    16491998                }
    16501999        } else {
    16512000                if (volume > 63 || volume < 0) {
     
    16582007                        volume = 50;
    16592008                }
    16602009                if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
    1661                         return;
     2010                        return 0;
    16622011                }
    16632012                g_sound->stopMusic();
    16642013                if (size == 0xFFFF) {
    1665                         g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0);
     2014                        g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0);
    16662015                } else {
    16672016                        g_sound->stopSound(channel);
    16682017                }
    16692018        }
     2019        return 0;
    16702020}
    16712021
    1672 void o1_disableSystemMenu() {
     2022int FWScript::o1_disableSystemMenu() {
    16732023        byte param = getNextByte();
    16742024
    1675         debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param);
     2025        debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
    16762026        disableSystemMenu = (param != 0);
     2027        return 0;
    16772028}
    16782029
    1679 void o1_loadMask5() {
     2030int FWScript::o1_loadMask5() {
    16802031        byte param = getNextByte();
    16812032
    1682         debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param);
     2033        debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
    16832034        loadOverlayElement(param, 5);
     2035        return 0;
    16842036}
    16852037
    1686 void o1_unloadMask5() {
     2038int FWScript::o1_unloadMask5() {
    16872039        byte param = getNextByte();
    16882040
    1689         debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param);
     2041        debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
    16902042        freeOverlay(param, 5);
     2043        return 0;
    16912044}
    16922045
    16932046// ------------------------------------------------------------------------
    16942047// OPERATION STEALTH opcodes
    16952048// ------------------------------------------------------------------------
    16962049
    1697 void o2_loadPart() {
     2050int FWScript::o2_loadPart() {
    16982051        const char *param = getNextString();
    16992052
    1700         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     2053        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
     2054        return 0;
    17012055}
    17022056
    1703 void o2_playSample() {
     2057int FWScript::o2_playSample() {
    17042058        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    17052059                // no-op in these versions
    17062060                getNextByte();
     
    17092063                getNextByte();
    17102064                getNextWord();
    17112065                getNextWord();
    1712                 return;
     2066                return 0;
    17132067        }
    1714         o1_playSample();
     2068        return o1_playSample();
    17152069}
    17162070
    1717 void o2_playSampleAlt() {
     2071int FWScript::o2_playSampleAlt() {
    17182072        byte num = getNextByte();
    17192073        byte channel = getNextByte();
    17202074        uint16 frequency = getNextWord();
     
    17232077        uint16 size = getNextWord();
    17242078
    17252079        if (size == 0xFFFF) {
    1726                 size = animDataTable[num].width * animDataTable[num].height;
     2080                size = animDataTable[num].width() * animDataTable[num].height();
    17272081        }
    1728         if (animDataTable[num].ptr1) {
     2082        if (animDataTable[num].data()) {
    17292083                if (g_cine->getPlatform() == Common::kPlatformPC) {
    17302084                        // if speaker output is available, play sound on it
    17312085                        // if it's another device, don't play anything
    17322086                        // TODO: implement this, it's used in the introduction for example
    17332087                        // on each letter displayed
    17342088                } else {
    1735                         g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0);
     2089                        g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
    17362090                }
    17372091        }
     2092        return 0;
    17382093}
    17392094
    1740 void o2_addSeqListElement() {
     2095int FWScript::o2_addSeqListElement() {
    17412096        byte param1 = getNextByte();
    17422097        byte param2 = getNextByte();
    17432098        byte param3 = getNextByte();
     
    17462101        uint16 param6 = getNextWord();
    17472102        uint16 param7 = getNextWord();
    17482103
    1749         debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7);
     2104        debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
    17502105        addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
     2106        return 0;
    17512107}
    17522108
    1753 void o2_removeSeq() {
     2109int FWScript::o2_removeSeq() {
    17542110        byte a = getNextByte();
    17552111        byte b = getNextByte();
    17562112
    1757         debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b);
     2113        debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
    17582114        removeSeq(a, 0, b);
     2115        return 0;
    17592116}
    17602117
    1761 void o2_op81() {
     2118/*! \todo Implement this instruction
     2119 */
     2120int FWScript::o2_op81() {
    17622121        warning("STUB: o2_op81()");
    17632122        // freeUnkList();
     2123        return 0;
    17642124}
    17652125
    1766 void o2_op82() {
    1767         warning("STUB: o2_op82()");
    1768         getNextByte();
    1769         getNextByte();
    1770         getNextWord();
     2126/*! \todo Implement this instruction
     2127 */
     2128int FWScript::o2_op82() {
     2129        byte a = getNextByte();
     2130        byte b = getNextByte();
     2131        uint16 c = getNextWord();
     2132        warning("STUB: o2_op82(%x, %x, %x)", a, b, c);
     2133        return 0;
    17712134}
    17722135
    1773 void o2_isSeqRunning() {
     2136int FWScript::o2_isSeqRunning() {
    17742137        byte a = getNextByte();
    17752138        byte b = getNextByte();
    17762139
    1777         debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b);
     2140        debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
    17782141
    17792142        if (isSeqRunning(a, 0, b)) {
    1780                 _currentScriptElement->compareResult = 1;
     2143                _compare = 1;
    17812144        } else {
    1782                 _currentScriptElement->compareResult = 0;
     2145                _compare = 0;
    17832146        }
     2147        return 0;
    17842148}
    17852149
    1786 void o2_gotoIfSupNearest() {
     2150/*! \todo The assert may produce false positives and requires testing
     2151 */
     2152int FWScript::o2_gotoIfSupNearest() {
    17872153        byte labelIdx = getNextByte();
    17882154
    1789         if (_currentScriptElement->compareResult == kCmpGT) {
    1790                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2155        if (_compare == kCmpGT) {
     2156                assert(_labels[labelIdx] != -1);
    17912157
    1792                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx);
    1793                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2158                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
     2159                _pos = _script.getLabel(*_info, labelIdx, _pos);
    17942160        } else {
    1795                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx);
     2161                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
    17962162        }
     2163        return 0;
    17972164}
    17982165
    1799 void o2_gotoIfSupEquNearest() {
     2166/*! \todo The assert may produce false positives and requires testing
     2167 */
     2168int FWScript::o2_gotoIfSupEquNearest() {
    18002169        byte labelIdx = getNextByte();
    18012170
    1802         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1803                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2171        if (_compare & (kCmpGT | kCmpEQ)) {
     2172                assert(_labels[labelIdx] != -1);
    18042173
    1805                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx);
    1806                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2174                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
     2175                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18072176        } else {
    1808                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx);
     2177                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
    18092178        }
     2179        return 0;
    18102180}
    18112181
    1812 void o2_gotoIfInfNearest() {
     2182/*! \todo The assert may produce false positives and requires testing
     2183 */
     2184int FWScript::o2_gotoIfInfNearest() {
    18132185        byte labelIdx = getNextByte();
    18142186
    1815         if (_currentScriptElement->compareResult == kCmpLT) {
    1816                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2187        if (_compare == kCmpLT) {
     2188                assert(_labels[labelIdx] != -1);
    18172189
    1818                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx);
    1819                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2190                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
     2191                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18202192        } else {
    1821                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx);
     2193                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
    18222194        }
     2195        return 0;
    18232196}
    18242197
    1825 void o2_gotoIfInfEquNearest() {
     2198/*! \todo The assert may produce false positives and requires testing
     2199 */
     2200int FWScript::o2_gotoIfInfEquNearest() {
    18262201        byte labelIdx = getNextByte();
    18272202
    1828         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1829                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2203        if (_compare & (kCmpLT | kCmpEQ)) {
     2204                assert(_labels[labelIdx] != -1);
    18302205
    1831                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx);
    1832                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2206                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
     2207                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18332208        } else {
    1834                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx);
     2209                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
    18352210        }
     2211        return 0;
    18362212}
    18372213
    1838 void o2_gotoIfEquNearest() {
     2214/*! \todo The assert may produce false positives and requires testing
     2215 */
     2216int FWScript::o2_gotoIfEquNearest() {
    18392217        byte labelIdx = getNextByte();
    18402218
    1841         if (_currentScriptElement->compareResult == kCmpEQ) {
    1842                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2219        if (_compare == kCmpEQ) {
     2220                assert(_labels[labelIdx] != -1);
    18432221
    1844                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx);
    1845                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2222                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
     2223                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18462224        } else {
    1847                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx);
     2225                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
    18482226        }
     2227        return 0;
    18492228}
    18502229
    1851 void o2_gotoIfDiffNearest() {
     2230/*! \todo The assert may produce false positives and requires testing
     2231 */
     2232int FWScript::o2_gotoIfDiffNearest() {
    18522233        byte labelIdx = getNextByte();
    18532234
    1854         if (_currentScriptElement->compareResult != kCmpEQ) {
    1855                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2235        if (_compare != kCmpEQ) {
     2236                assert(_labels[labelIdx] != -1);
    18562237
    1857                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx);
    1858                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2238                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
     2239                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18592240        } else {
    1860                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx);
     2241                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
    18612242        }
     2243        return 0;
    18622244}
    18632245
    1864 void o2_startObjectScript() {
     2246int FWScript::o2_startObjectScript() {
    18652247        byte param = getNextByte();
    18662248
    1867         debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param);
     2249        debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
    18682250        runObjectScript(param);
     2251        return 0;
    18692252}
    18702253
    1871 void o2_stopObjectScript() {
     2254int FWScript::o2_stopObjectScript() {
    18722255        byte param = getNextByte();
    18732256
    1874         debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param);
    1875         stopObjectScript(param);
     2257        debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
     2258        ScriptList::iterator it = objectScripts.begin();
     2259
     2260        for (; it != objectScripts.end(); ++it) {
     2261                if ((*it)->index() == param) {
     2262                        (*it)->_index = -1;
     2263                }
     2264        }
     2265        return 0;
    18762266}
    18772267
    1878 void o2_op8D() {
    1879         warning("STUB: o2_op8D()");
    1880         getNextWord();
    1881         getNextWord();
    1882         getNextWord();
    1883         getNextWord();
    1884         getNextWord();
    1885         getNextWord();
    1886         getNextWord();
    1887         getNextWord();
     2268/*! \todo Implement this instruction
     2269 */
     2270int FWScript::o2_op8D() {
     2271        uint16 a = getNextWord();
     2272        uint16 b = getNextWord();
     2273        uint16 c = getNextWord();
     2274        uint16 d = getNextWord();
     2275        uint16 e = getNextWord();
     2276        uint16 f = getNextWord();
     2277        uint16 g = getNextWord();
     2278        uint16 h = getNextWord();
     2279        warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
    18882280        // _currentScriptElement->compareResult = ...
     2281        return 0;
    18892282}
    18902283
    1891 void o2_addBackground() {
     2284int FWScript::o2_addBackground() {
    18922285        byte param1 = getNextByte();
    18932286        const char *param2 = getNextString();
    18942287
    1895         debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1);
     2288        debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
    18962289        addBackground(param2, param1);
     2290        return 0;
    18972291}
    18982292
    1899 void o2_removeBackground() {
     2293int FWScript::o2_removeBackground() {
    19002294        byte param = getNextByte();
    19012295
    19022296        assert(param);
    19032297
    1904         debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param);
     2298        debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
    19052299
    19062300        if (additionalBgTable[param]) {
    19072301                free(additionalBgTable[param]);
     
    19172311        }
    19182312
    19192313        strcpy(currentBgName[param], "");
     2314        return 0;
    19202315}
    19212316
    1922 void o2_loadAbs() {
     2317int FWScript::o2_loadAbs() {
    19232318        byte param1 = getNextByte();
    19242319        const char *param2 = getNextString();
    19252320
    1926         debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2);
     2321        debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
    19272322        loadAbs(param2, param1);
     2323        return 0;
    19282324}
    19292325
    1930 void o2_loadBg() {
     2326int FWScript::o2_loadBg() {
    19312327        byte param = getNextByte();
    19322328
    19332329        assert(param <= 8);
    19342330
    1935         debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param);
     2331        debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
    19362332
    19372333        if (additionalBgTable[param]) {
    19382334                currentAdditionalBgIdx = param;
     
    19412337                //}
    19422338                fadeRequired = true;
    19432339        }
     2340        return 0;
    19442341}
    19452342
    1946 void o2_wasZoneChecked() {
     2343/*! \todo Implement this instruction
     2344 */
     2345int FWScript::o2_wasZoneChecked() {
    19472346        warning("STUB: o2_wasZoneChecked()");
     2347        return 0;
    19482348}
    19492349
    1950 void o2_op9B() {
    1951         warning("STUB: o2_op9B()");
    1952         getNextWord();
    1953         getNextWord();
    1954         getNextWord();
    1955         getNextWord();
    1956         getNextWord();
    1957         getNextWord();
    1958         getNextWord();
    1959         getNextWord();
     2350/*! \todo Implement this instruction
     2351 */
     2352int FWScript::o2_op9B() {
     2353        uint16 a = getNextWord();
     2354        uint16 b = getNextWord();
     2355        uint16 c = getNextWord();
     2356        uint16 d = getNextWord();
     2357        uint16 e = getNextWord();
     2358        uint16 f = getNextWord();
     2359        uint16 g = getNextWord();
     2360        uint16 h = getNextWord();
     2361        warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
     2362        return 0;
    19602363}
    19612364
    1962 void o2_op9C() {
    1963         warning("STUB: o2_op9C()");
    1964         getNextWord();
    1965         getNextWord();
    1966         getNextWord();
    1967         getNextWord();
     2365/*! \todo Implement this instruction
     2366 */
     2367int FWScript::o2_op9C() {
     2368        uint16 a = getNextWord();
     2369        uint16 b = getNextWord();
     2370        uint16 c = getNextWord();
     2371        uint16 d = getNextWord();
     2372        warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
     2373        return 0;
    19682374}
    19692375
    1970 void o2_useBgScroll() {
     2376int FWScript::o2_useBgScroll() {
    19712377        byte param = getNextByte();
    19722378
    19732379        assert(param <= 8);
    19742380
    1975         debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param);
     2381        debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
    19762382
    19772383        if (additionalBgTable[param]) {
    19782384                currentAdditionalBgIdx2 = param;
    19792385        }
     2386        return 0;
    19802387}
    19812388
    1982 void o2_setAdditionalBgVScroll() {
     2389int FWScript::o2_setAdditionalBgVScroll() {
    19832390        byte param1 = getNextByte();
    19842391
    19852392        if (param1) {
    19862393                byte param2 = getNextByte();
    19872394
    1988                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2);
    1989                 additionalBgVScroll = _currentScriptElement->localVars[param2];
     2395                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
     2396                additionalBgVScroll = _localVars[param2];
    19902397        } else {
    19912398                uint16 param2 = getNextWord();
    19922399
    1993                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2);
     2400                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
    19942401                additionalBgVScroll = param2;
    19952402        }
     2403        return 0;
    19962404}
    19972405
    1998 void o2_op9F() {
     2406/*! \todo Implement this instruction
     2407 */
     2408int FWScript::o2_op9F() {
    19992409        warning("o2_op9F()");
    20002410        getNextWord();
    20012411        getNextWord();
     2412        return 0;
    20022413}
    20032414
    2004 void o2_addGfxElementA0() {
     2415int FWScript::o2_addGfxElementA0() {
    20052416        uint16 param1 = getNextWord();
    20062417        uint16 param2 = getNextWord();
    20072418
    2008         debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2);
     2419        debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
    20092420        addGfxElementA0(param1, param2);
     2421        return 0;
    20102422}
    20112423
    2012 void o2_opA1() {
    2013         warning("STUB: o2_opA1()");
    2014         getNextWord();
    2015         getNextWord();
    2016         // removeGfxElementA0( ... );
     2424/*! \todo Implement this instruction
     2425 */
     2426int FWScript::o2_removeGfxElementA0() {
     2427        uint16 idx = getNextWord();
     2428        uint16 param = getNextWord();
     2429        warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param);
     2430        removeGfxElementA0(idx, param);
     2431        return 0;
    20172432}
    20182433
    2019 void o2_opA2() {
    2020         warning("STUB: o2_opA2()");
    2021         getNextWord();
    2022         getNextWord();
     2434/*! \todo Implement this instruction
     2435 */
     2436int FWScript::o2_opA2() {
     2437        uint16 a = getNextWord();
     2438        uint16 b = getNextWord();
     2439        warning("STUB: o2_opA2(%x, %x)", a, b);
    20232440        // addGfxElementA2();
     2441        return 0;
    20242442}
    20252443
    2026 void o2_opA3() {
    2027         warning("STUB: o2_opA3()");
    2028         getNextWord();
    2029         getNextWord();
     2444/*! \todo Implement this instruction
     2445 */
     2446int FWScript::o2_opA3() {
     2447        uint16 a = getNextWord();
     2448        uint16 b = getNextWord();
     2449        warning("STUB: o2_opA3(%x, %x)", a, b);
    20302450        // removeGfxElementA2();
     2451        return 0;
    20312452}
    20322453
    2033 void o2_loadMask22() {
     2454int FWScript::o2_loadMask22() {
    20342455        byte param = getNextByte();
    20352456
    2036         debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param);
     2457        debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
    20372458        loadOverlayElement(param, 22);
     2459        return 0;
    20382460}
    20392461
    2040 void o2_unloadMask22() {
     2462int FWScript::o2_unloadMask22() {
    20412463        byte param = getNextByte();
    20422464
    2043         debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param);
     2465        debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
    20442466        freeOverlay(param, 22);
     2467        return 0;
    20452468}
    20462469
    2047 // ------------------------------------------------------------------------
     2470//-----------------------------------------------------------------------
    20482471
    2049 void executeScript(prcLinkedListStruct *scriptElement, uint16 params) {
    2050         assert(scriptElement);
     2472void addGfxElementA0(int16 param1, int16 param2) {
     2473        overlayHeadElement *currentHead = &overlayHead;
     2474        overlayHeadElement *tempHead = currentHead;
     2475        overlayHeadElement *newElement;
    20512476
    2052         if (scriptElement->scriptIdx == -1) {
     2477        currentHead = tempHead->next;
     2478
     2479        while (currentHead) {
     2480                if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
     2481                        if (currentHead->type == 2 || currentHead->objIdx == 3) {
     2482                                break;
     2483                        }
     2484                }
     2485
     2486                tempHead = currentHead;
     2487                currentHead = currentHead->next;
     2488        }
     2489
     2490        if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
    20532491                return;
     2492
     2493        newElement = new overlayHeadElement;
     2494
     2495        newElement->next = tempHead->next;
     2496        tempHead->next = newElement;
     2497
     2498        newElement->objIdx = param1;
     2499        newElement->type = 20;
     2500
     2501        newElement->x = param2;
     2502        newElement->y = 0;
     2503        newElement->width = 0;
     2504        newElement->color = 0;
     2505
     2506        if (!currentHead)
     2507                currentHead = &overlayHead;
     2508
     2509        newElement->previous = currentHead->previous;
     2510
     2511        currentHead->previous = newElement;
     2512}
     2513
     2514/*! \todo Check that it works
     2515 */
     2516void removeGfxElementA0(int16 idx, int16 param) {
     2517        overlayHeadElement *parent = &overlayHead;
     2518        overlayHeadElement *head = overlayHead.next;
     2519        overlayHeadElement *tmp;
     2520
     2521        while (head) {
     2522                if (head->objIdx == idx && head->x == param) {
     2523                        parent->next = head->next;
     2524                        tmp = head->next ? head->next : &overlayHead;
     2525                        tmp->previous = parent;
     2526                        delete head;
     2527                        return;
     2528                }
     2529
     2530                parent = head;
     2531                head = head->next;
    20542532        }
     2533}
    20552534
    2056         assert(scriptElement->scriptPtr);
     2535void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
     2536        SeqListElement *currentHead = &seqList;
     2537        SeqListElement *tempHead = currentHead;
    20572538
    2058         _currentScriptElement = scriptElement;
    2059         _currentScriptParams = params;
    2060         _currentScriptPtr = scriptElement->scriptPtr;
    2061         _currentPosition = scriptElement->scriptPosition;
     2539        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2540                tempHead = currentHead;
     2541                currentHead = tempHead->next;
     2542        }
    20622543
    2063         _closeScript = 0;
     2544        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2545                currentHead->var4 = -1;
     2546        }
     2547}
    20642548
    2065         while (!_closeScript) {
    2066                 _currentLine = _currentPosition;
     2549uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
     2550        SeqListElement *currentHead = &seqList;
     2551        SeqListElement *tempHead = currentHead;
    20672552
    2068                 byte opcode = getNextByte();
     2553        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2554                tempHead = currentHead;
     2555                currentHead = tempHead->next;
     2556        }
    20692557
    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);
     2558        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2559                return 1;
     2560        }
     2561
     2562        return 0;
     2563}
     2564
     2565void palRotate(byte a, byte b, byte c) {
     2566        if (c == 1) {
     2567                uint16 currentColor = c_palette[b];
     2568
     2569                for (int16 i = b; i > a; i--) {
     2570                        c_palette[i] = c_palette[i - 1];
    20752571                }
     2572
     2573                c_palette[a] = currentColor;
    20762574        }
    20772575}
    20782576
    2079 void executeList1(void) {
    2080         prcLinkedListStruct *currentHead = objScriptList.next;
     2577void addScriptToList0(uint16 idx) {
     2578        ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
     2579        assert(tmp);
     2580        globalScripts.push_back(tmp);
     2581}
    20812582
    2082         while (currentHead) {
    2083                 prcLinkedListStruct *tempHead;
     2583int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
     2584        byte *ptr = page + (y * width) + x / 2;
     2585        byte zoneVar;
    20842586
    2085                 tempHead = currentHead->next;
     2587        if (!(x % 2)) {
     2588                zoneVar = (*(ptr) >> 4) & 0xF;
     2589        } else {
     2590                zoneVar = (*(ptr)) & 0xF;
     2591        }
    20862592
    2087                 executeScript(currentHead, 1);
     2593        return zoneVar;
     2594}
    20882595
    2089                 currentHead = tempHead;
     2596int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
     2597        byte *ptr = page + (y * width) + x;
     2598        byte zoneVar;
     2599
     2600        zoneVar = (*(ptr)) & 0xF;
     2601
     2602        return zoneVar;
     2603}
     2604
     2605int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
     2606        int16 lx = objectTable[objIdx].x + x;
     2607        int16 ly = objectTable[objIdx].y + y;
     2608        int16 idx;
     2609
     2610        for (int16 i = 0; i < numZones; i++) {
     2611                idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     2612
     2613                assert(idx >= 0 && idx <= NUM_MAX_ZONE);
     2614
     2615                if (zoneData[idx] == zoneIdx) {
     2616                        return 1;
     2617                }
    20902618        }
     2619
     2620        return 0;
    20912621}
    20922622
    2093 void executeList0(void) {
    2094         prcLinkedListStruct *currentHead = globalScriptsHead.next;
     2623uint16 compareVars(int16 a, int16 b) {
     2624        uint16 flag = 0;
    20952625
    2096         while (currentHead) {
    2097                 prcLinkedListStruct *tempHead;
     2626        if (a == b) {
     2627                flag |= kCmpEQ;
     2628        } else if (a > b) {
     2629                flag |= kCmpGT;
     2630        } else if (a < b) {
     2631                flag |= kCmpLT;
     2632        }
    20982633
    2099                 executeScript(currentHead, 0);
     2634        return flag;
     2635}
    21002636
    2101                 tempHead = currentHead->next;
    2102                 currentHead = tempHead;
     2637void executeList1(void) {
     2638        ScriptList::iterator it = objectScripts.begin();
     2639        for (; it != objectScripts.end();) {
     2640                if ((*it)->index() < 0 || (*it)->execute() < 0) {
     2641                        it = objectScripts.erase(it);
     2642                } else {
     2643                        ++it;
     2644                }
    21032645        }
    21042646}
    21052647
     2648void executeList0(void) {
     2649        ScriptList::iterator it = globalScripts.begin();
     2650        for (; it != globalScripts.end();) {
     2651                if ((*it)->index() < 0 || (*it)->execute() < 0) {
     2652                        it = globalScripts.erase(it);
     2653                } else {
     2654                        ++it;
     2655                }
     2656        }
     2657}
     2658
     2659/*! \todo objectScripts.clear()?
     2660 */
    21062661void purgeList1(void) {
    21072662}
    21082663
     
    28043359                                sprintf(lineBuffer, "disallowPlayerInput()\n");
    28053360                                break;
    28063361                        }
    2807                 case OP_changeDataDisk:
     3362                case 0x6B:
    28083363                        {
    28093364                                byte newDisk;
    28103365
     
    28783433
    28793434                                if (opcode - 1 == 0x77) {
    28803435                                        sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    2881                                 else if (opcode - 1 == 0x78) {
     3436                                } else if (opcode - 1 == 0x78) {
    28823437                                        sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    28833438                                }
    28843439
  • engines/cine/part.cpp

     
    3333
    3434uint16 numElementInPart;
    3535
    36 AnimData *animDataTable;
    3736PartBuffer *partBuffer;
    3837
    3938void loadPart(const char *partName) {
  • 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

     
    111111
    112112        partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer));
    113113
    114         animDataTable = (AnimData *)malloc(NUM_MAX_ANIMDATA * sizeof(AnimData));
    115 
    116114        if (g_cine->getGameType() == Cine::GType_OS) {
    117115                readVolCnf();
    118116        }
     
    124122                loadErrmessDat("errmess.dat");
    125123        }
    126124
     125        // in case ScummVM engines can be restarted in the future
     126        scriptTable.clear();
     127        relTable.clear();
     128        objectScripts.clear();
     129        globalScripts.clear();
     130
    127131        memset(objectTable, 0, sizeof(objectTable));
    128         memset(scriptTable, 0, sizeof(scriptTable));
    129132        memset(messageTable, 0, sizeof(messageTable));
    130         memset(relTable, 0, sizeof(relTable));
    131133
    132         for (int i = 0; i < NUM_MAX_ANIMDATA; i++) {
    133                 animDataTable[i].ptr1 = animDataTable[i].ptr2 = NULL;
    134         }
    135 
    136134        overlayHead.next = overlayHead.previous = NULL;
    137135
    138136        var8 = 0;
    139137        bgIncrustList = NULL;
    140138
    141         objScriptList.next = NULL;
    142         objScriptList.scriptPtr = NULL;
    143 
    144         globalScriptsHead.next = NULL;
    145         globalScriptsHead.scriptPtr = NULL;
    146 
    147139        var2 = var3 = var4 = var5 = 0;
    148140
    149         freePrcLinkedList();
    150 
    151141        _preLoad = false;
    152142        if (ConfMan.hasKey("save_slot")) {
    153143                char saveNameBuffer[256];
  • engines/cine/gfx.cpp

     
    3737uint16 c_palette[256];
    3838byte colorMode256 = 0;
    3939byte palette256[256 * 3];
     40byte newPalette[256 * 3];
     41byte newColorMode = 0;
    4042
    4143byte *screenBuffer;
    4244byte *page1Raw;
     
    157159        //gfxFlipPage(page2);
    158160}
    159161
    160 void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
     162void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
    161163        int16 i, j;
    162164
    163165        for (i = 0; i < height; i++) {
     
    180182        }
    181183}
    182184
    183 void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
     185void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    184186        int16 i, j;
    185187
    186188        for (i = 0; i < height; i++) {
     
    198200        }
    199201}
    200202
    201 void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
     203void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    202204        int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx) {
    203205        int16 i, j, d, spritePitch, maskPitch;
    204206
     
    299301        }
    300302}
    301303
    302 int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width) {
    303         byte *ptrToData = (ptr) + y * width + x;
     304int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width) {
     305        const byte *ptrToData = (ptr) + y * width + x;
    304306
    305307        if (x > width) {
    306308                return 0;
     
    379381        g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200);
    380382}
    381383
    382 void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height,
     384void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height,
    383385                                   byte *page, int16 x, int16 y) {
    384386        int16 i, j;
    385387
     
    406408        }
    407409}
    408410
    409 void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height,
     411void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height,
    410412                                        byte *page, int16 x, int16 y) {
    411413        int16 i, j;
    412414
     
    425427        }
    426428}
    427429
     430/*! \todo Fix rendering to prevent fadein artifacts
     431 */
     432void fadeFromBlack() {
     433        int i, j;
     434        int r, g, b, tr, tg, tb;
     435        if (newColorMode == 2) {
     436                colorMode256 = 1;
     437                memset(palette256, 0, 256*3);
     438        } else if (newColorMode == 1) {
     439                colorMode256 = 0;
     440                memset(c_palette, 0, 16 * sizeof(uint16));
     441        }
     442
     443        for (i = 0; i < 8; i++ ) {
     444                gfxFlipRawPage(page1Raw);
     445                g_system->updateScreen();
     446                g_system->delayMillis(50);
     447
     448                if (colorMode256) {
     449                        for (j = 0; j < 256*3; j++) {
     450                                r = palette256[j] + (newPalette[j] + 7) / 8;
     451                                palette256[j] = CLIP(r, 0, (int)newPalette[j]);
     452                        }
     453                } else {
     454                        for (j = 0; j < 16; j++) {
     455                                r = c_palette[j] & 0xf;
     456                                g = (c_palette[j] & 0xf0) >> 4;
     457                                b = (c_palette[j] & 0xf00) >> 8;
     458
     459                                tr = tempPalette[j] & 0xf;
     460                                tg = (tempPalette[j] & 0xf0) >> 4;
     461                                tb = (tempPalette[j] & 0xf00) >> 8;
     462
     463                                r = CLIP(r + (tr + 7) / 8, 0, tr);
     464                                g = CLIP(g + (tg + 7) / 8, 0, tg);
     465                                b = CLIP(b + (tb + 7) / 8, 0, tb);
     466
     467                                c_palette[j] = r | (g << 4) | (b << 8);
     468                        }
     469
     470                }
     471        }
     472
     473        if (colorMode256) {
     474                memcpy(palette256, newPalette, 256*3);
     475        } else {
     476                memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     477        }
     478}
     479
    428480void fadeToBlack() {
    429481        for (int i = 0; i < 8; i++) {
    430482                if (colorMode256) {
    431                         for (int j = 0; j < 256; j++) {
    432                                 palette256[j] = transformColor(palette256[j], -1, -1, -1);
     483                        for (int j = 0; j < 256*3; j++) {
     484                                palette256[j] = CLIP(palette256[j] - 32, 0, 255);
    433485                        }
    434486                } else {
    435487                        for (int j = 0; j < 16; j++) {
     
    449501void flip(void) {
    450502        blitRawScreen(page1Raw);
    451503        if (fadeRequired) {
    452                 memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     504                if (newColorMode == 2) {
     505                        colorMode256 = 1;
     506                        memcpy(palette256, newPalette, 256*3);
     507                } else {
     508                        colorMode256 = 0;
     509                        memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     510                }
    453511                fadeRequired = false;
    454512        }
    455513}
  • 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
  • engines/cine/bg.cpp

     
    7878}
    7979
    8080void loadBgHigh(const char *currentPtr) {
    81         memcpy(palette256, currentPtr, 256 * 3);
     81        memcpy(newPalette, currentPtr, 256 * 3);
    8282        currentPtr += 256 * 3;
    8383
    8484        memcpy(page2Raw, currentPtr, 320 * 200);
    8585
    86         colorMode256 = 1;
     86        newColorMode = 2;
    8787}
    8888
    8989byte loadBg(const char *bgName) {
     
    9999        if (bpp == 8) {
    100100                loadBgHigh((const char *)ptr);
    101101        } else {
    102                 colorMode256 = 0;
     102                newColorMode = 1;
    103103
    104104                for (int i = 0; i < 16; i++) {
    105105                        tempPalette[i] = READ_BE_UINT16(ptr);
  • engines/cine/texte.cpp

     
    4040const char **otherMessages;
    4141const char *commandPrepositionOn;
    4242
    43 void generateMask(byte *sprite, byte *mask, uint16 size, byte transparency);
     43void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
    4444
    4545void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
    4646        Common::File pFileHandle;
  • engines/cine/anim.h

     
    5454        byte color;
    5555};
    5656
     57#define ANIM_RAW 0 // memcpy
     58#define ANIM_MASK 1 // convertMask
     59#define ANIM_SPRITE 2 // gfxConvertSpriteToRaw
     60#define ANIM_MASKSPRITE 3 // gfxConvertSpriteToRaw + generateMask
     61#define ANIM_PALSPRITE 5 // convert8BBP
     62#define ANIM_FULLSPRITE 8 // convert8BBP2
     63
     64class animData {
     65private:
     66        uint16 _width; ///< Image width (ussually twice the real size)
     67        uint16 _height; ///< Image height
     68        uint16 _bpp; ///< Bit depth/type information
     69        uint16 _var1; ///< Something related to width
     70        byte *_data; ///< Image data
     71        byte *_mask; ///< Image mask (may be NULL)
     72        int16 _fileIdx; ///< Source file index in bundle
     73        int16 _frameIdx; ///< Frame number in animation
     74        char _name[10]; ///< Part filename
     75        int _size; ///< _data/_mask size, internal only
     76
     77public:
     78        animData();
     79        animData(const animData &src);
     80        ~animData();
     81
     82        animData &operator=(const animData &src);
     83
     84        uint16 width() const { return _width; } ///< Image width
     85        uint16 height() const { return _height; } ///< Image height
     86        uint16 bpp() const { return _bpp; } ///< Bit depth/type information
     87        uint16 var1() const { return _var1; } ///< Something related to width
     88        const byte *data() const { return _data; } ///< Image data
     89        const byte *mask() const { return _mask; } ///< Image mask (may be NULL)
     90
     91        void load(byte *d, int type, uint16 w, uint16 h, int16 file, int16 frame, const char *n, byte transparent = 0);
     92        void clear();
     93
     94        void save(Common::OutSaveFile &fHandle) const;
     95};
     96
     97#define NUM_MAX_ANIMDATA 255
     98
     99extern animData animDataTable[NUM_MAX_ANIMDATA];
     100
    57101void freeAnimDataTable(void);
    58102void freeAnimDataRange(byte startIdx, byte numIdx);
    59103void loadResource(const char *animName);
    60104void loadAbs(const char *resourceName, uint16 idx);
    61 void loadResourcesFromSave();
     105void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken);
    62106
    63107} // End of namespace Cine
    64108