Ticket #8841: osfix2.patch

File osfix2.patch, 198.8 KB (added by SF/next_ghost, 16 years ago)

Improved osfix patch

  • 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        byte *_data; ///< Script bytecode
     89        ScriptVars _labels; ///< Initial script labels
     90
     91protected:
     92        void computeLabels(const FWScriptInfo &info);
     93        int getNextLabel(const FWScriptInfo &info, int offset) const;
     94
     95public:
     96        uint16 _size; ///< Bytecode length
     97
     98        explicit RawScript(uint16 size);
     99        RawScript(const FWScriptInfo &info, const byte *data, uint16 size);
     100        RawScript(const RawScript &src);
     101        ~RawScript(void);
     102
     103        RawScript &operator=(const RawScript &src);
     104
     105        void setData(const FWScriptInfo &info, const byte *data);
     106        /*! \brief Size of script
     107         * \return Size of script
     108         */
     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 {
     122public:
     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
     128        RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3);
     129        RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3);
     130
     131        /// \brief Run the script one more time
     132        /// \return Run count before incrementation
     133        int16 run(void) { return _runCount++; }
     134};
     135
     136/*! \brief Future Wars script, prcLinkedListStruct replacement
     137 * \todo Rewrite _globalVars initialization
     138 */
     139class FWScript {
     140private:
     141        const RawScript &_script; ///< Script bytecode reference
     142        uint16 _pos; ///< Current position in script
     143        uint16 _line; ///< Current opcode index in bytecode for debugging
     144        uint16 _compare; ///< Last compare result
     145        ScriptVars _labels; ///< Current script labels
     146        ScriptVars _localVars; ///< Local script variables
     147        ScriptVars &_globalVars; ///< Global variables reference
     148        FWScriptInfo *_info; ///< Script info
     149
     150        static const Opcode _opcodeTable[];
     151        static const unsigned int _numOpcodes;
     152
     153protected:
     154        int o1_modifyObjectParam();
     155        int o1_getObjectParam();
     156        int o1_addObjectParam();
     157        int o1_subObjectParam();
     158        int o1_add2ObjectParam();
     159        int o1_sub2ObjectParam();
     160        int o1_compareObjectParam();
     161        int o1_setupObject();
     162        int o1_checkCollision();
     163        int o1_loadVar();
     164        int o1_addVar();
     165        int o1_subVar();
     166        int o1_mulVar();
     167        int o1_divVar();
     168        int o1_compareVar();
     169        int o1_modifyObjectParam2();
     170        int o1_loadMask0();
     171        int o1_unloadMask0();
     172        int o1_addToBgList();
     173        int o1_loadMask1();
     174        int o1_unloadMask1();
     175        int o1_loadMask4();
     176        int o1_unloadMask4();
     177        int o1_addSpriteFilledToBgList();
     178        int o1_op1B();
     179        int o1_label();
     180        int o1_goto();
     181        int o1_gotoIfSup();
     182        int o1_gotoIfSupEqu();
     183        int o1_gotoIfInf();
     184        int o1_gotoIfInfEqu();
     185        int o1_gotoIfEqu();
     186        int o1_gotoIfDiff();
     187        int o1_removeLabel();
     188        int o1_loop();
     189        int o1_startGlobalScript();
     190        int o1_endGlobalScript();
     191        int o1_loadAnim();
     192        int o1_loadBg();
     193        int o1_loadCt();
     194        int o1_loadPart();
     195        int o1_closePart();
     196        int o1_loadNewPrcName();
     197        int o1_requestCheckPendingDataLoad();
     198        int o1_blitAndFade();
     199        int o1_fadeToBlack();
     200        int o1_transformPaletteRange();
     201        int o1_setDefaultMenuColor2();
     202        int o1_palRotate();
     203        int o1_break();
     204        int o1_endScript();
     205        int o1_message();
     206        int o1_loadGlobalVar();
     207        int o1_compareGlobalVar();
     208        int o1_declareFunctionName();
     209        int o1_freePartRange();
     210        int o1_unloadAllMasks();
     211        int o1_setScreenDimensions();
     212        int o1_displayBackground();
     213        int o1_initializeZoneData();
     214        int o1_setZoneDataEntry();
     215        int o1_getZoneDataEntry();
     216        int o1_setDefaultMenuColor();
     217        int o1_allowPlayerInput();
     218        int o1_disallowPlayerInput();
     219        int o1_changeDataDisk();
     220        int o1_loadMusic();
     221        int o1_playMusic();
     222        int o1_fadeOutMusic();
     223        int o1_stopSample();
     224        int o1_op71();
     225        int o1_op72();
     226        int o1_op73();
     227        int o1_playSample();
     228        int o1_disableSystemMenu();
     229        int o1_loadMask5();
     230        int o1_unloadMask5();
     231
     232        // pointers to member functions in C++ suck...
     233        int o2_loadPart();
     234        int o2_addSeqListElement();
     235        int o2_removeSeq();
     236        int o2_playSample();
     237        int o2_playSampleAlt();
     238        int o2_op81();
     239        int o2_op82();
     240        int o2_isSeqRunning();
     241        int o2_gotoIfSupNearest();
     242        int o2_gotoIfSupEquNearest();
     243        int o2_gotoIfInfNearest();
     244        int o2_gotoIfInfEquNearest();
     245        int o2_gotoIfEquNearest();
     246        int o2_gotoIfDiffNearest();
     247        int o2_startObjectScript();
     248        int o2_stopObjectScript();
     249        int o2_op8D();
     250        int o2_addBackground();
     251        int o2_removeBackground();
     252        int o2_loadAbs();
     253        int o2_loadBg();
     254        int o2_wasZoneChecked();
     255        int o2_op9B();
     256        int o2_op9C();
     257        int o2_useBgScroll();
     258        int o2_setAdditionalBgVScroll();
     259        int o2_op9F();
     260        int o2_addGfxElementA0();
     261        int o2_removeGfxElementA0();
     262        int o2_opA2();
     263        int o2_opA3();
     264        int o2_loadMask22();
     265        int o2_unloadMask22();
     266
     267        byte getNextByte();
     268        uint16 getNextWord();
     269        const char *getNextString();
     270
     271        void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
     272
     273        FWScript(const RawScript &script, int16 index, FWScriptInfo *info);
     274        FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info);
     275        FWScript(const FWScript &src, FWScriptInfo *info);
     276
     277public:
     278        int16 _index; ///< Index in script table
     279
     280        FWScript(const RawScript &script, int16 index);
     281//      FWScript(const RawObjectScript &script, int16 index);
     282        FWScript(const FWScript &src);
     283        ~FWScript(void);
     284
     285        int execute();
     286        void save(Common::OutSaveFile &fHandle) const;
     287
     288        friend class FWScriptInfo;
     289
     290        // workaround for bug in g++ which prevents protected member functions
     291        // of FWScript from being used in OSScript::_opcodeTable[]
     292        // initialization ("error: protected within this context")
     293        friend class OSScript;
     294};
     295
     296/*! \brief Operation Stealth script, prcLinkedListStruct replacement
     297 */
     298class OSScript : public FWScript {
     299private:
     300        static const Opcode _opcodeTable[];
     301        static const unsigned int _numOpcodes;
     302
     303protected:
     304        void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos);
     305
     306public:
     307        OSScript(const RawScript &script, int16 index);
     308        OSScript(RawObjectScript &script, int16 index);
     309        OSScript(const OSScript &src);
     310
     311        friend class OSScriptInfo;
     312};
     313
     314/*! \brief Future Wars script factory and info
     315 */
     316class FWScriptInfo {
     317protected:
     318        virtual opFunc opcodeHandler(byte opcode) const;
     319
     320public:
     321        virtual ~FWScriptInfo() {}
     322
     323        virtual const char *opcodeInfo(byte opcode) const;
     324        virtual FWScript *create(const RawScript &script, int16 index) const;
     325        virtual FWScript *create(const RawObjectScript &script, int16 index) const;
     326        virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     327        virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const;
     328
     329        friend class FWScript;
     330};
     331
     332/*! \brief Operation Stealth script factory and info
     333 */
     334class OSScriptInfo : public FWScriptInfo {
     335protected:
     336        virtual opFunc opcodeHandler(byte opcode) const;
     337
     338public:
     339        virtual ~OSScriptInfo() {}
     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
     350typedef Common::SharedPtr<FWScript> ScriptPtr;
     351typedef Common::SharedPtr<RawScript> RawScriptPtr;
     352typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr;
     353typedef Common::List<ScriptPtr> ScriptList;
     354typedef Common::Array<RawScriptPtr> RawScriptArray;
     355typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray;
     356
    63357#define NUM_MAX_SCRIPT 50
    64358
    65 extern ScriptStruct scriptTable[NUM_MAX_SCRIPT];
     359extern RawScriptArray scriptTable;
     360extern FWScriptInfo *scriptInfo;
    66361
    67362void setupOpcodes();
    68363
    69 void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize);
    70364void decompileScript(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize, uint16 scriptIdx);
    71365void dumpScript(char *dumpName);
    72366
     
    79373int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx);
    80374
    81375void runObjectScript(int16 entryIdx);
    82 int16 stopObjectScript(int16 entryIdx);
    83376
    84377void executeList1(void);
    85378void executeList0(void);
     
    87380void purgeList1(void);
    88381void purgeList0(void);
    89382
    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 
    203383} // End of namespace Cine
    204384
    205385#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/object.h

     
    7474
    7575void addObjectParam(byte objIdx, byte paramIdx, int16 newValue);
    7676void subObjectParam(byte objIdx, byte paramIdx, int16 newValue);
    77 byte compareObjectParam(byte objIdx, byte param1, int16 param2);
     77uint16 compareObjectParam(byte objIdx, byte param1, int16 param2);
    7878
    7979} // End of namespace Cine
    8080
  • 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

     
    3636namespace Cine {
    3737
    3838uint32 var8;
    39 BGIncrustList *bgIncrustList;
     39Common::List<BGIncrust> bgIncrustList;
    4040
     41/*! \brief Add masked sprite to the background
     42 * \param objIdx Sprite description
     43 * \param addList Add sprite to incrust list if true
     44 * \todo Fix incrust objects on CT background. Always drawing incrust elements
     45 * on CT background breaks game zones
     46 */
    4147void addToBGList(int16 objIdx, bool addList) {
    4248        int16 x = objectTable[objIdx].x;
    4349        int16 y = objectTable[objIdx].y;
    44         int16 width = animDataTable[objectTable[objIdx].frame].var1;
    45         int16 height = animDataTable[objectTable[objIdx].frame].height;
     50        int16 width = animDataTable[objectTable[objIdx].frame]._var1;
     51        int16 height = animDataTable[objectTable[objIdx].frame]._height;
     52        const byte *data = animDataTable[objectTable[objIdx].frame].data();
     53        const byte *mask = animDataTable[objectTable[objIdx].frame].mask();
    4654//      int16 part = objectTable[objIdx].part;
    4755
     56        // Operation Stealth may switch among multiple backgrounds
    4857        if (g_cine->getGameType() == GType_OS) {
    49                 drawSpriteRaw2(animDataTable[objectTable[objIdx].frame].ptr1, objectTable[objIdx].part, width, height, page2Raw, x, y);
     58                for (int i = 0; i < 8; i++) {
     59                        if (additionalBgTable[i]) {
     60                                drawSpriteRaw2(data, objectTable[objIdx].part, width, height, additionalBgTable[i], x, y);
     61                        }
     62                }
    5063        } else {
    51                 drawSpriteRaw(animDataTable[objectTable[objIdx].frame].ptr1, animDataTable[objectTable[objIdx].frame].ptr2, width, height, page2Raw, x, y);
     64                drawSpriteRaw(data, mask, width, height, page2Raw, x, y);
    5265        }
    5366
    5467        if (addList)
    5568                createBgIncrustListElement(objIdx, 0);
    5669}
    5770
     71/*! \brief Add filled sprite to the background
     72 * \param objIdx Sprite description
     73 * \param addList Add sprite to incrust list if true
     74 * \todo Fix incrust objects on CT background. Always drawing incrust elements
     75 * on CT background breaks game zones
     76 */
    5877void addSpriteFilledToBGList(int16 objIdx, bool addList) {
    5978        int16 x = objectTable[objIdx].x;
    6079        int16 y = objectTable[objIdx].y;
    61         int16 width = animDataTable[objectTable[objIdx].frame].width;
    62         int16 height = animDataTable[objectTable[objIdx].frame].height;
     80        int16 width = animDataTable[objectTable[objIdx].frame]._width;
     81        int16 height = animDataTable[objectTable[objIdx].frame]._height;
     82        const byte *data = animDataTable[objectTable[objIdx].frame].data();
    6383
    64         if (animDataTable[objectTable[objIdx].frame].ptr1) {
    65                 gfxFillSprite(animDataTable[objectTable[objIdx].frame].ptr1, width / 2, height, page2Raw, x, y);
     84        if (data) {
     85                // Operation Stealth may switch among multiple backgrounds
     86                if (g_cine->getGameType() == GType_OS) {
     87                        for (int i = 0; i < 8; i++) {
     88                                if (additionalBgTable[i]) {
     89                                        gfxFillSprite(data, width / 2, height, additionalBgTable[i], x, y);
     90                                }
     91                        }
     92                } else {
     93                        gfxFillSprite(data, width / 2, height, page2Raw, x, y);
     94                }
    6695        }
    6796
    6897        if (addList)
    6998                createBgIncrustListElement(objIdx, 1);
    7099}
    71100
     101/*! \brief Add new element to incrust list
     102 * \param objIdx Element description
     103 * \param param Type of element
     104 */
    72105void createBgIncrustListElement(int16 objIdx, int16 param) {
    73         BGIncrustList *bgIncrustPtr = bgIncrustList;
    74         BGIncrustList *bgIncrustPtrP = 0;
     106        BGIncrust tmp;
    75107
    76         // Find first empty element
    77         while (bgIncrustPtr) {
    78                 bgIncrustPtrP = bgIncrustPtr;
    79                 bgIncrustPtr = bgIncrustPtr->next;
    80         }
     108        tmp.objIdx = objIdx;
     109        tmp.param = param;
     110        tmp.x = objectTable[objIdx].x;
     111        tmp.y = objectTable[objIdx].y;
     112        tmp.frame = objectTable[objIdx].frame;
     113        tmp.part = objectTable[objIdx].part;
    81114
    82         bgIncrustPtr = new BGIncrustList;
    83         if (bgIncrustPtrP)
    84                 bgIncrustPtrP->next = bgIncrustPtr;
    85         else
    86                 bgIncrustList = bgIncrustPtr;
    87 
    88         bgIncrustPtr->next = 0;
    89 
    90         bgIncrustPtr->objIdx = objIdx;
    91         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;
     115        bgIncrustList.push_back(tmp);
    96116}
    97117
    98 void freeBgIncrustList(void) {
    99         BGIncrustList *bgIncrustPtr = bgIncrustList;
    100         BGIncrustList *bgIncrustPtrN;
    101 
    102         while (bgIncrustPtr) {
    103                 bgIncrustPtrN = bgIncrustPtr->next;
    104                 delete bgIncrustPtr;
    105                 bgIncrustPtr = bgIncrustPtrN;
    106         }
    107 
    108         resetBgIncrustList();
    109 }
    110 
     118/*! \brief Reset var8 (probably something related to bgIncrustList
     119 */
    111120void resetBgIncrustList(void) {
    112         bgIncrustList = NULL;
    113121        var8 = 0;
    114122}
    115123
    116 void loadBgIncrustFromSave(Common::InSaveFile *fHandle) {
    117         BGIncrustList *bgIncrustPtr = bgIncrustList;
    118         BGIncrustList *bgIncrustPtrP = 0;
     124/*! \brief Restore incrust list from savefile
     125 * \param fHandle Savefile open for reading
     126 */
     127void loadBgIncrustFromSave(Common::InSaveFile &fHandle) {
     128        BGIncrust tmp;
     129        int size = fHandle.readSint16BE();
    119130
    120         // Find first empty element
    121         while (bgIncrustPtr) {
    122                 bgIncrustPtrP = bgIncrustPtr;
    123                 bgIncrustPtr = bgIncrustPtr->next;
    124         }
     131        for (int i = 0; i < size; i++) {
     132                fHandle.readUint32BE();
     133                fHandle.readUint32BE();
    125134
    126         bgIncrustPtr = new BGIncrustList;
    127         if (bgIncrustPtrP)
    128                 bgIncrustPtrP->next = bgIncrustPtr;
    129         else
    130                 bgIncrustList = bgIncrustPtr;
     135                tmp.objIdx = fHandle.readUint16BE();
     136                tmp.param = fHandle.readUint16BE();
     137                tmp.x = fHandle.readUint16BE();
     138                tmp.y = fHandle.readUint16BE();
     139                tmp.frame = fHandle.readUint16BE();
     140                tmp.part = fHandle.readUint16BE();
     141       
     142                bgIncrustList.push_back(tmp);
    131143
    132         bgIncrustPtr->next = 0;
    133 
    134         fHandle->readUint32BE();
    135         fHandle->readUint32BE();
    136 
    137         bgIncrustPtr->objIdx = fHandle->readUint16BE();
    138         bgIncrustPtr->param = fHandle->readUint16BE();
    139     bgIncrustPtr->x = fHandle->readUint16BE();
    140     bgIncrustPtr->y = fHandle->readUint16BE();
    141     bgIncrustPtr->frame = fHandle->readUint16BE();
    142     bgIncrustPtr->part = fHandle->readUint16BE();
    143 }
    144 
    145 void reincrustAllBg(void) {
    146         BGIncrustList *bgIncrustPtr = bgIncrustList;
    147 
    148         while (bgIncrustPtr) {
    149 #if 0
    150                 objectTable[bgIncrustPtr->objIdx].x = bgIncrustPtr->x;
    151                 objectTable[bgIncrustPtr->objIdx].y = bgIncrustPtr->y;
    152                 objectTable[bgIncrustPtr->objIdx].frame = bgIncrustPtr->frame;
    153                 objectTable[bgIncrustPtr->objIdx].part = bgIncrustPtr->part;
    154 #endif
    155                 if (bgIncrustPtr->param == 0) {
    156                         addToBGList(bgIncrustPtr->objIdx, false);
     144                if (tmp.param == 0) {
     145                        addToBGList(tmp.objIdx, false);
    157146                } else {
    158                         addSpriteFilledToBGList(bgIncrustPtr->objIdx, false);
     147                        addSpriteFilledToBGList(tmp.objIdx, false);
    159148                }
    160 
    161                 bgIncrustPtr = bgIncrustPtr->next;
    162149        }
    163150}
    164151
  • 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), _realWidth(0), _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), _realWidth(src._realWidth), _size(src._size) {
    212205
    213         removeExtention(name, animName);
     206        if (src._data) {
     207                _data = new byte[_size];
     208                assert(_data);
     209                memcpy(_data, src._data, _size*sizeof(byte));
     210        }
    214211
    215         for (int i = 0; i < ARRAYSIZE(animData); i++) {
    216                 if (!strcmp(name, animData[i].name)) {
    217                         return animData[i].color;
    218                 }
     212        if(src._mask) {
     213                _mask = new byte[_size];
     214                assert(_mask);
     215                memcpy(_mask, src._mask, _size*sizeof(byte));
    219216        }
    220         return 0;
     217
     218        memset(_name, 0, 10);
     219        strcpy(_name, src._name);
    221220}
    222221
    223 int16 allocFrame(uint16 width, uint16 height, int8 isMask) {
    224         uint16 i;
    225         uint32 frameSize;
     222/*! \brief Destructor
     223 */
     224AnimData::~AnimData() {
     225        clear();
     226}
    226227
    227         for (i = 0; i < NUM_MAX_ANIMDATA; i++) {
    228                 if (!animDataTable[i].ptr1)
    229                         break;
    230         }
     228/*! \brief Assingment operator
     229 */
     230AnimData &AnimData::operator=(const AnimData &src) {
     231        AnimData tmp = src;
     232        byte *ptr;
    231233
    232         if (i == NUM_MAX_ANIMDATA)
    233                 return -1;
     234        _width = tmp._width;
     235        _height = tmp._height;
     236        _bpp = tmp._bpp;
     237        _var1 = tmp._var1;
    234238
    235         if (!isMask) {          // sprite + generated mask
    236                 frameSize = width * height;
     239        ptr = _data;
     240        _data = tmp._data;
     241        tmp._data = ptr;
    237242
    238                 animDataTable[i].ptr1 = (byte *)malloc(frameSize);
    239                 animDataTable[i].ptr2 = (byte *)malloc(frameSize);
    240         } else {
    241                 // mask
    242                 frameSize = width * height * 8;
     243        ptr = _mask;
     244        _mask = tmp._mask;
     245        tmp._mask = ptr;
    243246
    244                 animDataTable[i].ptr1 = (byte *)malloc(frameSize);
    245                 animDataTable[i].ptr2 = NULL;
    246         }
     247        _fileIdx = tmp._fileIdx;
     248        _frameIdx = tmp._frameIdx;
     249        memset(_name, 0, 10);
     250        strcpy(_name, tmp._name);
     251        _realWidth = tmp._realWidth;
     252        _size = tmp._size;
    247253
    248         animDataTable[i].width = width;
    249         animDataTable[i].var1 = width >> 3;
    250         animDataTable[i].bpp = 4;
    251         animDataTable[i].height = height;
     254        return *this;
     255}
    252256
    253         animDataTable[i].fileIdx = -1;
    254         animDataTable[i].frameIdx = -1;
     257byte AnimData::getColor(int x, int y) {
     258        assert(_data);
     259        assert(x >= 0 && x < _realWidth && y >= 0 && y <= _height);
     260        assert(x + y * _realWidth < _size);
    255261
    256         animDataCount++;
    257 
    258         return i;
     262        return _data[x + y * _realWidth];
    259263}
    260264
    261 int16 reserveFrame(uint16 width, uint16 height, uint16 type, int16 idx) {
    262         uint16 i;
    263         uint32 frameSize;
     265/*! \brief Load and decode image frame
     266 * \param d Encoded image data
     267 * \param type Encoding type
     268 * \param w Image width
     269 * \param h Image height
     270 * \param file Data file index in bundle
     271 * \param frame Image frame index
     272 * \param n Part name
     273 * \param transparent Transparent color (for ANIM_MASKSPRITE)
     274 */
     275void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
     276        int16 frame, const char *n, byte transparent) {
    264277
    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                 }
     278        assert(d);
    272279
    273                 if (i == NUM_MAX_ANIMDATA)
    274                         return -1;
     280        if (_data) {
     281                clear();
    275282        }
    276283
    277         frameSize = width * height;
     284        _width = w * 2;
     285        _height = h;
     286        _var1 = _width >> 3;
     287        _data = NULL;
     288        _mask = NULL;
     289        _fileIdx = file;
     290        _frameIdx = frame;
     291        memset(_name, 0, 10);
     292        strcpy(_name, n);
     293        _realWidth = w;
    278294
    279         if (type == 4) {                // 256 color sprites
    280                 frameSize *= 2;
    281                 type = 8;
    282                 width *= 2;
    283         }
     295        switch (type) {
     296        case ANIM_RAW:
     297                _width = w;
     298                _var1 = w >> 3;
     299                _bpp = 4;
     300                _size = w * h;
     301                _data = new byte[_size];
     302                assert(_data);
     303                memcpy(_data, d, _size*sizeof(byte));
     304                break;
    284305
    285         if (type == 5) {
    286                 frameSize += 16;
    287         }
     306        case ANIM_MASK:
     307                _bpp = 1;
     308                _size = w * h * 8;
     309                _data = new byte[_size];
     310                _realWidth = w * 8;
     311                assert(_data);
     312                convertMask(_data, d, w, h);
     313                break;
    288314
    289         frameSize *= 2;
     315        case ANIM_SPRITE:
     316                _bpp = 4;
     317                _size = w * h * 2;
     318                _data = new byte[_size];
     319                _realWidth = w * 2;
     320                assert(_data);
     321                gfxConvertSpriteToRaw(_data, d, w, h);
     322                break;
    290323
    291         animDataTable[i].ptr1 = (byte *)malloc(frameSize);
     324        case ANIM_MASKSPRITE:
     325                _bpp = 4;
     326                _size = w * h * 2;
     327                _data = new byte[_size];
     328                _mask = new byte[_size];
     329                _realWidth = w * 2;
     330                assert(_data && _mask);
     331                gfxConvertSpriteToRaw(_data, d, w, h);
     332                generateMask(_data, _mask, _size, transparent);
     333                break;
    292334
    293         assert(animDataTable[i].ptr1);
     335        case ANIM_PALSPRITE:
     336                _bpp = 5;
     337                _size = w * h * 2;
     338                _data = new byte[_size];
     339                _realWidth = w * 2;
     340                assert(_data);
     341                convert8BBP(_data, d, w, h);
     342                break;
    294343
    295         animDataTable[i].width = width;
     344        case ANIM_FULLSPRITE:
     345                _bpp = 8;
     346                _var1 = _width >> 4;
     347                _size = w * h;
     348                _data = new byte[_size];
     349                assert(_data);
     350                convert8BBP2(_data, d, w, h);
     351                break;
    296352
    297         if (type == 5) {
    298                 animDataTable[i].var1 = width / 8;
    299         } else {
    300                 animDataTable[i].var1 = width / 16;
     353        default:
     354                error("AnimData::load: unknown image type");
    301355        }
     356}
    302357
    303         animDataTable[i].bpp = type;
     358/*! \brief Reset image
     359 */
     360void AnimData::clear() {
     361        delete[] _data;
     362        delete [] _mask;
    304363
    305         animDataTable[i].height = height;
     364        _width = 0;
     365        _height = 0;
     366        _bpp = 0;
     367        _var1 = 0;
     368        _data = NULL;
     369        _mask = NULL;
     370        _fileIdx = -1;
     371        _frameIdx = -1;
     372        memset(_name, 0, 10);
     373        _size = 0;
     374}
    306375
    307         animDataTable[i].fileIdx = -1;
    308         animDataTable[i].frameIdx = -1;
     376/*! \brief Write image identifiers to savefile
     377 * \param fHandle Savefile open for writing
     378 */
     379void AnimData::save(Common::OutSaveFile &fHandle) const {
     380        fHandle.writeUint16BE(_width);
     381        fHandle.writeUint16BE(_var1);
     382        fHandle.writeUint16BE(_bpp);
     383        fHandle.writeUint16BE(_height);
     384        // Just because I write pointers to a file doesn't mean
     385        // anyone should actually read those values back!
     386        fHandle.writeUint32BE((uint32)_data);
     387        fHandle.writeUint32BE((uint32)_mask);
     388        fHandle.writeUint16BE(_fileIdx);
     389        fHandle.writeUint16BE(_frameIdx);
     390        fHandle.write(_name, 10);
     391}
    309392
    310         animDataCount++;
     393/*! \brief Clear part of animDataTable
     394 * \param startIdx First image frame to be cleared
     395 * \param numIdx Number of image frames to be cleared
     396 */
     397void freeAnimDataRange(byte startIdx, byte numIdx) {
     398        for (byte i = 0; i < numIdx; i++) {
     399                animDataTable[startIdx + i].clear();
     400        }
     401}
    311402
    312         return i;
     403/*! \brief Clear whole animDataTable
     404 */
     405void freeAnimDataTable() {
     406        freeAnimDataRange(0, NUM_MAX_ANIMDATA);
    313407}
    314408
    315 void generateMask(byte * sprite, byte * mask, uint16 size, byte transparency) {
     409/*! \brief Find transparent color index for image
     410 * \brief animName Image file name
     411 */
     412static byte getAnimTransparentColor(const char *animName) {
     413        char name[15];
     414
     415        removeExtention(name, animName);
     416
     417        for (int i = 0; i < ARRAYSIZE(transparencyData); i++) {
     418                if (!strcmp(name, transparencyData[i].name)) {
     419                        return transparencyData[i].color;
     420                }
     421        }
     422        return 0;
     423}
     424
     425/*! \brief Generate mask for image
     426 * \param[in] sprite Image data
     427 * \param[out] mask Image mask
     428 * \param size Image data length
     429 * \param transparency Transparent color index
     430 */
     431void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency) {
    316432        for (uint16 i = 0; i < size; i++) {
    317433                if (*(sprite++) != transparency) {
    318434                        *(mask++) = 0;
     
    322438        }
    323439}
    324440
    325 void convertMask(byte * dest, byte * source, int16 width, int16 height) {
     441/*! \brief Decode 1bpp mask
     442 * \param[out] dest Decoded mask
     443 * \param[in] source Encoded mask
     444 * \param width Mask width
     445 * \param height Mask height
     446 */
     447void convertMask(byte *dest, const byte *source, int16 width, int16 height) {
    326448        int16 i, j;
    327449        byte maskEntry;
    328450
     
    335457        }
    336458}
    337459
    338 void convert4BBP(byte * dest, byte * source, int16 width, int16 height) {
     460/*! \brief Decode 4bpp sprite
     461 * \param[out] dest Decoded image
     462 * \param[in] source Encoded image
     463 * \param width Image width
     464 * \param height Image height
     465 */
     466void convert4BBP(byte *dest, const byte *source, int16 width, int16 height) {
    339467        byte maskEntry;
    340468
    341469        for (int16 i = 0; i < width * height; i++) {
     
    345473        }
    346474}
    347475
    348 void loadAnimHeader(Common::MemoryReadStream readS) {
     476/*! \brief Read image header
     477 * \param[out] animHeader Image header reference
     478 * \param readS Input stream open for reading
     479 */
     480void loadAnimHeader(AnimHeaderStruct &animHeader, Common::MemoryReadStream readS) {
    349481        animHeader.field_0 = readS.readByte();
    350482        animHeader.field_1 = readS.readByte();
    351483        animHeader.field_2 = readS.readByte();
     
    366498        animHeader.field_14 = readS.readUint16BE();
    367499}
    368500
     501/*! \brief Find next empty space animDataTable
     502 * \param start First index to check
     503 */
     504int emptyAnimSpace(int start = 0) {
     505        for (; start < NUM_MAX_ANIMDATA; start++) {
     506                if (!animDataTable[start].data()) {
     507                        return start;
     508                }
     509        }
     510
     511        return -1;
     512}
     513
     514/*! \brief Load SPL data into animDataTable
     515 * \param resourceName SPL filename
     516 * \param idx Target index in animDataTable
     517 */
    369518void loadSpl(const char *resourceName, int16 idx) {
    370519        int16 foundFileIdx = findFileInBundle(resourceName);
    371         int16 entry;
     520        int entry;
     521
     522        if (foundFileIdx < 0) {
     523                return;
     524        }
     525
    372526        byte *dataPtr = readBundleFile(foundFileIdx);
    373527
    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);
     528        entry = idx < 0 ? emptyAnimSpace() : idx;
     529        assert(entry >= 0);
     530        animDataTable[entry].load(dataPtr, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
    381531
    382                 animDataTable[entry].fileIdx = foundFileIdx;
    383                 animDataTable[entry].frameIdx = 0;
    384                 strcpy(animDataTable[entry].name, currentPartName);
    385         }
    386 
    387532        free(dataPtr);
    388533}
    389534
     535/*! \brief Load 1bpp mask
     536 * \param resourceName Mask filename
     537 */
    390538void loadMsk(const char *resourceName) {
    391539        int16 foundFileIdx = findFileInBundle(resourceName);
    392         int16 entry;
     540        int entry = 0;
    393541        byte *dataPtr = readBundleFile(foundFileIdx);
    394542        byte *ptr;
     543        AnimHeaderStruct animHeader;
    395544
    396545        Common::MemoryReadStream readS(dataPtr, 0x16);
    397         loadAnimHeader(readS);
     546        loadAnimHeader(animHeader, readS);
    398547        ptr = dataPtr + 0x16;
    399548
    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);
     549        for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
     550                entry = emptyAnimSpace(entry);
     551                assert(entry >= 0);
     552                animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
    406553                ptr += animHeader.frameWidth * animHeader.frameHeight;
    407 
    408                 animDataTable[entry].fileIdx = foundFileIdx;
    409                 animDataTable[entry].frameIdx = i;
    410                 strcpy(animDataTable[entry].name, currentPartName);
    411554        }
    412555
    413556        free(dataPtr);
    414557}
    415558
     559/*! \brief Load animation
     560 * \param resourceName Animation filename
     561 */
    416562void loadAni(const char *resourceName) {
    417563        int16 foundFileIdx = findFileInBundle(resourceName);
    418         int16 entry;
     564        int entry = 0;
    419565        byte *dataPtr = readBundleFile(foundFileIdx);
    420         byte *ptr, *animPtr;
     566        byte *ptr;
    421567        byte transparentColor;
    422         uint32 fullSize;
     568        AnimHeaderStruct animHeader;
    423569
    424570        Common::MemoryReadStream readS(dataPtr, 0x16);
    425         loadAnimHeader(readS);
     571        loadAnimHeader(animHeader, readS);
    426572        ptr = dataPtr + 0x16;
    427573
    428574        transparentColor = getAnimTransparentColor(resourceName);
    429575
    430         fullSize = animHeader.frameWidth * animHeader.frameHeight;
     576        for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
     577                entry = emptyAnimSpace(entry);
     578                assert(entry >= 0);
    431579
    432         for (int16 i = 0; i < animHeader.numFrames; i++) {
    433                 entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, 0);
    434 
    435                 assert(entry != -1);
    436 
    437580                // special case transparency handling
    438581                if (!strcmp(resourceName, "L2202.ANI")) {
    439                         if (i < 2) {
    440                                 transparentColor = 0;
    441                         } else {
    442                                 transparentColor = 7;
    443                         }
     582                        transparentColor = i < 2 ? 0 : 7;
     583                } else if (!strcmp(resourceName, "L4601.ANI")) {
     584                        transparentColor = i < 1 ? 0xE : 0;
    444585                }
    445586
    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);
     587                animDataTable[entry].load(ptr, ANIM_MASKSPRITE, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName, transparentColor);
     588                ptr += animHeader.frameWidth * animHeader.frameHeight;
    468589        }
    469590
    470591        free(dataPtr);
    471592}
    472593
    473 void convert8BBP(byte * dest, byte * source, int16 width, int16 height) {
    474         byte table[16];
     594/*! \brief Decode 16 color image with palette
     595 * \param[out] dest Decoded image
     596 * \param[in] source Encoded image
     597 * \param width Image width
     598 * \param height Image height
     599 */
     600void convert8BBP(byte *dest, const byte *source, int16 width, int16 height) {
     601        const byte *table = source;
    475602        byte color;
    476603
    477         memcpy(table, source, 16);
    478604        source += 16;
    479605
    480606        for (uint16 i = 0; i < width * height; i++) {
     
    485611        }
    486612}
    487613
    488 void convert8BBP2(byte * dest, byte * source, int16 width, int16 height) {
    489         uint16 i, j, k, m;
     614/*! \brief Decode 8bit image
     615 * \param[out] dest Decoded image
     616 * \param[in] source Encoded image
     617 * \param width Image width
     618 * \param height Image height
     619 * \attention Data in source are destroyed during decoding
     620 */
     621void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
     622        uint16 i, j;
     623        int k, m;
    490624        byte color;
    491625
    492626        for (j = 0; j < (width * height) / 16; j++) {
    493627                // m = 0: even bits, m = 1: odd bits
    494                 for (m = 0; m < 2; m++) {
     628                for (m = 0; m <= 1; m++) {
    495629                        for (i = 0; i < 8; i++) {
    496630                                color = 0;
    497                                 for (k = 14 + m; k >= 0 + m; k = k - 2) {
     631                                for (k = 14 + m; k >= 0; k -= 2) {
    498632                                        color |= ((*(source + k) & 0x080) >> 7);
    499633                                        *(source + k) <<= 1;
    500634                                        if (k > 0 + m)
     
    508642        }       // end j
    509643}
    510644
     645/*! \brief Load image set
     646 * \param resourceName Image set filename
     647 * \param idx Target index in animDataTable
     648 */
    511649void loadSet(const char *resourceName, int16 idx) {
    512650        AnimHeader2Struct header2;
    513         uint32 fullSize;
    514651        uint16 numSpriteInAnim;
    515652        int16 foundFileIdx = findFileInBundle(resourceName);
    516         int16 entry, typeParam;
     653        int16 entry = idx >= 0 ? idx : 0;
    517654        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 };
     655        int type;
    519656
    520657        origDataPtr = dataPtr = readBundleFile(foundFileIdx);
    521658        assert(!memcmp(dataPtr, "SET", 3));
     
    526663
    527664        startOfDataPtr = ptr + numSpriteInAnim * 0x10;
    528665
    529         for (int16 i = 0; i < numSpriteInAnim; i++) {
    530                 typeParam = 0;
    531 
     666        for (int16 i = 0; i < numSpriteInAnim; i++, entry++) {
    532667                Common::MemoryReadStream readS(ptr, 0x10);
    533668
    534669                header2.field_0 = readS.readUint32BE();
     
    541676
    542677                ptr += 0x10;
    543678
    544                 fullSize = header2.width * header2.height;
     679                entry = idx < 0 ? emptyAnimSpace(entry) : idx + i;
     680                assert(entry >= 0);
    545681
    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 
    562682                dataPtr = startOfDataPtr + header2.field_0;
    563683
    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);
     684                if (header2.type == 1) {
     685                        type = ANIM_MASK;
     686                } else if (header2.type == 4) {
     687                        type = ANIM_SPRITE;
     688                } else if (header2.type == 5) {
     689                        type = ANIM_PALSPRITE;
    568690                } 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                         }
     691                        type = ANIM_FULLSPRITE;
    578692                }
    579693
    580                 animDataTable[entry].fileIdx = foundFileIdx;
    581                 animDataTable[entry].frameIdx = i;
    582                 strcpy(animDataTable[entry].name, currentPartName);
     694                animDataTable[entry].load(dataPtr, type, header2.width, header2.height, foundFileIdx, i, currentPartName);
    583695        }
    584696
    585697        free(origDataPtr);
    586698}
    587699
     700/*! \brief Load SEQ data into animDataTable
     701 * \param resourceName SEQ data filename
     702 * \param idx Target index in animDataTable
     703 */
    588704void loadSeq(const char *resourceName, int16 idx) {
    589705        int16 foundFileIdx = findFileInBundle(resourceName);
    590706        byte *dataPtr = readBundleFile(foundFileIdx);
    591         int16 entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
     707        int entry = idx < 0 ? emptyAnimSpace() : idx;
    592708
    593         memcpy(animDataTable[entry].ptr1, dataPtr + 0x16, (uint16) partBuffer[foundFileIdx].unpackedSize - 0x16);
     709        animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
    594710        free(dataPtr);
    595711}
    596712
     
    624740        error("loadResource: Cannot determine type for '%s'", resourceName);
    625741}
    626742
     743/*! \todo There seems to be some additional resource file that is not loaded
     744 */
    627745void loadAbs(const char *resourceName, uint16 idx) {
    628746        /* byte isMask = 0; */
    629747        /* byte isSpl = 0; */
     
    632750                loadSet(resourceName, idx);
    633751                return;
    634752        } else if (strstr(resourceName, ".H32")) {
     753                warning("Ignoring file %s (load at %d)", resourceName, idx);
    635754                return;
    636755        } else if (strstr(resourceName, ".SEQ")) {
    637756                loadSeq(resourceName, idx);
     
    640759                loadSpl(resourceName, idx);
    641760                return;
    642761        } else if (strstr(resourceName, ".AMI")) {
     762                warning("Ignoring file %s (load at %d)", resourceName, idx);
    643763                return;
    644764        } else if (strstr(resourceName, ".ANI")) {
     765                warning("Ignoring file %s (load at %d)", resourceName, idx);
    645766                return;
    646767        }
    647768
    648769        error("loadAbs: Cannot determine type for '%s'", resourceName);
    649770}
    650771
    651 void loadResourcesFromSave() {
    652         int16 currentAnim, foundFileIdx, fullSize, entry, i;
     772/*! \brief Load animDataTable from save
     773 * \param fHandle Savefile open for reading
     774 * \param broken Broken/correct file format switch
     775 * \todo Add Operation Stealth savefile support
     776 *
     777 * Unlike the old code, this one actually rebuilds the table one frame
     778 * at a time.
     779 */
     780void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
     781        int16 currentAnim, foundFileIdx;
    653782        int8 isMask = 0, isSpl = 0;
    654         byte *dataPtr, *ptr, *animPtr;
    655         char animName[256], part[256];
     783        byte *dataPtr, *ptr;
     784        char *animName, part[256];
    656785        byte transparentColor;
    657786        AnimData *currentPtr;
     787        AnimHeaderStruct animHeader;
    658788
     789        uint16 width, height, bpp, var1;
     790        int16  frame;
     791        char name[10];
     792        int type;
     793
    659794        strcpy(part, currentPartName);
    660795
    661796        for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim++) {
    662797                currentPtr = &animDataTable[currentAnim];
    663                 if (currentPtr->refresh && currentPtr->fileIdx != -1) {
    664                         if (strcmp(currentPartName, currentPtr->name)) {
    665                                 closePart();
    666                                 loadPart(currentPtr->name);
    667                         }
    668798
    669                         foundFileIdx = currentPtr->fileIdx;
     799                width = fHandle.readUint16BE();
     800                var1 = fHandle.readUint16BE();
     801                bpp = fHandle.readUint16BE();
     802                height = fHandle.readUint16BE();
    670803
    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;
     804                if (!broken) {
     805                        if (!fHandle.readUint32BE()) {
     806                                fHandle.skip(18);
     807                                continue;
    688808                        }
     809                        fHandle.readUint32BE();
     810                }
    689811
    690                         {
    691                                 fullSize = animHeader.frameWidth * animHeader.frameHeight;
     812                foundFileIdx = fHandle.readSint16BE();
     813                frame = fHandle.readSint16BE();
     814                fHandle.read(name, 10);
    692815
    693                                 loadRelatedPalette(animName);
     816                if (foundFileIdx < 0 || (broken && !fHandle.readByte())) {
     817                        continue;
     818                }
    694819
    695                                 transparentColor = getAnimTransparentColor(animName);
     820                if (strcmp(currentPartName, name)) {
     821                        closePart();
     822                        loadPart(name);
     823                }
    696824
    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                                         }
     825                animName = partBuffer[foundFileIdx].partName;
     826                ptr = dataPtr = readBundleFile(foundFileIdx);
    706827
    707                                         if (!strcmp(animName, "L4601.ANI")) {
    708                                                 if (i < 1) {
    709                                                         transparentColor = 0xE;
    710                                                 } else {
    711                                                         transparentColor = 0;
    712                                                 }
    713                                         }
     828                isSpl  = (strstr(animName, ".SPL")) ? 1 : 0;
     829                isMask = (strstr(animName, ".MSK")) ? 1 : 0;
    714830
    715                                         currentPtr[i].ptr1 = NULL;
    716                                         entry = allocFrame(animHeader.frameWidth * 2, animHeader.frameHeight, isMask);
     831                if (isSpl) {
     832                        width = (uint16) partBuffer[foundFileIdx].unpackedSize;
     833                        height = 1;
     834                        frame = 0;
     835                        type = ANIM_RAW;
     836                } else {
     837                        Common::MemoryReadStream readS(ptr, 0x16);
     838                        loadAnimHeader(animHeader, readS);
     839                        ptr += 0x16;
    717840
    718                                         currentPtr->fileIdx = foundFileIdx;
     841                        width = animHeader.frameWidth;
     842                        height = animHeader.frameHeight;
    719843
    720                                         assert(entry != -1);
     844                        if (isMask) {
     845                                type = ANIM_MASK;
     846                        } else {
     847                                type = ANIM_MASKSPRITE;
    721848
    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;
     849                                loadRelatedPalette(animName);
     850                                transparentColor = getAnimTransparentColor(animName);
    730851
    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);
     852                                // special case transparency handling
     853                                if (!strcmp(animName, "L2202.ANI")) {
     854                                        transparentColor = (frame < 2) ? 0 : 7;
     855                                } else if (!strcmp(animName, "L4601.ANI")) {
     856                                        transparentColor = (frame < 1) ? 0xE : 0;
    748857                                }
    749858                        }
     859                }
    750860
    751                         free(dataPtr);
    752                 }
     861                ptr += frame * width * height;
     862                currentPtr->load(ptr, type, width, height, foundFileIdx, frame, name, transparentColor);
     863                free(dataPtr);
    753864        }
    754865
    755866        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) {
    238184        overlayHeadElement *currentHead = overlayHead.previous;
    239185
    240186        int16 objX, objY, frame, part, threshold, height, xdif, ydif;
     187        int width;
    241188
    242189        while (currentHead) {
    243190                if (currentHead->type < 2) {
     
    250197                                part = objectTable[currentHead->objIdx].part;
    251198
    252199                                if (currentHead->type == 0) {
    253                                         threshold = animDataTable[frame].var1;
     200                                        threshold = animDataTable[frame]._var1;
    254201                                } else {
    255                                         threshold = animDataTable[frame].width / 2;
     202                                        threshold = animDataTable[frame]._width / 2;
    256203                                }
    257204
    258                                 height = animDataTable[frame].height;
     205                                height = animDataTable[frame]._height;
     206                                width = animDataTable[frame]._realWidth;
    259207
    260208                                xdif = x - objX;
    261209                                ydif = y - objY;
    262210
    263211                                if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) {
    264                                         if (animDataTable[frame].ptr1) {
    265                                                 if (g_cine->getGameType() == Cine::GType_OS)
    266                                                         return currentHead->objIdx;
    267 
    268                                                 if (currentHead->type == 0)     { // use generated mask
    269                                                         if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr2, animDataTable[frame].width)) {
     212                                        if (animDataTable[frame].data()) {
     213                                                if (g_cine->getGameType() == Cine::GType_OS) {
     214                                                        if(xdif < width && (currentHead->type == 1 || animDataTable[frame].getColor(xdif, ydif) != objectTable[currentHead->objIdx].part)) {
    270215                                                                return currentHead->objIdx;
    271216                                                        }
     217                                                } else if (currentHead->type == 0)      { // use generated mask
     218                                                        if (gfxGetBit(x - objX, y - objY, animDataTable[frame].mask(), animDataTable[frame]._width)) {
     219                                                                return currentHead->objIdx;
     220                                                        }
    272221                                                } else if (currentHead->type == 1) { // is mask
    273                                                         if (gfxGetBit(x - objX, y - objY, animDataTable[frame].ptr1, animDataTable[frame].width * 4)) {
     222                                                        if (gfxGetBit(x - objX, y - objY, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
    274223                                                                return currentHead->objIdx;
    275224                                                        }
    276225                                                }
     
    302251        return true;
    303252}
    304253
     254/*! \brief Restore script list item from savefile
     255 * \param fHandle Savefile handlem open for reading
     256 * \param isGlobal Restore object or global script?
     257 */
    305258void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) {
    306         int16 i;
     259        ScriptVars localVars, labels;
     260        uint16 compare, pos;
     261        int16 idx;
    307262
    308         prcLinkedListStruct *newElement;
    309         prcLinkedListStruct *currentHead = &globalScriptsHead;
    310         prcLinkedListStruct *tempHead = currentHead;
     263        labels.load(*fHandle);
     264        localVars.load(*fHandle);
    311265
    312         currentHead = tempHead->next;
     266        compare = fHandle->readUint16BE();
     267        pos = fHandle->readUint16BE();
     268        idx = fHandle->readUint16BE();
    313269
    314         while (currentHead) {
    315                 tempHead = currentHead;
    316                 currentHead = tempHead->next;
     270        // no way to reinitialize these
     271        if (idx < 0) {
     272                return;
    317273        }
    318274
    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;
     275        // original code loaded everything into globalScripts, this should be
     276        // the correct behavior
     277        if (isGlobal) {
     278                ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx, labels, localVars, compare, pos));
     279                assert(tmp);
     280                globalScripts.push_back(tmp);
     281        } else {
     282                ScriptPtr tmp(scriptInfo->create(*relTable[idx], idx, labels, localVars, compare, pos));
     283                assert(tmp);
     284                objectScripts.push_back(tmp);
     285        }
    337286}
    338287
    339288void loadOverlayFromSave(Common::InSaveFile *fHandle) {
     
    370319        currentHead->previous = newElement;
    371320}
    372321
    373 void setupScriptList(bool isGlobal) {
    374         prcLinkedListStruct *currentHead;
     322/*! \brief Savefile format tester
     323 * \param fHandle Savefile to check
     324 *
     325 * This function seeks through savefile and tries to guess if it's the original
     326 * savegame format or broken format from ScummVM 0.10/0.11
     327 * The test is incomplete but this should cover 99.99% of cases.
     328 * If anyone makes a savefile which could confuse this test, assert will
     329 * report it
     330 */
     331bool brokenSave(Common::InSaveFile &fHandle) {
     332        // Backward seeking not supported in compressed savefiles
     333        // if you really want it, finish it yourself
     334        return false;
    375335
    376         if (isGlobal)
    377                 currentHead = globalScriptsHead.next;
    378         else
    379                 currentHead = objScriptList.next;
     336        // fixed size part: 14093 bytes (12308 bytes in broken save)
     337        // animDataTable begins at byte 6431
    380338
    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;
     339        int filesize = fHandle.size();
     340        int startpos = fHandle.pos();
     341        int pos, tmp;
     342        bool correct = false, broken = false;
     343
     344        // check for correct format
     345        while (filesize > 14093) {
     346                pos = 14093;
     347
     348                fHandle.seek(pos);
     349                tmp = fHandle.readUint16BE();
     350                pos += 2 + tmp * 206;
     351                if (pos >= filesize) break;
     352
     353                fHandle.seek(pos);
     354                tmp = fHandle.readUint16BE();
     355                pos += 2 + tmp * 206;
     356                if (pos >= filesize) break;
     357
     358                fHandle.seek(pos);
     359                tmp = fHandle.readUint16BE();
     360                pos += 2 + tmp * 20;
     361                if (pos >= filesize) break;
     362
     363                fHandle.seek(pos);
     364                tmp = fHandle.readUint16BE();
     365                pos += 2 + tmp * 20;
     366
     367                if (pos == filesize) correct = true;
     368                break;
    387369        }
     370        debug(5, "brokenSave: correct format check %s: size=%d, pos=%d",
     371                correct ? "passed" : "failed", filesize, pos);
     372
     373        // check for broken format
     374        while (filesize > 12308) {
     375                pos = 12308;
     376
     377                fHandle.seek(pos);
     378                tmp = fHandle.readUint16BE();
     379                pos += 2 + tmp * 206;
     380                if (pos >= filesize) break;
     381
     382                fHandle.seek(pos);
     383                tmp = fHandle.readUint16BE();
     384                pos += 2 + tmp * 206;
     385                if (pos >= filesize) break;
     386
     387                fHandle.seek(pos);
     388                tmp = fHandle.readUint16BE();
     389                pos += 2 + tmp * 20;
     390                if (pos >= filesize) break;
     391
     392                fHandle.seek(pos);
     393                tmp = fHandle.readUint16BE();
     394                pos += 2 + tmp * 20;
     395
     396                if (pos == filesize) broken = true;
     397                break;
     398        }
     399        debug(5, "brokenSave: broken format check %s: size=%d, pos=%d",
     400                broken ? "passed" : "failed", filesize, pos);
     401
     402        // there's a very small chance that both cases will match
     403        // if anyone runs into it, you'll have to walk through
     404        // the animDataTable and try to open part file for each entry
     405        if (!correct && !broken) {
     406                error("brokenSave: file format check failed");
     407        } else if (correct && broken) {
     408                error("brokenSave: both file formats seem to apply");
     409        }
     410
     411        fHandle.seek(startpos);
     412        debug(5, "brokenSave: detected %s file format",
     413                correct ? "correct" : "broken");
     414
     415        return broken;
    388416}
    389417
    390418bool CineEngine::makeLoad(char *saveName) {
    391419        int16 i;
    392420        int16 size;
     421        bool broken;
    393422        Common::InSaveFile *fHandle;
    394423
    395424        fHandle = g_saveFileMan->openForLoading(saveName);
     
    408437        // if (g_cine->getGameType() == Cine::GType_OS) {
    409438        //      freeUnkList();
    410439        // }
    411         freePrcLinkedList();
    412         releaseObjectScripts();
    413         freeBgIncrustList();
     440        bgIncrustList.clear();
    414441        closePart();
    415442
    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         }
     443        objectScripts.clear();
     444        globalScripts.clear();
     445        relTable.clear();
     446        scriptTable.clear();
    426447
    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 
    435448        for (i = 0; i < NUM_MAX_MESSAGE; i++) {
    436449                messageTable[i].len = 0;
    437450
     
    478491
    479492        checkForPendingDataLoadSwitch = 0;
    480493
     494        broken = brokenSave(*fHandle);
     495
    481496        currentDisk = fHandle->readUint16BE();
    482497
    483498        fHandle->read(currentPartName, 13);
     
    491506        fHandle->read(currentBgName[0], 13);
    492507        fHandle->read(currentCtName, 13);
    493508
     509        checkDataDisk(currentDisk);
     510
     511        if (strlen(currentPartName)) {
     512                loadPart(currentPartName);
     513        }
     514
     515        if (strlen(currentPrcName)) {
     516                loadPrc(currentPrcName);
     517        }
     518
     519        if (strlen(currentRelName)) {
     520                loadRel(currentRelName);
     521        }
     522
     523        if (strlen(currentBgName[0])) {
     524                loadBg(currentBgName[0]);
     525        }
     526
     527        if (strlen(currentCtName)) {
     528                loadCt(currentCtName);
     529        }
     530
    494531        fHandle->readUint16BE();
    495532        fHandle->readUint16BE();
    496533
     
    540577        fHandle->readUint16BE();
    541578        fHandle->readUint16BE();
    542579
    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         }
     580        loadResourcesFromSave(*fHandle, broken);
    555581
    556582        // TODO: handle screen params (really required ?)
    557583        fHandle->readUint16BE();
     
    576602                loadOverlayFromSave(fHandle);
    577603        }
    578604
    579         size = fHandle->readSint16BE();
    580         for (i = 0; i < size; i++) {
    581                 loadBgIncrustFromSave(fHandle);
    582         }
     605        loadBgIncrustFromSave(*fHandle);
    583606
    584607        delete fHandle;
    585608
    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 
    602609        if (strlen(currentMsgName)) {
    603610                loadMsg(currentMsgName);
    604611        }
    605612
    606         if (strlen(currentBgName[0])) {
    607                 loadBg(currentBgName[0]);
    608         }
    609 
    610         if (strlen(currentCtName)) {
    611                 loadCt(currentCtName);
    612         }
    613 
    614         loadResourcesFromSave();
    615         reincrustAllBg();
    616 
    617613        setMouseCursor(MOUSE_CURSOR_NORMAL);
    618614
    619615        if (strlen(currentDatName)) {
     
    702698        fHandle->writeUint16BE(0x1E);
    703699
    704700        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);
     701                animDataTable[i].save(*fHandle);
    720702        }
    721703
    722704        fHandle->writeUint16BE(0);  // Screen params, unhandled
     
    727709        fHandle->writeUint16BE(0);
    728710
    729711        {
    730                 int16 numScript = 0;
    731                 prcLinkedListStruct *currentHead = globalScriptsHead.next;
    732 
    733                 while (currentHead) {
    734                         numScript++;
    735                         currentHead = currentHead->next;
     712                ScriptList::iterator it;
     713                fHandle->writeUint16BE(globalScripts.size());
     714                for (it = globalScripts.begin(); it != globalScripts.end(); ++it) {
     715                        (*it)->save(*fHandle);
    736716                }
    737717
    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;
     718                fHandle->writeUint16BE(objectScripts.size());
     719                for (it = objectScripts.begin(); it != objectScripts.end(); ++it) {
     720                        (*it)->save(*fHandle);
    755721                }
    756722        }
    757723
    758724        {
    759725                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;
    789726                overlayHeadElement *currentHead = overlayHead.next;
    790727
    791728                while (currentHead) {
     
    812749                }
    813750        }
    814751
     752        Common::List<BGIncrust>::iterator it;
     753        fHandle->writeUint16BE(bgIncrustList.size());
     754
     755        for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) {
     756                fHandle->writeUint32BE(0); // next
     757                fHandle->writeUint32BE(0); // unkPtr
     758                fHandle->writeUint16BE(it->objIdx);
     759                fHandle->writeUint16BE(it->param);
     760                fHandle->writeUint16BE(it->x);
     761                fHandle->writeUint16BE(it->y);
     762                fHandle->writeUint16BE(it->frame);
     763                fHandle->writeUint16BE(it->part);
     764        }
     765/*
    815766        int numBgIncrustList = 0;
    816767        BGIncrustList *bgIncrustPtr = bgIncrustList;
    817768
     
    834785
    835786                bgIncrustPtr = bgIncrustPtr->next;
    836787        }
     788*/
    837789
    838790        delete fHandle;
    839791
     
    985937
    986938                if (characterWidth) {
    987939                        byte characterIdx = fontParamTable[character].characterIdx;
    988                         drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
     940                        if (g_cine->getGameType() == Cine::GType_OS) {
     941                                drawSpriteRaw2(textTable[characterIdx][0], 0, 2, 8, page1Raw, x, y);
     942                        } else {
     943                                drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, x, y);
     944                        }
    989945                        x += characterWidth + 1;
    990946                }
    991947        }
     
    17261682        return var_5E;
    17271683}
    17281684
    1729 void drawSprite(overlayHeadElement *currentOverlay, byte *spritePtr,
    1730                                 byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
     1685void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr,
     1686                                const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    17311687        byte *ptr = NULL;
    17321688        byte *msk = NULL;
    17331689        byte i = 0;
     
    17541710
    17551711                        maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;
    17561712
    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++);
     1713                        maskWidth = animDataTable[maskSpriteIdx]._width / 2;
     1714                        maskHeight = animDataTable[maskSpriteIdx]._height;
     1715                        gfxUpdateSpriteMask(spritePtr, maskPtr, width, height, animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, ptr, msk, x, y, maskX, maskY, i++);
    17601716#ifdef DEBUG_SPRITE_MASK
    1761                         gfxFillSprite(animDataTable[maskSpriteIdx].ptr1, maskWidth, maskHeight, page, maskX, maskY, 1);
     1717                        gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
    17621718#endif
    17631719                }
    17641720
     
    17901746                                if (i > 200) {
    17911747                                        memcpy(page1Raw + (i - additionalBgVScroll) * 320, scrollBg + (i - 200) * 320, 320);
    17921748                                } else {
    1793                                         memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i) * 320, 320);
     1749                                        memcpy(page1Raw + (i - additionalBgVScroll) * 320, bgPage + (i-1) * 320, 320);
    17941750                                }
    17951751                        }
    17961752                }
     
    18051761        uint16 lineResult, fullLineWidth;
    18061762        uint16 interWordSize, interWordSizeRemain;
    18071763        const char *endOfMessagePtr;
    1808         byte currentChar, characterWidth;
     1764        byte currentChar; //, characterWidth;
    18091765
    18101766        gfxDrawPlainBoxRaw(x, y, x + width, y + 4, color, page1Raw);
    18111767
     
    18541810                                if (interWordSizeRemain)
    18551811                                        interWordSizeRemain = 0;
    18561812                        } else {
    1857                                 characterWidth = fontParamTable[currentChar].characterWidth;
    1858 
    1859                                 if (characterWidth) {
    1860                                         byte characterIdx = fontParamTable[currentChar].characterIdx;
    1861                                         drawSpriteRaw(textTable[characterIdx][0], textTable[characterIdx][1], 2, 8, page1Raw, localX, localY);
    1862                                         localX += characterWidth + 1;
    1863                                 }
     1813                                localX = drawChar(currentChar, localX, localY);
    18641814                        }
    18651815                } while ((messagePtr < endOfMessagePtr) && !endOfMessageReached);
    18661816
     
    19101860        freeOverlay(cmd, 3);
    19111861}
    19121862
     1863/*! \todo Fix Operation Stealth logo in intro (the green text after the plane
     1864 * takes off). Each letter should slowly grow top-down, it has something to
     1865 * do with object 10 (some mask or something)
     1866 */
    19131867void drawOverlays(void) {
    19141868        uint16 partVar1, partVar2;
    19151869        AnimData *pPart;
     
    19421896                                        if (g_cine->getGameType() == Cine::GType_OS) {
    19431897                                                pPart = &animDataTable[objPtr->frame];
    19441898
    1945                                                 partVar1 = pPart->var1;
    1946                                                 partVar2 = pPart->height;
     1899                                                partVar1 = pPart->_var1;
     1900                                                partVar2 = pPart->_height;
    19471901
    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);
     1902                                                if (pPart->data()) {
     1903                                                        // NOTE: is the mask supposed to be in data()? Shouldn't that be mask(), like below?
     1904                                                        // OS sprites don't use masks, see drawSprite() -- next_ghost
     1905                                                        drawSprite(currentOverlay, pPart->data(), pPart->data(), partVar1, partVar2, page1Raw, x, y);
    19511906                                                }
    19521907                                        } else {
    19531908                                                part = objPtr->part;
     
    19561911
    19571912                                                pPart = &animDataTable[objPtr->frame];
    19581913
    1959                                                 partVar1 = pPart->var1;
    1960                                                 partVar2 = pPart->height;
     1914                                                partVar1 = pPart->_var1;
     1915                                                partVar2 = pPart->_height;
    19611916
    1962                                                 if (pPart->ptr1) {
    1963                                                         drawSprite(currentOverlay, pPart->ptr1, pPart->ptr2, partVar1, partVar2, page1Raw, x, y);
     1917                                                if (pPart->data()) {
     1918                                                        drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y);
    19641919                                                }
    19651920                                        }
    19661921                                }
     
    20131968                                x = objPtr->x;
    20141969                                y = objPtr->y;
    20151970
     1971
    20161972                                if (objPtr->frame >= 0) {
    20171973                                        part = objPtr->part;
    20181974
     
    20201976
    20211977                                        pPart = &animDataTable[objPtr->frame];
    20221978
    2023                                         partVar1 = pPart->width / 2;
    2024                                         partVar2 = pPart->height;
     1979                                        partVar1 = pPart->_width / 2;
     1980                                        partVar2 = pPart->_height;
    20251981
    2026                                         if (pPart->ptr1) {
    2027                                                 gfxFillSprite(pPart->ptr1, partVar1, partVar2, page1Raw, x, y);
     1982                                        if (pPart->data()) {
     1983                                                gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y);
    20281984                                        }
    20291985                                }
    20301986                                break;
     
    20401996
    20411997                                var5 = currentOverlay->x;
    20421998
    2043                                 if (objPtr->frame >= 0) {
    2044                                         if (var5 <= 8) {
    2045                                                 if (additionalBgTable[var5]) {
    2046                                                         if (animDataTable[objPtr->frame].bpp == 1) {
    2047                                                                 int16 x2;
    2048                                                                 int16 y2;
     1999                                if (objPtr->frame >= 0 && var5 <= 8 && additionalBgTable[var5] && animDataTable[objPtr->frame]._bpp == 1) {
     2000                                        int16 x2;
     2001                                        int16 y2;
    20492002
    2050                                                                 x2 = animDataTable[objPtr->frame].width / 2;
    2051                                                                 y2 = animDataTable[objPtr->frame].height;
     2003                                        x2 = animDataTable[objPtr->frame]._width / 2;
     2004                                        y2 = animDataTable[objPtr->frame]._height;
    20522005
    2053                                                                 if (animDataTable[objPtr->frame].ptr1) {
    2054                                                                         // drawSpriteRaw(animDataTable[objPtr->frame].ptr1, animDataTable[objPtr->frame].ptr1, x2, y2,
    2055                                                                         //                              additionalBgTable[currentAdditionalBgIdx], x, y);
    2056                                                                 }
    2057                                                         }
    2058                                                 }
     2006                                        if (animDataTable[objPtr->frame].data()) {
     2007                                                maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), x2, y2, page1Raw, x, y);
    20592008                                        }
    20602009                                }
    20612010                                break;
     
    20752024
    20762025void checkForPendingDataLoad(void) {
    20772026        if (newPrcName[0] != 0) {
    2078                 freePrcLinkedList();
    2079                 resetglobalScriptsHead();
    2080 
    20812027                loadPrc(newPrcName);
    20822028
    20832029                strcpy(currentPrcName, newPrcName);
     
    20872033        }
    20882034
    20892035        if (newRelName[0] != 0) {
    2090                 releaseObjectScripts();
    2091                 resetObjectScriptHead();
    2092 
    20932036                loadRel(newRelName);
    20942037
    20952038                strcpy(currentRelName, newRelName);
     
    23152258#endif
    23162259}
    23172260
    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;
     2261uint16 addAni(uint16 param1, uint16 param2, const byte *ptr, SeqListElement *element, uint16 param3, int16 *param4) {
     2262        const byte *currentPtr = ptr;
     2263        const byte *ptrData;
     2264        const byte *ptr2;
    23222265        int16 di;
    23232266
    23242267        assert(ptr);
     
    23602303void processSeqListElement(SeqListElement *element) {
    23612304        int16 x = objectTable[element->var6].x;
    23622305        int16 y = objectTable[element->var6].y;
    2363         byte *ptr1 = animDataTable[element->varA].ptr1;
     2306        const byte *ptr1 = animDataTable[element->varA].data();
    23642307        int16 var_10;
    23652308        int16 var_4;
    23662309        int16 var_2;
  • 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/gfx.h

     
    3737extern uint16 c_palette[256];
    3838extern byte colorMode256;
    3939extern byte palette256[256 * 3];
     40extern byte newPalette[256 * 3];
     41extern byte newColorMode;
     42extern byte ctColorMode;
     43extern byte bgColorMode;
    4044
    4145void gfxInit();
    4246void gfxDestroy();
     
    4650void transformPaletteRange(byte startColor, byte numColor, int8 r, int8 g, int8 b);
    4751void gfxFlipPage(void);
    4852
    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);
     53void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
     54void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
    5155
    52 void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
     56void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    5357    int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx);
    5458
    5559void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
     
    5761
    5862void gfxResetPage(byte *pagePtr);
    5963
    60 int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width);
     64int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width);
     65byte gfxGetColor(int16 x, int16 y, const byte *ptr, int16 width);
    6166
    6267void gfxResetRawPage(byte *pageRaw);
    6368void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h);
    6469void gfxCopyRawPage(byte *source, byte * dest);
    6570void gfxFlipRawPage(byte *frontBuffer);
    66 void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
     71void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
    6772void 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);
     73void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height, byte *page, int16 x, int16 y);
     74void maskBgOverlay(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
    6975
     76void fadeFromBlack(void);
    7077void fadeToBlack(void);
    7178
    72 void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
     79// wtf?!
     80//void gfxDrawMaskedSprite(byte *param1, byte *param2, byte *param3, byte *param4, int16 param5);
    7381void gfxWaitVBL(void);
    7482void gfxRedrawMouseCursor(void);
    7583
  • engines/cine/bg.h

     
    2727#define CINE_BG_H
    2828
    2929namespace Cine {
     30struct bgData {
     31        byte *data;
     32        byte colorMode;
     33        byte *highPalette;
     34        uint16 *lowPalette;
     35};
    3036
    3137byte loadBg(const char *bgName);
    3238byte loadCt(const char *bgName);
    3339
     40//extern bgData additionalBgTable[9];
    3441extern byte *additionalBgTable[9];
    3542extern byte currentAdditionalBgIdx;
    3643extern byte currentAdditionalBgIdx2;
  • 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        debug(6, "assert(%d < %d)", 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 {
    500         debugN(5, "assert(%d < %d)\n", idx, _size);
     503        debug(6, "assert(%d < %d)", 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) {
    512         debugN(5, "assert(%d <= %d)\n", len, _size);
     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 {
     520        debug(6, "assert(%d <= %d)", len, _size);
    513521        assert(len <= _size);
    514522        for (unsigned int i = 0; i < len; i++) {
    515523                fHandle.writeUint16BE(_vars[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) {
    525         debugN(5, "assert(%d <= %d)\n", len, _size);
     539        debug(6, "assert(%d <= %d)", len, _size);
    526540        assert(len <= _size);
    527541        for (unsigned int i = 0; i < len; i++) {
    528542                _vars[i] = fHandle.readUint16BE();
    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 */
     611int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const {
     612        assert(_data);
     613        int pos = offset;
    609614
    610 void stopGlobalScript(uint16 scriptIdx) {
    611         prcLinkedListStruct *currentHead = &globalScriptsHead;
    612         prcLinkedListStruct *tempHead = currentHead;
     615        assert(pos >= 0);
    613616
    614         currentHead = tempHead->next;
     617        while (pos < _size) {
     618                uint8 opcode = _data[pos++];
     619                const char *ptr = info.opcodeInfo(opcode);
    615620
    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) {
     621                if (!ptr) {
    647622                        continue;
    648623                }
    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) {
     624
     625                for (; *ptr; ++ptr) {
     626                        switch (*ptr) {
    655627                        case 'b': // byte
    656                                 position++;
     628                                pos++;
    657629                                break;
    658630                        case 'w': // word
    659                                 position += 2;
     631                                pos += 2;
    660632                                break;
    661633                        case 'c': { // byte != 0 ? byte : word
    662                                         uint8 test = scriptPtr[position];
    663                                         position++;
     634                                        uint8 test = _data[pos];
     635                                        pos++;
    664636                                        if (test) {
    665                                                 position++;
     637                                                pos++;
    666638                                        } else {
    667                                                 position += 2;
     639                                                pos += 2;
    668640                                        }
    669641                                }
    670642                                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;
     643                        case 'l': // label
     644                                return pos;
    683645                        case 's': // string
    684                                 while (scriptPtr[position++] != 0);
     646                                while (_data[pos++] != 0);
    685647                                break;
    686648                        case 'x': // exit script
    687                                 return position;
     649                                return -pos-1;
    688650                        }
    689651                }
    690652        }
    691         return position;
     653        return _size;
    692654}
    693655
    694 void computeScriptStack(byte *scriptPtr, int16 *stackPtr, uint16 scriptSize) {
    695         computeScriptStackSub(true, scriptPtr, stackPtr, scriptSize, 0, 0);
    696 }
     656/*! \brief Calculate initial script labels
     657 * \param info Script info instance
     658 *
     659 * computeScriptStack replacement
     660 */
     661void RawScript::computeLabels(const FWScriptInfo &info) {
     662        assert(_data);
     663        int pos = 0;
     664        int i;
    697665
    698 uint16 computeScriptStackFromScript(byte *scriptPtr, uint16 currentPosition, uint16 labelIdx, uint16 scriptSize) {
    699         return computeScriptStackSub(false, scriptPtr, (int16 *)&dummyU16, (uint16)scriptSize, labelIdx, currentPosition);
     666        // reset labels
     667        for (i = 0; i < SCRIPT_STACK_SIZE; i++) {
     668                _labels[i] = -1;
     669        }
     670
     671        // parse bytecode
     672        while ((pos = getNextLabel(info, pos)) >= 0) {
     673                i = _data[pos];
     674                _labels[i] = ++pos;
     675        }
    700676}
    701677
    702 void palRotate(byte a, byte b, byte c) {
    703         if (c == 1) {
    704                 uint16 currentColor = c_palette[b];
     678/*! \brief find the next label from current position
     679 * \param info Script info instance
     680 * \param index Label index to look for
     681 * \param offset Current position in script
     682 * \return Position of next instruction following the label
     683 *
     684 * computeScriptStackFromScript replacement
     685 */
     686uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
     687        const {
    705688
    706                 for (int16 i = b; i > a; i--) {
    707                         c_palette[i] = c_palette[i - 1];
     689        assert(_data);
     690        int pos = offset;
     691
     692        while ((pos = getNextLabel(info, pos)) >= 0) {
     693                if (_data[pos++] == index) {
     694                        return pos;
    708695                }
     696        }
    709697
    710                 c_palette[a] = currentColor;
    711         }
     698        return -pos - 1;
    712699}
    713700
    714 void addScriptToList0(uint16 idx) {
    715         uint16 i;
    716         prcLinkedListStruct *pNewElement;
    717         prcLinkedListStruct *currentHead = &globalScriptsHead;
    718         prcLinkedListStruct *tempHead = currentHead;
     701/*! \brief Copy bytecode and calculate labels
     702 * \param data Bytecode to copy, must be _size long
     703 */
     704void RawScript::setData(const FWScriptInfo &info, const byte *data) {
     705        assert(!_data); // this function should be called only once per instance
     706        _data = new byte[_size+1];
    719707
    720         assert(idx <= NUM_MAX_SCRIPT);
     708        assert(data && _data);
     709        memcpy(_data, data, _size * sizeof(byte));
     710        _data[_size] = 0;
    721711
    722         currentHead = tempHead->next;
     712        computeLabels(info);
     713}
    723714
    724         while (currentHead) {
    725                 tempHead = currentHead;
     715/*! \brief Initial script labels
     716 * \return Precalculated script labels
     717 */
     718const ScriptVars &RawScript::labels(void) const {
     719        assert(_data);
     720        return _labels;
     721}
    726722
    727                 assert(tempHead);
     723/*! \brief One byte of bytecode
     724 * \param pos Index in bytecode
     725 * \return Byte from bytecode
     726 */
     727byte RawScript::getByte(unsigned int pos) const {
     728        assert(_data && pos < _size);
    728729
    729                 currentHead = tempHead->next;
    730         }
     730        return _data[pos];
     731}
    731732
    732         pNewElement = new prcLinkedListStruct;
     733/*! \brief One word of bytecode
     734 * \param pos Index of the first byte in bytecode
     735 * \return Word of bytecode
     736 */
     737uint16 RawScript::getWord(unsigned int pos) const {
     738        assert(_data && pos+1 < _size);
    733739
    734         assert(pNewElement);
     740        return READ_BE_UINT16(_data + pos);
     741}
    735742
    736         pNewElement->next = tempHead->next;
    737         tempHead->next = pNewElement;
     743/*! \brief String in bytecode
     744 * \param pos Index of the first char in string
     745 * \return Pointer to part of bytecode
     746 */
     747const char *RawScript::getString(unsigned int pos) const {
     748        assert(_data && pos < _size);
    738749
    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         }
     750        return (const char*)(_data+pos);
     751}
    743752
    744         pNewElement->compareResult = 0;
    745         pNewElement->scriptPosition = 0;
     753/*! \brief Constructor for partial loading
     754 * \param size Size of bytecode which will be added later
     755 * \param p1 First object script parameter
     756 * \param p2 Second object script parameter
     757 * \param p3 Third object script parameter
     758 *
     759 * This constructor _MUST_ be followed by setdata() method call before the
     760 * instance can be used. It leaves the instance in partially invalid state.
     761 */
     762RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
     763        : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
     764{ }
    746765
    747         pNewElement->scriptPtr = scriptTable[idx].ptr;
    748         pNewElement->scriptIdx = idx;
     766/*! \brief Complete constructor
     767 * \param data Script bytecode
     768 * \param s Bytecode length
     769 * \param p1 First object script parameter
     770 * \param p2 Second object script parameter
     771 * \param p3 Third object script parameter
     772 */
     773RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
     774        uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
     775        _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
     776
     777/*! \brief Contructor for global scripts
     778 * \param script Script bytecode reference
     779 * \param idx Script bytecode index
     780 */
     781FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
     782        _pos(0), _line(0), _compare(0), _index(idx),
     783        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     784        _globalVars(globalVars), _info(new FWScriptInfo) { }
     785
     786/*! \brief Copy constructor
     787 */
     788FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
     789        _line(src._line), _compare(src._compare), _index(src._index),
     790        _labels(src._labels), _localVars(src._localVars),
     791        _globalVars(src._globalVars), _info(new FWScriptInfo) { }
     792
     793/*! \brief Contructor for global scripts in derived classes
     794 * \param script Script bytecode reference
     795 * \param idx Script bytecode index
     796 */
     797FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
     798        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     799        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     800        _globalVars(globalVars), _info(info) { }
     801
     802/*! \brief Constructor for object scripts in derived classes
     803 * \param script Script bytecode reference
     804 * \param idx Script bytecode index
     805 */
     806FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
     807        _script(script), _pos(0), _line(0), _compare(0), _index(idx),
     808        _labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
     809        _globalVars(globalVars), _info(info) {
     810
     811        _localVars[0] = script.run();
    749812}
    750813
    751 int16 endScript0(uint16 scriptIdx) {
    752         prcLinkedListStruct *currentHead = &globalScriptsHead;
    753         prcLinkedListStruct *tempHead = currentHead;
     814/*! \brief Copy constructor for derived classes
     815 */
     816FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
     817        _script(src._script), _pos(src._pos), _line(src._line),
     818        _compare(src._compare), _index(src._index), _labels(src._labels),
     819        _localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
    754820
    755         //assert(scriptIdx <= NUM_MAX_SCRIPT);
     821FWScript::~FWScript(void) {
     822        delete _info;
     823}
    756824
    757         currentHead = tempHead->next;
     825/*! \brief Read next byte from bytecode
     826 * \return Byte from bytecode
     827 */
     828byte FWScript::getNextByte() {
     829        byte val = _script.getByte(_pos);
     830        _pos++;
     831        return val;
     832}
    758833
    759         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    760                 tempHead = currentHead;
    761                 currentHead = tempHead->next;
    762         }
     834/*! \brief Read next word from bytecode
     835 * \return Word from bytecode
     836 */
     837uint16 FWScript::getNextWord() {
     838        uint16 val = _script.getWord(_pos);
     839        _pos += 2;
     840        return val;
     841}
    763842
    764         if (!currentHead) {
    765                 return -1;
    766         }
     843/*! \brief Read next string from bytecode
     844 * \return Pointer to string
     845 */
     846const char *FWScript::getNextString() {
     847        const char *val = _script.getString(_pos);
     848        _pos += strlen(val) + 1;
     849        return val;
     850}
    767851
    768         if (currentHead->scriptIdx != scriptIdx) {
    769                 return -1;
     852/*! \brief Restore script state from savefile
     853 * \param labels Restored script labels
     854 * \param local Restored local script variables
     855 * \param compare Restored last comparison result
     856 * \param pos Restored script position
     857 */
     858void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     859        assert(pos < _script._size);
     860        _labels = labels;
     861        _localVars = local;
     862        _compare = compare;
     863        _pos = _line = pos;
     864}
     865
     866/*! \brief Execute script
     867 * \return <0 on script termination, >0 on script pause
     868 *
     869 * executeScript replacement.
     870 * Instruction handler must return 0 if the script should continue or
     871 * nonzero with the same meaning as return value of this function
     872 */
     873int FWScript::execute() {
     874        int ret = 0;
     875
     876        while (!ret) {
     877                _line = _pos;
     878                byte opcode = getNextByte();
     879                opFunc handler = _info->opcodeHandler(opcode);
     880
     881                if (handler) {
     882                        ret = (this->*handler)();
     883                }
    770884        }
    771885
    772         currentHead->scriptIdx = -1;
     886        return ret;
     887}
    773888
    774         return 0;
     889/*! \brief Save script to savefile
     890 * \param fHandle Savefile handle
     891 */
     892void FWScript::save(Common::OutSaveFile &fHandle) const {
     893        _labels.save(fHandle);
     894        _localVars.save(fHandle);
     895        fHandle.writeUint16BE(_compare);
     896        fHandle.writeUint16BE(_pos);
     897        // data order sucks...
     898        fHandle.writeUint16BE(_index);
    775899}
    776900
    777 int16 endScript1(uint16 scriptIdx) {
    778         prcLinkedListStruct *currentHead = &objScriptList;
    779         prcLinkedListStruct *tempHead = currentHead;
     901/*! \brief Contructor for global scripts
     902 * \param script Script bytecode reference
     903 * \param idx Script bytecode index
     904 */
     905OSScript::OSScript(const RawScript &script, int16 idx) :
     906        FWScript(script, idx, new OSScriptInfo) {}
    780907
    781         currentHead = tempHead->next;
     908/*! \brief Constructor for object scripts
     909 * \param script Script bytecode reference
     910 * \param idx Script bytecode index
     911 */
     912OSScript::OSScript(RawObjectScript &script, int16 idx) :
     913        FWScript(script, idx, new OSScriptInfo) {}
    782914
    783         while (currentHead && currentHead->scriptIdx != scriptIdx) {
    784                 tempHead = currentHead;
    785                 currentHead = tempHead->next;
    786         }
     915/*! \brief Copy constructor
     916 */
     917OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
    787918
    788         if (!currentHead) {
    789                 return -1;
     919/*! \brief Restore script state from savefile
     920 * \param labels Restored script labels
     921 * \param local Restored local script variables
     922 * \param compare Restored last comparison result
     923 * \param pos Restored script position
     924 */
     925void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     926        FWScript::load(labels, local, compare, pos);
     927}
     928/*! \brief Get opcode info string
     929 * \param opcode Opcode to look for in opcode table
     930 */
     931const char *FWScriptInfo::opcodeInfo(byte opcode) const {
     932        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     933                return NULL;
    790934        }
    791935
    792         if (currentHead->scriptIdx != scriptIdx) {
    793                 return -1;
     936        if (!FWScript::_opcodeTable[opcode - 1].args) {
     937                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeInfo", opcode - 1);
     938                return NULL;
    794939        }
    795940
    796         currentHead->scriptIdx = -1;
    797 
    798         return 0;
     941        return FWScript::_opcodeTable[opcode - 1].args;
    799942}
    800943
    801 int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
    802         byte *ptr = page + (y * width) + x / 2;
    803         byte zoneVar;
     944/*! \brief Get opcode handler pointer
     945 * \param opcode Opcode to look for in opcode table
     946 */
     947opFunc FWScriptInfo::opcodeHandler(byte opcode) const {
     948        if (opcode == 0 || opcode > FWScript::_numOpcodes) {
     949                return NULL;
     950        }
    804951
    805         if (!(x % 2)) {
    806                 zoneVar = (*(ptr) >> 4) & 0xF;
    807         } else {
    808                 zoneVar = (*(ptr)) & 0xF;
     952        if (!FWScript::_opcodeTable[opcode - 1].proc) {
     953                warning("Undefined opcode 0x%02X in FWScriptInfo::opcodeHandler", opcode - 1);
     954                return NULL;
    809955        }
    810956
    811         return zoneVar;
     957        return FWScript::_opcodeTable[opcode - 1].proc;
    812958}
    813959
    814 int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
    815         byte *ptr = page + (y * width) + x;
    816         byte zoneVar;
     960/*! \brief Create new FWScript instance
     961 * \param script Script bytecode
     962 * \param index Bytecode index
     963 */
     964FWScript *FWScriptInfo::create(const RawScript &script, int16 index) const {
     965        return new FWScript(script, index);
     966}
    817967
    818         zoneVar = (*(ptr)) & 0xF;
     968/*! \brief Create new FWScript instance
     969 * \param script Object script bytecode
     970 * \param index Bytecode index
     971 */
     972FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index) const {
     973        return new FWScript(script, index);
     974}
    819975
    820         return zoneVar;
     976/*! \brief Load saved FWScript instance
     977 * \param script Script bytecode
     978 * \param index Bytecode index
     979 * \param local Local variables
     980 * \param labels Script labels
     981 * \param compare Last compare result
     982 * \param pos Position in script
     983 */
     984FWScript *FWScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     985        FWScript *tmp = new FWScript(script, index);
     986        assert(tmp);
     987        tmp->load(labels, local, compare, pos);
     988        return tmp;
    821989}
    822990
    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;
     991/*! \brief Load saved FWScript instance
     992 * \param script Object script bytecode
     993 * \param index Bytecode index
     994 * \param local Local variables
     995 * \param labels Script labels
     996 * \param compare Last compare result
     997 * \param pos Position in script
     998 */
     999FWScript *FWScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1000        FWScript *tmp = new FWScript(script, index);
     1001        assert(tmp);
     1002        tmp->load(labels, local, compare, pos);
     1003        return tmp;
     1004}
    8271005
    828         for (int16 i = 0; i < numZones; i++) {
    829                 idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     1006/*! \brief Get opcode info string
     1007 * \param opcode Opcode to look for in opcode table
     1008 */
     1009const char *OSScriptInfo::opcodeInfo(byte opcode) const {
     1010        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1011                return NULL;
     1012        }
    8301013
    831                 assert(idx >= 0 && idx <= NUM_MAX_ZONE);
    832 
    833                 if (zoneData[idx] == zoneIdx) {
    834                         return 1;
    835                 }
     1014        if (!OSScript::_opcodeTable[opcode - 1].args) {
     1015                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
     1016                return NULL;
    8361017        }
    8371018
    838         return 0;
     1019        return OSScript::_opcodeTable[opcode - 1].args;
    8391020}
    8401021
    841 uint16 compareVars(int16 a, int16 b) {
    842         uint16 flag = 0;
     1022/*! \brief Get opcode handler pointer
     1023 * \param opcode Opcode to look for in opcode table
     1024 */
     1025opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
     1026        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     1027                return NULL;
     1028        }
    8431029
    844         if (a == b) {
    845                 flag |= kCmpEQ;
    846         } else if (a > b) {
    847                 flag |= kCmpGT;
    848         } else if (a < b) {
    849                 flag |= kCmpLT;
     1030        if (!OSScript::_opcodeTable[opcode - 1].proc) {
     1031                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
     1032                return NULL;
    8501033        }
    8511034
    852         return flag;
     1035        return OSScript::_opcodeTable[opcode - 1].proc;
    8531036}
    8541037
     1038/*! \brief Create new OSScript instance
     1039 * \param script Script bytecode
     1040 * \param index Bytecode index
     1041 */
     1042FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
     1043        return new OSScript(script, index);
     1044}
     1045
     1046/*! \brief Create new OSScript instance
     1047 * \param script Object script bytecode
     1048 * \param index Bytecode index
     1049 */
     1050FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
     1051        return new OSScript(script, index);
     1052}
     1053
     1054/*! \brief Load saved OSScript instance
     1055 * \param script Script bytecode
     1056 * \param index Bytecode index
     1057 * \param local Local variables
     1058 * \param labels Script labels
     1059 * \param compare Last compare result
     1060 * \param pos Position in script
     1061 */
     1062FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1063        OSScript *tmp = new OSScript(script, index);
     1064        assert(tmp);
     1065        tmp->load(labels, local, compare, pos);
     1066        return tmp;
     1067}
     1068
     1069/*! \brief Load saved OSScript instance
     1070 * \param script Object script bytecode
     1071 * \param index Bytecode index
     1072 * \param local Local variables
     1073 * \param labels Script labels
     1074 * \param compare Last compare result
     1075 * \param pos Position in script
     1076 */
     1077FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     1078        OSScript *tmp = new OSScript(script, index);
     1079        assert(tmp);
     1080        tmp->load(labels, local, compare, pos);
     1081        return tmp;
     1082}
     1083
    8551084// ------------------------------------------------------------------------
    8561085// FUTURE WARS opcodes
    8571086// ------------------------------------------------------------------------
    8581087
    859 void o1_modifyObjectParam() {
     1088int FWScript::o1_modifyObjectParam() {
    8601089        byte objIdx = getNextByte();
    8611090        byte paramIdx = getNextByte();
    8621091        int16 newValue = getNextWord();
    8631092
    864         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1093        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8651094
    8661095        modifyObjectParam(objIdx, paramIdx, newValue);
     1096        return 0;
    8671097}
    8681098
    869 void o1_getObjectParam() {
     1099int FWScript::o1_getObjectParam() {
    8701100        byte objIdx = getNextByte();
    8711101        byte paramIdx = getNextByte();
    8721102        byte newValue = getNextByte();
    8731103
    874         debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _currentLine, objIdx, paramIdx, newValue);
     1104        debugC(5, kCineDebugScript, "Line: %d: getObjectParam(objIdx:%d,paramIdx:%d,var:%d)", _line, objIdx, paramIdx, newValue);
    8751105
    876         _currentScriptElement->localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1106        _localVars[newValue] = getObjectParam(objIdx, paramIdx);
     1107        return 0;
    8771108}
    8781109
    879 void o1_addObjectParam() {
     1110int FWScript::o1_addObjectParam() {
    8801111        byte objIdx = getNextByte();
    8811112        byte paramIdx = getNextByte();
    8821113        int16 newValue = getNextWord();
    8831114
    884         debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1115        debugC(5, kCineDebugScript, "Line: %d: addObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8851116
    8861117        addObjectParam(objIdx, paramIdx, newValue);
     1118        return 0;
    8871119}
    8881120
    889 void o1_subObjectParam() {
     1121int FWScript::o1_subObjectParam() {
    8901122        byte objIdx = getNextByte();
    8911123        byte paramIdx = getNextByte();
    8921124        int16 newValue = getNextWord();
    8931125
    894         debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _currentLine, objIdx, paramIdx, newValue);
     1126        debugC(5, kCineDebugScript, "Line: %d: subObjectParam(objIdx:%d,paramIdx:%d,newValue:%d)", _line, objIdx, paramIdx, newValue);
    8951127
    8961128        subObjectParam(objIdx, paramIdx, newValue);
     1129        return 0;
    8971130}
    8981131
    899 void o1_add2ObjectParam() {
    900         getNextByte();
    901         getNextByte();
    902         getNextWord();
    903         warning("STUB: o1_add2ObjectParam()");
     1132/*! \todo Implement this instruction
     1133 */
     1134int FWScript::o1_add2ObjectParam() {
     1135        uint16 a = getNextByte();
     1136        uint16 b = getNextByte();
     1137        uint16 c = getNextWord();
     1138        warning("STUB: o1_add2ObjectParam(%x, %x, %x)", a, b, c);
     1139        return 0;
    9041140}
    9051141
    906 void o1_sub2ObjectParam() {
    907         getNextByte();
    908         getNextByte();
    909         getNextWord();
    910         warning("STUB: o1_sub2ObjectParam()");
     1142/*! \todo Implement this instruction
     1143 */
     1144int FWScript::o1_sub2ObjectParam() {
     1145        uint16 a = getNextByte();
     1146        uint16 b = getNextByte();
     1147        uint16 c = getNextWord();
     1148        warning("STUB: o1_sub2ObjectParam(%x, %x, %x)", a, b, c);
     1149        return 0;
    9111150}
    9121151
    913 void o1_compareObjectParam() {
     1152int FWScript::o1_compareObjectParam() {
    9141153        byte objIdx = getNextByte();
    9151154        byte param1 = getNextByte();
    9161155        int16 param2 = getNextWord();
    9171156
    918         debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _currentLine, objIdx, param1, param2);
     1157        debugC(5, kCineDebugScript, "Line: %d: compareObjectParam(objIdx:%d,type:%d,value:%d)", _line, objIdx, param1, param2);
    9191158
    920         _currentScriptElement->compareResult = compareObjectParam(objIdx, param1, param2);
     1159        _compare = compareObjectParam(objIdx, param1, param2);
     1160        return 0;
    9211161}
    9221162
    923 void o1_setupObject() {
     1163int FWScript::o1_setupObject() {
    9241164        byte objIdx = getNextByte();
    9251165        int16 param1 = getNextWord();
    9261166        int16 param2 = getNextWord();
    9271167        int16 param3 = getNextWord();
    9281168        int16 param4 = getNextWord();
    9291169
    930         debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1170        debugC(5, kCineDebugScript, "Line: %d: setupObject(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9311171
    9321172        setupObject(objIdx, param1, param2, param3, param4);
     1173        return 0;
    9331174}
    9341175
    935 void o1_checkCollision() {
     1176int FWScript::o1_checkCollision() {
    9361177        byte objIdx = getNextByte();
    9371178        int16 param1 = getNextWord();
    9381179        int16 param2 = getNextWord();
    9391180        int16 param3 = getNextWord();
    9401181        int16 param4 = getNextWord();
    9411182
    942         debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _currentLine, objIdx, param1, param2, param3, param4);
     1183        debugC(5, kCineDebugScript, "Line: %d: checkCollision(objIdx:%d,%d,%d,%d,%d)", _line, objIdx, param1, param2, param3, param4);
    9431184
    944         _currentScriptElement->compareResult = checkCollision(objIdx, param1, param2, param3, param4);
     1185        _compare = checkCollision(objIdx, param1, param2, param3, param4);
     1186        return 0;
    9451187}
    9461188
    947 void o1_loadVar() {
     1189int FWScript::o1_loadVar() {
    9481190        byte varIdx = getNextByte();
    9491191        byte varType = getNextByte();
    9501192
     
    9541196
    9551197                switch (varType) {
    9561198                case 1:
    957                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    958                         _currentScriptElement->localVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1199                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = var[%d]", _line, varIdx, dataIdx);
     1200                        _localVars[varIdx] = _localVars[dataIdx];
    9591201                        break;
    9601202                case 2:
    961                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    962                         _currentScriptElement->localVars[varIdx] = globalVars[dataIdx];
     1203                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1204                        _localVars[varIdx] = _globalVars[dataIdx];
    9631205                        break;
    9641206                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;
     1207                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseX", _line, varIdx);
     1208                        getMouseData(mouseUpdateStatus, &dummyU16, (uint16 *)&var, &dummyU16);
     1209                        _localVars[varIdx] = var;
    9681210                        break;
    9691211                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;
     1212                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = mouseY", _line, varIdx);
     1213                        getMouseData(mouseUpdateStatus, &dummyU16, &dummyU16, (uint16 *)&var);
     1214                        _localVars[varIdx] = var;
    9731215                        break;
    9741216                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);
     1217                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = rand mod %d", _line, varIdx, dataIdx);
     1218                        _localVars[varIdx] = g_cine->_rnd.getRandomNumber(dataIdx - 1);
    9771219                        break;
    9781220                case 8:
    979                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _currentLine, varIdx, dataIdx);
    980                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].packedSize;
     1221                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].packedSize", _line, varIdx, dataIdx);
     1222                        _localVars[varIdx] = partBuffer[dataIdx].packedSize;
    9811223                        break;
    9821224                case 9:
    983                         debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _currentLine, varIdx, dataIdx);
    984                         _currentScriptElement->localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
     1225                        debugC(5, kCineDebugScript, "Line: %d: var[%d] = file[%d].unpackedSize", _line, varIdx, dataIdx);
     1226                        _localVars[varIdx] = partBuffer[dataIdx].unpackedSize;
    9851227                        break;
    9861228                default:
    9871229                        error("executeScript: o1_loadVar: Unknown variable type %d", varType);
     
    9891231        } else {
    9901232                int16 value = getNextWord();
    9911233
    992                 debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _currentLine, varIdx, value);
    993                 _currentScriptElement->localVars[varIdx] = value;
     1234                debugC(5, kCineDebugScript, "Line: %d: var[%d] = %d", _line, varIdx, value);
     1235                _localVars[varIdx] = value;
    9941236        }
     1237
     1238        return 0;
    9951239}
    9961240
    997 void o1_addVar() {
     1241int FWScript::o1_addVar() {
    9981242        byte varIdx = getNextByte();
    9991243        byte varType = getNextByte();
    10001244
    10011245        if (varType) {
    10021246                byte dataIdx = getNextByte();
    10031247
    1004                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _currentLine, varIdx, dataIdx);
    1005                 _currentScriptElement->localVars[varIdx] += _currentScriptElement->localVars[dataIdx];
     1248                if (varType == 1) {
     1249                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += var[%d]", _line, varIdx, dataIdx);
     1250                        _localVars[varIdx] += _localVars[dataIdx];
     1251                } else if (varType == 2) {
     1252                        debugC(5, kCineDebugScript, "Line: %d: var[%d] += globalVar[%d]", _line, varIdx, dataIdx);
     1253                        _localVars[varIdx] += _globalVars[dataIdx];
     1254                }
    10061255        } else {
    10071256                int16 value = getNextWord();
    10081257
    1009                 debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _currentLine, varIdx, value);
    1010                 _currentScriptElement->localVars[varIdx] += value;
     1258                debugC(5, kCineDebugScript, "Line: %d: var[%d] += %d", _line, varIdx, value);
     1259                _localVars[varIdx] += value;
    10111260        }
     1261
     1262        return 0;
    10121263}
    10131264
    1014 void o1_subVar() {
     1265int FWScript::o1_subVar() {
    10151266        byte varIdx = getNextByte();
    10161267        byte varType = getNextByte();
    10171268
    10181269        if (varType) {
    10191270                byte dataIdx = getNextByte();
    10201271
    1021                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _currentLine, varIdx, dataIdx);
    1022                 _currentScriptElement->localVars[varIdx] -= _currentScriptElement->localVars[dataIdx];
     1272                if (varType == 1) {
     1273                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= var[%d]", _line, varIdx, dataIdx);
     1274                        _localVars[varIdx] -= _localVars[dataIdx];
     1275                } else if (varType == 2) {
     1276                        debugC(5, kCineDebugScript, "Line: %d: var[%d] -= globalVar[%d]", _line, varIdx, dataIdx);
     1277                        _localVars[varIdx] -= _globalVars[dataIdx];
     1278                }
     1279
    10231280        } else {
    10241281                int16 value = getNextWord();
    10251282
    1026                 debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _currentLine, varIdx, value);
    1027                 _currentScriptElement->localVars[varIdx] -= value;
     1283                debugC(5, kCineDebugScript, "Line: %d: var[%d] -= %d", _line, varIdx, value);
     1284                _localVars[varIdx] -= value;
    10281285        }
     1286
     1287        return 0;
    10291288}
    10301289
    1031 void o1_mulVar() {
     1290int FWScript::o1_mulVar() {
    10321291        byte varIdx = getNextByte();
    10331292        byte varType = getNextByte();
    10341293
    10351294        if (varType) {
    10361295                byte dataIdx = getNextByte();
    10371296
    1038                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _currentLine, varIdx, dataIdx);
    1039                 _currentScriptElement->localVars[varIdx] *= _currentScriptElement->localVars[dataIdx];
     1297                if (varType == 1) {
     1298                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= var[%d]", _line, varIdx, dataIdx);
     1299                        _localVars[varIdx] *= _localVars[dataIdx];
     1300                } else if (varType == 2) {
     1301                        debugC(5, kCineDebugScript, "Line: %d: var[%d] *= globalVar[%d]", _line, varIdx, dataIdx);
     1302                        _localVars[varIdx] *= _globalVars[dataIdx];
     1303                }
    10401304        } else {
    10411305                int16 value = getNextWord();
    10421306
    1043                 debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _currentLine, varIdx, value);
    1044                 _currentScriptElement->localVars[varIdx] *= value;
     1307                debugC(5, kCineDebugScript, "Line: %d: var[%d] *= %d", _line, varIdx, value);
     1308                _localVars[varIdx] *= value;
    10451309        }
     1310
     1311        return 0;
    10461312}
    10471313
    1048 void o1_divVar() {
     1314int FWScript::o1_divVar() {
    10491315        byte varIdx = getNextByte();
    10501316        byte varType = getNextByte();
    10511317
    10521318        if (varType) {
    10531319                byte dataIdx = getNextByte();
    10541320
    1055                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _currentLine, varIdx, dataIdx);
    1056                 _currentScriptElement->localVars[varIdx] /= _currentScriptElement->localVars[dataIdx];
     1321                if (varType == 1) {
     1322                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= var[%d]", _line, varIdx, dataIdx);
     1323                        _localVars[varIdx] /= _localVars[dataIdx];
     1324                } else if (varType == 2) {
     1325                        debugC(5, kCineDebugScript, "Line: %d: var[%d] /= globalVar[%d]", _line, varIdx, dataIdx);
     1326                        _localVars[varIdx] /= _globalVars[dataIdx];
     1327                }
    10571328        } else {
    10581329                int16 value = getNextWord();
    10591330
    1060                 debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _currentLine, varIdx, value);
    1061                 _currentScriptElement->localVars[varIdx] /= value;
     1331                debugC(5, kCineDebugScript, "Line: %d: var[%d] /= %d", _line, varIdx, value);
     1332                _localVars[varIdx] /= value;
    10621333        }
     1334
     1335        return 0;
    10631336}
    10641337
    1065 void o1_compareVar() {
     1338int FWScript::o1_compareVar() {
    10661339        byte varIdx = getNextByte();
    10671340        byte varType = getNextByte();
    10681341
    10691342        if (varType) {
    10701343                byte dataIdx = getNextByte();
    10711344
    1072                 // printf("Val: %d\n", dataIdx);
    1073 
    10741345                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]);
     1346                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and var[%d]", _line, varIdx, dataIdx);
     1347                        _compare = compareVars(_localVars[varIdx], _localVars[dataIdx]);
    10801348                } 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]);
     1349                        debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and globalVar[%d]", _line, varIdx, dataIdx);
     1350                        _compare = compareVars(_localVars[varIdx], _globalVars[dataIdx]);
    10851351                }
    10861352        } else {
    10871353                int16 value = getNextWord();
    10881354
    1089                 debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _currentLine, varIdx, value);
    1090                 _currentScriptElement->compareResult = compareVars(_currentScriptElement->localVars[varIdx], value);
     1355                debugC(5, kCineDebugScript, "Line: %d: compare var[%d] and %d", _line, varIdx, value);
     1356                _compare = compareVars(_localVars[varIdx], value);
    10911357        }
     1358
     1359        return 0;
    10921360}
    10931361
    1094 void o1_modifyObjectParam2() {
     1362int FWScript::o1_modifyObjectParam2() {
    10951363        byte objIdx = getNextByte();
    10961364        byte paramIdx = getNextByte();
    10971365        byte newValue = getNextByte();
    10981366
    1099         debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _currentLine, objIdx, paramIdx, newValue);
     1367        debugC(5, kCineDebugScript, "Line: %d: modifyObjectParam2(objIdx:%d,paramIdx:%d,var[%d])", _line, objIdx, paramIdx, newValue);
    11001368
    1101         modifyObjectParam(objIdx, paramIdx, _currentScriptElement->localVars[newValue]);
     1369        modifyObjectParam(objIdx, paramIdx, _localVars[newValue]);
     1370        return 0;
    11021371}
    11031372
    1104 void o1_loadMask0() {
     1373int FWScript::o1_loadMask0() {
    11051374        // OP_loadV7Element
    11061375        byte param = getNextByte();
    11071376
    1108         debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _currentLine, param);
     1377        debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
    11091378        loadOverlayElement(param, 0);
     1379        return 0;
    11101380}
    11111381
    1112 void o1_unloadMask0() {
     1382int FWScript::o1_unloadMask0() {
    11131383        byte param = getNextByte();
    11141384
    1115         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _currentLine, param);
     1385        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
    11161386        freeOverlay(param, 0);
     1387        return 0;
    11171388}
    11181389
    1119 void o1_addToBgList() {
     1390int FWScript::o1_addToBgList() {
    11201391        byte param = getNextByte();
    11211392
    1122         debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _currentLine, param);
     1393        debugC(5, kCineDebugScript, "Line: %d: addToBGList(%d)", _line, param);
    11231394        addToBGList(param);
     1395        return 0;
    11241396}
    11251397
    1126 void o1_loadMask1() {
     1398int FWScript::o1_loadMask1() {
    11271399        byte param = getNextByte();
    11281400
    1129         debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _currentLine, param);
     1401        debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
    11301402        loadOverlayElement(param, 1);
     1403        return 0;
    11311404}
    11321405
    1133 void o1_unloadMask1() {
     1406int FWScript::o1_unloadMask1() {
    11341407        byte param = getNextByte();
    11351408
    1136         debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _currentLine, param);
     1409        debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
    11371410        freeOverlay(param, 1);
     1411        return 0;
    11381412}
    11391413
    1140 void o1_loadMask4() {
     1414int FWScript::o1_loadMask4() {
    11411415        byte param = getNextByte();
    11421416
    1143         debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _currentLine, param);
     1417        debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
    11441418        loadOverlayElement(param, 4);
     1419        return 0;
    11451420}
    11461421
    1147 void o1_unloadMask4() {
     1422int FWScript::o1_unloadMask4() {
    11481423        byte param = getNextByte();
    11491424
    1150         debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _currentLine, param);
     1425        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
    11511426        freeOverlay(param, 4);
     1427        return 0;
    11521428}
    11531429
    1154 void o1_addSpriteFilledToBgList() {
     1430int FWScript::o1_addSpriteFilledToBgList() {
    11551431        byte param = getNextByte();
    11561432
    1157         debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _currentLine, param);
     1433        debugC(5, kCineDebugScript, "Line: %d: op1A(%d) -> TODO !", _line, param);
    11581434        addSpriteFilledToBGList(param);
     1435        return 0;
    11591436}
    11601437
    1161 void o1_op1B() {
    1162         debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _currentLine);
    1163         freeBgIncrustList();
     1438int FWScript::o1_op1B() {
     1439        debugC(5, kCineDebugScript, "Line: %d: freeBgIncrustList", _line);
     1440        bgIncrustList.clear();
     1441        return 0;
    11641442}
    11651443
    1166 void o1_label() {
     1444int FWScript::o1_label() {
    11671445        byte labelIdx = getNextByte();
    11681446
    1169         debugC(5, kCineDebugScript, "Line: %d: label(%d)", _currentLine, labelIdx);
    1170         _currentScriptElement->stack[labelIdx] = _currentPosition;
     1447        debugC(5, kCineDebugScript, "Line: %d: label(%d)", _line, labelIdx);
     1448        _labels[labelIdx] = _pos;
     1449        return 0;
    11711450}
    11721451
    1173 void o1_goto() {
     1452int FWScript::o1_goto() {
    11741453        byte labelIdx = getNextByte();
    11751454
    1176         assert(_currentScriptElement->stack[labelIdx] != -1);
     1455        assert(_labels[labelIdx] != -1);
    11771456
    1178         debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _currentLine, labelIdx);
    1179         _currentPosition = _currentScriptElement->stack[labelIdx];
     1457        debugC(5, kCineDebugScript, "Line: %d: goto label(%d)", _line, labelIdx);
     1458        _pos = _labels[labelIdx];
     1459        return 0;
    11801460}
    11811461
    1182 void o1_gotoIfSup() {
     1462int FWScript::o1_gotoIfSup() {
    11831463        byte labelIdx = getNextByte();
    11841464
    1185         if (_currentScriptElement->compareResult == kCmpGT) {
    1186                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1465        if (_compare == kCmpGT) {
     1466                assert(_labels[labelIdx] != -1);
    11871467
    1188                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _currentLine, labelIdx);
    1189                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1468                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (true)", _line, labelIdx);
     1469                _pos = _labels[labelIdx];
    11901470        } else {
    1191                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _currentLine, labelIdx);
     1471                debugC(5, kCineDebugScript, "Line: %d: if(>) goto %d (false)", _line, labelIdx);
    11921472        }
     1473        return 0;
    11931474}
    11941475
    1195 void o1_gotoIfSupEqu() {
     1476int FWScript::o1_gotoIfSupEqu() {
    11961477        byte labelIdx = getNextByte();
    11971478
    1198         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1199                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1479        if (_compare & (kCmpGT | kCmpEQ)) {
     1480                assert(_labels[labelIdx] != -1);
    12001481
    1201                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _currentLine, labelIdx);
    1202                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1482                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (true)", _line, labelIdx);
     1483                _pos = _labels[labelIdx];
    12031484        } else {
    1204                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _currentLine, labelIdx);
     1485                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto %d (false)", _line, labelIdx);
    12051486        }
     1487        return 0;
    12061488}
    12071489
    1208 void o1_gotoIfInf() {
     1490int FWScript::o1_gotoIfInf() {
    12091491        byte labelIdx = getNextByte();
    12101492
    1211         if (_currentScriptElement->compareResult == kCmpLT) {
    1212                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1493        if (_compare == kCmpLT) {
     1494                assert(_labels[labelIdx] != -1);
    12131495
    1214                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _currentLine, labelIdx);
    1215                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1496                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (true)", _line, labelIdx);
     1497                _pos = _labels[labelIdx];
    12161498        } else {
    1217                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _currentLine, labelIdx);
     1499                debugC(5, kCineDebugScript, "Line: %d: if(<) goto %d (false)", _line, labelIdx);
    12181500        }
     1501        return 0;
    12191502}
    12201503
    1221 void o1_gotoIfInfEqu() {
     1504int FWScript::o1_gotoIfInfEqu() {
    12221505        byte labelIdx = getNextByte();
    12231506
    1224         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1225                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1507        if (_compare & (kCmpLT | kCmpEQ)) {
     1508                assert(_labels[labelIdx] != -1);
    12261509
    1227                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _currentLine, labelIdx);
    1228                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1510                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (true)", _line, labelIdx);
     1511                _pos = _labels[labelIdx];
    12291512        } else {
    1230                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _currentLine, labelIdx);
     1513                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto %d (false)", _line, labelIdx);
    12311514        }
     1515        return 0;
    12321516}
    12331517
    1234 void o1_gotoIfEqu() {
     1518int FWScript::o1_gotoIfEqu() {
    12351519        byte labelIdx = getNextByte();
    12361520
    1237         if (_currentScriptElement->compareResult == kCmpEQ) {
    1238                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1521        if (_compare == kCmpEQ) {
     1522                assert(_labels[labelIdx] != -1);
    12391523
    1240                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _currentLine, labelIdx);
    1241                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1524                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (true)", _line, labelIdx);
     1525                _pos = _labels[labelIdx];
    12421526        } else {
    1243                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _currentLine, labelIdx);
     1527                debugC(5, kCineDebugScript, "Line: %d: if(==) goto %d (false)", _line, labelIdx);
    12441528        }
     1529        return 0;
    12451530}
    12461531
    1247 void o1_gotoIfDiff() {
     1532int FWScript::o1_gotoIfDiff() {
    12481533        byte labelIdx = getNextByte();
    12491534
    1250         if (_currentScriptElement->compareResult != kCmpEQ) {
    1251                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1535        if (_compare != kCmpEQ) {
     1536                assert(_labels[labelIdx] != -1);
    12521537
    1253                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _currentLine, labelIdx);
    1254                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1538                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (true)", _line, labelIdx);
     1539                _pos = _labels[labelIdx];
    12551540        } else {
    1256                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _currentLine, labelIdx);
     1541                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto %d (false)", _line, labelIdx);
    12571542        }
     1543        return 0;
    12581544}
    12591545
    1260 void o1_removeLabel() {
     1546int FWScript::o1_removeLabel() {
    12611547        byte labelIdx = getNextByte();
    12621548
    1263         debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _currentLine, labelIdx);
    1264         _currentScriptElement->stack[labelIdx] = -1;
     1549        debugC(5, kCineDebugScript, "Line: %d: removeLabel(%d)", _line, labelIdx);
     1550        _labels[labelIdx] = -1;
     1551        return 0;
    12651552}
    12661553
    1267 void o1_loop() {
     1554int FWScript::o1_loop() {
    12681555        byte varIdx = getNextByte();
    12691556        byte labelIdx = getNextByte();
    12701557
    1271         _currentScriptElement->localVars[varIdx]--;
     1558        _localVars[varIdx]--;
    12721559
    1273         if (_currentScriptElement->localVars[varIdx] >= 0) {
    1274                 assert(_currentScriptElement->stack[labelIdx] != -1);
     1560        if (_localVars[varIdx] >= 0) {
     1561                assert(_labels[labelIdx] != -1);
    12751562
    1276                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _currentLine, varIdx, labelIdx);
    1277                 _currentPosition = _currentScriptElement->stack[labelIdx];
     1563                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (continue)", _line, varIdx, labelIdx);
     1564                _pos = _labels[labelIdx];
    12781565        } else {
    1279                 debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _currentLine, varIdx, labelIdx);
     1566                debugC(5, kCineDebugScript, "Line: %d: loop(var[%d]) goto %d (stop)", _line, varIdx, labelIdx);
    12801567        }
     1568        return 0;
    12811569}
    12821570
    1283 void o1_startGlobalScript() {
     1571int FWScript::o1_startGlobalScript() {
    12841572        // OP_startScript
    12851573        byte param = getNextByte();
    12861574
    12871575        assert(param < NUM_MAX_SCRIPT);
    12881576
    1289         debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _currentLine, param);
     1577        debugC(5, kCineDebugScript, "Line: %d: startScript(%d)", _line, param);
    12901578        addScriptToList0(param);
     1579        return 0;
    12911580}
    12921581
    1293 void o1_endGlobalScript() {
     1582int FWScript::o1_endGlobalScript() {
    12941583        byte scriptIdx = getNextByte();
    12951584
    1296         debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _currentLine, scriptIdx);
    1297         stopGlobalScript(scriptIdx);
     1585        debugC(5, kCineDebugScript, "Line: %d: stopGlobalScript(%d)", _line, scriptIdx);
     1586
     1587        ScriptList::iterator it = globalScripts.begin();
     1588
     1589        for (; it != globalScripts.end(); ++it) {
     1590                if ((*it)->_index == scriptIdx) {
     1591                        (*it)->_index = -1;
     1592                }
     1593        }
     1594
     1595        return 0;
    12981596}
    12991597
    1300 void o1_loadAnim() {
     1598int FWScript::o1_loadAnim() {
    13011599        // OP_loadResource
    13021600        const char *param = getNextString();
    13031601
    1304         debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _currentLine, param);
     1602        debugC(5, kCineDebugScript, "Line: %d: loadResource(\"%s\")", _line, param);
    13051603        loadResource(param);
     1604        return 0;
    13061605}
    13071606
    1308 void o1_loadBg() {
     1607int FWScript::o1_loadBg() {
    13091608        const char *param = getNextString();
    13101609
    1311         debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _currentLine, param);
     1610        debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
    13121611
    13131612        loadBg(param);
    1314         freeBgIncrustList();
     1613        bgIncrustList.clear();
    13151614        bgVar0 = 0;
     1615        return 0;
    13161616}
    13171617
    1318 void o1_loadCt() {
     1618int FWScript::o1_loadCt() {
    13191619        const char *param = getNextString();
    13201620
    1321         debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _currentLine, param);
     1621        debugC(5, kCineDebugScript, "Line: %d: loadCt(\"%s\")", _line, param);
    13221622        loadCt(param);
     1623        return 0;
    13231624}
    13241625
    1325 void o1_loadPart() {
     1626int FWScript::o1_loadPart() {
    13261627        const char *param = getNextString();
    13271628
    1328         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     1629        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
    13291630        loadPart(param);
     1631        return 0;
    13301632}
    13311633
    1332 void o1_closePart() {
    1333         debugC(5, kCineDebugScript, "Line: %d: closePart", _currentLine);
     1634int FWScript::o1_closePart() {
     1635        debugC(5, kCineDebugScript, "Line: %d: closePart", _line);
    13341636        closePart();
     1637        return 0;
    13351638}
    13361639
    1337 void o1_loadNewPrcName() {
     1640int FWScript::o1_loadNewPrcName() {
    13381641        // OP_loadData
    13391642        byte param1 = getNextByte();
    13401643        const char *param2 = getNextString();
     
    13431646
    13441647        switch (param1) {
    13451648        case 0:
    1346                 debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _currentLine, param2);
     1649                debugC(5, kCineDebugScript, "Line: %d: loadPrc(\"%s\")", _line, param2);
    13471650                strcpy(newPrcName, param2);
    13481651                break;
    13491652        case 1:
    1350                 debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _currentLine, param2);
     1653                debugC(5, kCineDebugScript, "Line: %d: loadRel(\"%s\")", _line, param2);
    13511654                strcpy(newRelName, param2);
    13521655                break;
    13531656        case 2:
    1354                 debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _currentLine, param2);
     1657                debugC(5, kCineDebugScript, "Line: %d: loadObject(\"%s\")", _line, param2);
    13551658                strcpy(newObjectName, param2);
    13561659                break;
    13571660        case 3:
    1358                 debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _currentLine, param2);
     1661                debugC(5, kCineDebugScript, "Line: %d: loadMsg(\"%s\")", _line, param2);
    13591662                strcpy(newMsgName, param2);
    13601663                break;
    13611664        }
     1665        return 0;
    13621666}
    13631667
    1364 void o1_requestCheckPendingDataLoad() {
    1365         debugC(5, kCineDebugScript, "Line: %d: request data load", _currentLine);
     1668int FWScript::o1_requestCheckPendingDataLoad() {
     1669        debugC(5, kCineDebugScript, "Line: %d: request data load", _line);
    13661670        checkForPendingDataLoadSwitch = 1;
     1671        return 0;
    13671672}
    13681673
    1369 void o1_blitAndFade() {
    1370         debugC(5, kCineDebugScript, "Line: %d: request fadein", _currentLine);
     1674int FWScript::o1_blitAndFade() {
     1675        debugC(5, kCineDebugScript, "Line: %d: request fadein", _line);
    13711676        // TODO: use real code
    13721677
    13731678        drawOverlays();
    13741679        fadeRequired = true;
    13751680        flip();
     1681
     1682//      fadeFromBlack();
     1683        return 0;
    13761684}
    13771685
    1378 void o1_fadeToBlack() {
    1379         debugC(5, kCineDebugScript, "Line: %d: request fadeout", _currentLine);
     1686int FWScript::o1_fadeToBlack() {
     1687        debugC(5, kCineDebugScript, "Line: %d: request fadeout", _line);
    13801688
    13811689        fadeToBlack();
     1690        return 0;
    13821691}
    13831692
    1384 void o1_transformPaletteRange() {
     1693int FWScript::o1_transformPaletteRange() {
    13851694        byte startColor = getNextByte();
    13861695        byte numColor = getNextByte();
    13871696        uint16 r = getNextWord();
    13881697        uint16 g = getNextWord();
    13891698        uint16 b = getNextWord();
    13901699
    1391         debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _currentLine, startColor, numColor, r, g, b);
     1700        debugC(5, kCineDebugScript, "Line: %d: transformPaletteRange(from:%d,numIdx:%d,r:%d,g:%d,b:%d)", _line, startColor, numColor, r, g, b);
    13921701
    13931702        transformPaletteRange(startColor, numColor, r, g, b);
     1703        return 0;
    13941704}
    13951705
    1396 void o1_setDefaultMenuColor2() {
     1706int FWScript::o1_setDefaultMenuColor2() {
    13971707        byte param = getNextByte();
    13981708
    1399         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _currentLine, param);
     1709        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor2(%d)", _line, param);
    14001710        defaultMenuBoxColor2 = param;
     1711        return 0;
    14011712}
    14021713
    1403 void o1_palRotate() {
     1714int FWScript::o1_palRotate() {
    14041715        byte a = getNextByte();
    14051716        byte b = getNextByte();
    14061717        byte c = getNextByte();
    14071718
    1408         debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _currentLine, a, b, c);
     1719        debugC(5, kCineDebugScript, "Line: %d: palRotate(%d,%d,%d)", _line, a, b, c);
    14091720        palRotate(a, b, c);
     1721        return 0;
    14101722}
    14111723
    1412 void o1_break() {
    1413         debugC(5, kCineDebugScript, "Line: %d: break", _currentLine);
     1724/*!\brief Pause script
     1725 * \todo Make sure it works
     1726 */
     1727int FWScript::o1_break() {
     1728        debugC(5, kCineDebugScript, "Line: %d: break", _line);
    14141729
    1415         _currentScriptElement->scriptPosition = _currentPosition;
    1416         _closeScript = 1;
     1730        return 1;
    14171731}
    14181732
    1419 void o1_endScript() {
    1420         debugC(5, kCineDebugScript, "Line: %d: endScript", _currentLine);
     1733/*! \brief Terminate script
     1734 * \todo Make sure it works
     1735 */
     1736int FWScript::o1_endScript() {
     1737        debugC(5, kCineDebugScript, "Line: %d: endScript", _line);
    14211738
    1422         if (_currentScriptParams == 0) {
    1423                 endScript0(_currentScriptElement->scriptIdx);
    1424         } else {
    1425                 endScript1(_currentScriptElement->scriptIdx);
    1426         }
    1427 
    1428         _closeScript = 1;
     1739        return -1;
    14291740}
    14301741
    1431 void o1_message() {
     1742int FWScript::o1_message() {
    14321743        byte param1 = getNextByte();
    14331744        uint16 param2 = getNextWord();
    14341745        uint16 param3 = getNextWord();
    14351746        uint16 param4 = getNextWord();
    14361747        uint16 param5 = getNextWord();
    14371748
    1438         debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5);
     1749        debugC(5, kCineDebugScript, "Line: %d: message(%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5);
    14391750
    14401751        addMessage(param1, param2, param3, param4, param5);
     1752        return 0;
    14411753}
    14421754
    1443 void o1_loadGlobalVar() {
     1755int FWScript::o1_loadGlobalVar() {
    14441756        byte varIdx = getNextByte();
    14451757        byte varType = getNextByte();
    14461758
     
    14481760                byte dataIdx = getNextByte();
    14491761
    14501762                if (varType == 1) {
    1451                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _currentLine, varIdx, dataIdx);
    1452                         globalVars[varIdx] = _currentScriptElement->localVars[dataIdx];
     1763                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = var[%d]", _line, varIdx, dataIdx);
     1764                        _globalVars[varIdx] = _localVars[dataIdx];
    14531765                } else {
    1454                         debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _currentLine, varIdx, dataIdx);
    1455                         globalVars[varIdx] = globalVars[dataIdx];
     1766                        debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = globalVars[%d]", _line, varIdx, dataIdx);
     1767                        _globalVars[varIdx] = _globalVars[dataIdx];
    14561768                }
    14571769        } else {
    14581770                uint16 value = getNextWord();
    14591771
    1460                 debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _currentLine, varIdx, value);
    1461                 globalVars[varIdx] = value;
     1772                debugC(5, kCineDebugScript, "Line: %d: globalVars[%d] = %d", _line, varIdx, value);
     1773                _globalVars[varIdx] = value;
    14621774        }
     1775
     1776        return 0;
    14631777}
    14641778
    1465 void o1_compareGlobalVar() {
     1779int FWScript::o1_compareGlobalVar() {
    14661780        byte varIdx = getNextByte();
    14671781        byte varType = getNextByte();
    14681782
    14691783        if (varType) {
    14701784                byte value = getNextByte();
    14711785
    1472                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _currentLine, varIdx, value);
    1473                 _currentScriptElement->compareResult = compareVars(globalVars[varIdx], _currentScriptElement->localVars[value]);
     1786                if (varType == 1) {
     1787                        debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and var[%d]", _line, varIdx, value);
     1788                        _compare = compareVars(_globalVars[varIdx], _localVars[value]);
     1789                } else {
     1790                        debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and globalVars[%d]", _line, varIdx, value);
     1791                        _compare = compareVars(_globalVars[varIdx], _globalVars[value]);
     1792                }
    14741793        } else {
    14751794                uint16 value = getNextWord();
    14761795
    1477                 debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _currentLine, varIdx, value);
     1796                debugC(5, kCineDebugScript, "Line: %d: compare globalVars[%d] and %d", _line, varIdx, value);
    14781797
    14791798                if (varIdx == 255 && (g_cine->getGameType() == Cine::GType_FW)) {       // TODO: fix
    1480                         _currentScriptElement->compareResult = 1;
     1799                        _compare = 1;
    14811800                } else {
    1482                         _currentScriptElement->compareResult = compareVars(globalVars[varIdx], value);
     1801                        _compare = compareVars(_globalVars[varIdx], value);
    14831802                }
    14841803        }
     1804
     1805        return 0;
    14851806}
    14861807
    1487 void o1_declareFunctionName() {
     1808int FWScript::o1_declareFunctionName() {
    14881809        const char *param = getNextString();
    14891810
    1490         debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _currentLine, param);
     1811        debugC(5, kCineDebugScript, "Line: %d: comment(%s)", _line, param);
     1812        return 0;
    14911813}
    14921814
    1493 void o1_freePartRange() {
     1815int FWScript::o1_freePartRange() {
    14941816        byte startIdx = getNextByte();
    14951817        byte numIdx = getNextByte();
    14961818
    14971819        assert(startIdx + numIdx <= NUM_MAX_ANIMDATA);
    14981820
    1499         debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _currentLine, startIdx, numIdx);
     1821        debugC(5, kCineDebugScript, "Line: %d: freePartRange(%d,%d)", _line, startIdx, numIdx);
    15001822        freeAnimDataRange(startIdx, numIdx);
     1823        return 0;
    15011824}
    15021825
    1503 void o1_unloadAllMasks() {
    1504         debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _currentLine);
     1826int FWScript::o1_unloadAllMasks() {
     1827        debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
    15051828        unloadAllMasks();
     1829        return 0;
    15061830}
    15071831
    1508 void o1_setScreenDimensions() {
    1509         warning("STUB: o1_setScreenDimensions()");
    1510         getNextWord();
    1511         getNextWord();
    1512         getNextWord();
    1513         getNextWord();
     1832/*! \todo Implement this instruction
     1833 */
     1834int FWScript::o1_setScreenDimensions() {
     1835        uint16 a = getNextWord();
     1836        uint16 b = getNextWord();
     1837        uint16 c = getNextWord();
     1838        uint16 d = getNextWord();
     1839        warning("STUB: o1_setScreenDimensions(%x, %x, %x, %x)", a, b, c, d);
    15141840        // setupScreenParam
     1841        return 0;
    15151842}
    15161843
    1517 void o1_displayBackground() {
     1844/*! \todo Implement this instruction
     1845 */
     1846int FWScript::o1_displayBackground() {
    15181847        warning("STUB: o1_displayBackground()");
     1848        return 0;
    15191849}
    15201850
    1521 void o1_initializeZoneData() {
    1522         debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _currentLine);
     1851int FWScript::o1_initializeZoneData() {
     1852        debugC(5, kCineDebugScript, "Line: %d: initializeZoneData()", _line);
    15231853
    15241854        for (int i = 0; i < NUM_MAX_ZONE; i++) {
    15251855                zoneData[i] = i;
    15261856        }
     1857        return 0;
    15271858}
    15281859
    1529 void o1_setZoneDataEntry() {
     1860int FWScript::o1_setZoneDataEntry() {
    15301861        byte zoneIdx = getNextByte();
    15311862        uint16 var = getNextWord();
    15321863
    1533         debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _currentLine, zoneIdx, var);
     1864        debugC(5, kCineDebugScript, "Line: %d: setZone[%d] = %d", _line, zoneIdx, var);
    15341865        zoneData[zoneIdx] = var;
     1866        return 0;
    15351867}
    15361868
    1537 void o1_getZoneDataEntry() {
     1869int FWScript::o1_getZoneDataEntry() {
    15381870        byte zoneIdx = getNextByte();
    15391871        byte var = getNextByte();
    15401872
    1541         _currentScriptElement->localVars[var] = zoneData[zoneIdx];
     1873        _localVars[var] = zoneData[zoneIdx];
     1874        return 0;
    15421875}
    15431876
    1544 void o1_setDefaultMenuColor() {
     1877int FWScript::o1_setDefaultMenuColor() {
    15451878        byte param = getNextByte();
    15461879
    1547         debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _currentLine, param);
     1880        debugC(5, kCineDebugScript, "Line: %d: setDefaultMenuColor(%d)", _line, param);
    15481881        defaultMenuBoxColor = param;
     1882        return 0;
    15491883}
    15501884
    1551 void o1_allowPlayerInput() {
    1552         debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _currentLine);
     1885int FWScript::o1_allowPlayerInput() {
     1886        debugC(5, kCineDebugScript, "Line: %d: allowPlayerInput()", _line);
    15531887        allowPlayerInput = 1;
     1888        return 0;
    15541889}
    15551890
    1556 void o1_disallowPlayerInput() {
    1557         debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _currentLine);
     1891int FWScript::o1_disallowPlayerInput() {
     1892        debugC(5, kCineDebugScript, "Line: %d: dissallowPlayerInput()", _line);
    15581893        allowPlayerInput = 0;
     1894        return 0;
    15591895}
    15601896
    1561 void o1_changeDataDisk() {
     1897int FWScript::o1_changeDataDisk() {
    15621898        byte newDisk = getNextByte();
    15631899
    1564         debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _currentLine, newDisk);
     1900        debugC(5, kCineDebugScript, "Line: %d: changeDataDisk(%d)", _line, newDisk);
    15651901        checkDataDisk(newDisk);
     1902        return 0;
    15661903}
    15671904
    1568 void o1_loadMusic() {
     1905int FWScript::o1_loadMusic() {
    15691906        const char *param = getNextString();
    15701907
    1571         debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param);
     1908        debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _line, param);
    15721909        g_sound->loadMusic(param);
     1910        return 0;
    15731911}
    15741912
    1575 void o1_playMusic() {
    1576         debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
     1913int FWScript::o1_playMusic() {
     1914        debugC(5, kCineDebugScript, "Line: %d: playMusic()", _line);
    15771915        g_sound->playMusic();
     1916        return 0;
    15781917}
    15791918
    1580 void o1_fadeOutMusic() {
    1581         debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
     1919int FWScript::o1_fadeOutMusic() {
     1920        debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _line);
    15821921        g_sound->fadeOutMusic();
     1922        return 0;
    15831923}
    15841924
    1585 void o1_stopSample() {
    1586         debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
     1925int FWScript::o1_stopSample() {
     1926        debugC(5, kCineDebugScript, "Line: %d: stopSample()", _line);
    15871927        g_sound->stopMusic();
     1928        return 0;
    15881929}
    15891930
    1590 void o1_op71() {
    1591         warning("STUB: o1_op71()");
    1592         getNextByte();
    1593         getNextWord();
     1931/*! \todo Implement this instruction
     1932 */
     1933int FWScript::o1_op71() {
     1934        byte a = getNextByte();
     1935        uint16 b = getNextWord();
     1936        warning("STUB: o1_op71(%x, %x)", a, b);
     1937        return 0;
    15941938}
    15951939
    1596 void o1_op72() {
    1597         warning("STUB: o1_op72()");
    1598         getNextWord();
    1599         getNextByte();
    1600         getNextWord();
     1940/*! \todo Implement this instruction
     1941 */
     1942int FWScript::o1_op72() {
     1943        uint16 a = getNextWord();
     1944        byte b = getNextByte();
     1945        uint16 c = getNextWord();
     1946        warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
     1947        return 0;
    16011948}
    16021949
    1603 void o1_op73() {
     1950/*! \todo Implement this instruction
     1951 */
     1952int FWScript::o1_op73() {
    16041953        // I believe this opcode is identical to o1_op72(). In fact, Operation
    16051954        // Stealth doesn't even have it. It uses o1_op72() instead.
    1606         warning("STUB: o1_op73()");
    1607         getNextWord();
    1608         getNextByte();
    1609         getNextWord();
     1955        uint16 a = getNextWord();
     1956        byte b = getNextByte();
     1957        uint16 c = getNextWord();
     1958        warning("STUB: o1_op72(%x, %x, %x)", a, b, c);
     1959        return 0;
    16101960}
    16111961
    1612 void o1_playSample() {
    1613         debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
     1962int FWScript::o1_playSample() {
     1963        debugC(5, kCineDebugScript, "Line: %d: playSample()", _line);
    16141964
    16151965        byte anim = getNextByte();
    16161966        byte channel = getNextByte();
     
    16211971        int16 volume = getNextWord();
    16221972        uint16 size = getNextWord();
    16231973
    1624         if (!animDataTable[anim].ptr1) {
    1625                 return;
     1974        const byte *data = animDataTable[anim].data();
     1975
     1976        if (!data) {
     1977                return 0;
    16261978        }
    16271979
    16281980        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    16291981                if (size == 0xFFFF) {
    1630                         size = animDataTable[anim].width * animDataTable[anim].height;
     1982                        size = animDataTable[anim]._width * animDataTable[anim]._height;
    16311983                }
    16321984                if (channel < 10) { // || _currentOpcode == 0x78
    16331985                        int channel1, channel2;
     
    16381990                                channel1 = 2;
    16391991                                channel2 = 3;
    16401992                        }
    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);
     1993                        g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
     1994                        g_sound->playSound(channel2, freq, data, size,  1, volume,  0, repeat);
    16431995                } else {
    16441996                        channel -= 10;
    16451997                        if (volume > 63) {
    16461998                                volume = 63;
    16471999                        }
    1648                         g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat);
     2000                        g_sound->playSound(channel, freq, data, size, 0, 0, volume, repeat);
    16492001                }
    16502002        } else {
    16512003                if (volume > 63 || volume < 0) {
     
    16582010                        volume = 50;
    16592011                }
    16602012                if (g_cine->getGameType() == Cine::GType_OS && size == 0) {
    1661                         return;
     2013                        return 0;
    16622014                }
    16632015                g_sound->stopMusic();
    16642016                if (size == 0xFFFF) {
    1665                         g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0);
     2017                        g_sound->playSound(channel, 0, data, 0, 0, 0, volume, 0);
    16662018                } else {
    16672019                        g_sound->stopSound(channel);
    16682020                }
    16692021        }
     2022        return 0;
    16702023}
    16712024
    1672 void o1_disableSystemMenu() {
     2025int FWScript::o1_disableSystemMenu() {
    16732026        byte param = getNextByte();
    16742027
    1675         debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _currentLine, param);
     2028        debugC(5, kCineDebugScript, "Line: %d: disableSystemMenu(%d)", _line, param);
    16762029        disableSystemMenu = (param != 0);
     2030        return 0;
    16772031}
    16782032
    1679 void o1_loadMask5() {
     2033int FWScript::o1_loadMask5() {
    16802034        byte param = getNextByte();
    16812035
    1682         debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _currentLine, param);
     2036        debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
    16832037        loadOverlayElement(param, 5);
     2038        return 0;
    16842039}
    16852040
    1686 void o1_unloadMask5() {
     2041int FWScript::o1_unloadMask5() {
    16872042        byte param = getNextByte();
    16882043
    1689         debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _currentLine, param);
     2044        debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
    16902045        freeOverlay(param, 5);
     2046        return 0;
    16912047}
    16922048
    16932049// ------------------------------------------------------------------------
    16942050// OPERATION STEALTH opcodes
    16952051// ------------------------------------------------------------------------
    16962052
    1697 void o2_loadPart() {
     2053int FWScript::o2_loadPart() {
    16982054        const char *param = getNextString();
    16992055
    1700         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
     2056        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
     2057        return 0;
    17012058}
    17022059
    1703 void o2_playSample() {
     2060int FWScript::o2_playSample() {
    17042061        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    17052062                // no-op in these versions
    17062063                getNextByte();
     
    17092066                getNextByte();
    17102067                getNextWord();
    17112068                getNextWord();
    1712                 return;
     2069                return 0;
    17132070        }
    1714         o1_playSample();
     2071        return o1_playSample();
    17152072}
    17162073
    1717 void o2_playSampleAlt() {
     2074int FWScript::o2_playSampleAlt() {
    17182075        byte num = getNextByte();
    17192076        byte channel = getNextByte();
    17202077        uint16 frequency = getNextWord();
     
    17232080        uint16 size = getNextWord();
    17242081
    17252082        if (size == 0xFFFF) {
    1726                 size = animDataTable[num].width * animDataTable[num].height;
     2083                size = animDataTable[num]._width * animDataTable[num]._height;
    17272084        }
    1728         if (animDataTable[num].ptr1) {
     2085        if (animDataTable[num].data()) {
    17292086                if (g_cine->getPlatform() == Common::kPlatformPC) {
    17302087                        // if speaker output is available, play sound on it
    17312088                        // if it's another device, don't play anything
    17322089                        // TODO: implement this, it's used in the introduction for example
    17332090                        // on each letter displayed
    17342091                } else {
    1735                         g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0);
     2092                        g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
    17362093                }
    17372094        }
     2095        return 0;
    17382096}
    17392097
    1740 void o2_addSeqListElement() {
     2098int FWScript::o2_addSeqListElement() {
    17412099        byte param1 = getNextByte();
    17422100        byte param2 = getNextByte();
    17432101        byte param3 = getNextByte();
     
    17462104        uint16 param6 = getNextWord();
    17472105        uint16 param7 = getNextWord();
    17482106
    1749         debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _currentLine, param1, param2, param3, param4, param5, param6, param7);
     2107        debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
    17502108        addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
     2109        return 0;
    17512110}
    17522111
    1753 void o2_removeSeq() {
     2112int FWScript::o2_removeSeq() {
    17542113        byte a = getNextByte();
    17552114        byte b = getNextByte();
    17562115
    1757         debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _currentLine, a, b);
     2116        debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
    17582117        removeSeq(a, 0, b);
     2118        return 0;
    17592119}
    17602120
    1761 void o2_op81() {
     2121/*! \todo Implement this instruction
     2122 */
     2123int FWScript::o2_op81() {
    17622124        warning("STUB: o2_op81()");
    17632125        // freeUnkList();
     2126        return 0;
    17642127}
    17652128
    1766 void o2_op82() {
    1767         warning("STUB: o2_op82()");
    1768         getNextByte();
    1769         getNextByte();
    1770         getNextWord();
     2129/*! \todo Implement this instruction
     2130 */
     2131int FWScript::o2_op82() {
     2132        byte a = getNextByte();
     2133        byte b = getNextByte();
     2134        uint16 c = getNextWord();
     2135        warning("STUB: o2_op82(%x, %x, %x)", a, b, c);
     2136        return 0;
    17712137}
    17722138
    1773 void o2_isSeqRunning() {
     2139int FWScript::o2_isSeqRunning() {
    17742140        byte a = getNextByte();
    17752141        byte b = getNextByte();
    17762142
    1777         debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _currentLine, a, b);
     2143        debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
    17782144
    17792145        if (isSeqRunning(a, 0, b)) {
    1780                 _currentScriptElement->compareResult = 1;
     2146                _compare = 1;
    17812147        } else {
    1782                 _currentScriptElement->compareResult = 0;
     2148                _compare = 0;
    17832149        }
     2150        return 0;
    17842151}
    17852152
    1786 void o2_gotoIfSupNearest() {
     2153/*! \todo The assert may produce false positives and requires testing
     2154 */
     2155int FWScript::o2_gotoIfSupNearest() {
    17872156        byte labelIdx = getNextByte();
    17882157
    1789         if (_currentScriptElement->compareResult == kCmpGT) {
    1790                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2158        if (_compare == kCmpGT) {
     2159                assert(_labels[labelIdx] != -1);
    17912160
    1792                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _currentLine, labelIdx);
    1793                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2161                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
     2162                _pos = _script.getLabel(*_info, labelIdx, _pos);
    17942163        } else {
    1795                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _currentLine, labelIdx);
     2164                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
    17962165        }
     2166        return 0;
    17972167}
    17982168
    1799 void o2_gotoIfSupEquNearest() {
     2169/*! \todo The assert may produce false positives and requires testing
     2170 */
     2171int FWScript::o2_gotoIfSupEquNearest() {
    18002172        byte labelIdx = getNextByte();
    18012173
    1802         if (_currentScriptElement->compareResult & (kCmpGT | kCmpEQ)) {
    1803                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2174        if (_compare & (kCmpGT | kCmpEQ)) {
     2175                assert(_labels[labelIdx] != -1);
    18042176
    1805                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _currentLine, labelIdx);
    1806                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2177                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
     2178                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18072179        } else {
    1808                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _currentLine, labelIdx);
     2180                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
    18092181        }
     2182        return 0;
    18102183}
    18112184
    1812 void o2_gotoIfInfNearest() {
     2185/*! \todo The assert may produce false positives and requires testing
     2186 */
     2187int FWScript::o2_gotoIfInfNearest() {
    18132188        byte labelIdx = getNextByte();
    18142189
    1815         if (_currentScriptElement->compareResult == kCmpLT) {
    1816                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2190        if (_compare == kCmpLT) {
     2191                assert(_labels[labelIdx] != -1);
    18172192
    1818                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _currentLine, labelIdx);
    1819                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2193                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
     2194                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18202195        } else {
    1821                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _currentLine, labelIdx);
     2196                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
    18222197        }
     2198        return 0;
    18232199}
    18242200
    1825 void o2_gotoIfInfEquNearest() {
     2201/*! \todo The assert may produce false positives and requires testing
     2202 */
     2203int FWScript::o2_gotoIfInfEquNearest() {
    18262204        byte labelIdx = getNextByte();
    18272205
    1828         if (_currentScriptElement->compareResult & (kCmpLT | kCmpEQ)) {
    1829                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2206        if (_compare & (kCmpLT | kCmpEQ)) {
     2207                assert(_labels[labelIdx] != -1);
    18302208
    1831                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _currentLine, labelIdx);
    1832                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2209                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
     2210                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18332211        } else {
    1834                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _currentLine, labelIdx);
     2212                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
    18352213        }
     2214        return 0;
    18362215}
    18372216
    1838 void o2_gotoIfEquNearest() {
     2217/*! \todo The assert may produce false positives and requires testing
     2218 */
     2219int FWScript::o2_gotoIfEquNearest() {
    18392220        byte labelIdx = getNextByte();
    18402221
    1841         if (_currentScriptElement->compareResult == kCmpEQ) {
    1842                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2222        if (_compare == kCmpEQ) {
     2223                assert(_labels[labelIdx] != -1);
    18432224
    1844                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _currentLine, labelIdx);
    1845                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2225                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
     2226                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18462227        } else {
    1847                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _currentLine, labelIdx);
     2228                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
    18482229        }
     2230        return 0;
    18492231}
    18502232
    1851 void o2_gotoIfDiffNearest() {
     2233/*! \todo The assert may produce false positives and requires testing
     2234 */
     2235int FWScript::o2_gotoIfDiffNearest() {
    18522236        byte labelIdx = getNextByte();
    18532237
    1854         if (_currentScriptElement->compareResult != kCmpEQ) {
    1855                 assert(_currentScriptElement->stack[labelIdx] != -1);
     2238        if (_compare != kCmpEQ) {
     2239                assert(_labels[labelIdx] != -1);
    18562240
    1857                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _currentLine, labelIdx);
    1858                 _currentPosition = computeScriptStackFromScript(_currentScriptElement->scriptPtr, _currentPosition, labelIdx, scriptTable[_currentScriptElement->scriptIdx].size);
     2241                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
     2242                _pos = _script.getLabel(*_info, labelIdx, _pos);
    18592243        } else {
    1860                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _currentLine, labelIdx);
     2244                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
    18612245        }
     2246        return 0;
    18622247}
    18632248
    1864 void o2_startObjectScript() {
     2249int FWScript::o2_startObjectScript() {
    18652250        byte param = getNextByte();
    18662251
    1867         debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _currentLine, param);
     2252        debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
    18682253        runObjectScript(param);
     2254        return 0;
    18692255}
    18702256
    1871 void o2_stopObjectScript() {
     2257int FWScript::o2_stopObjectScript() {
    18722258        byte param = getNextByte();
    18732259
    1874         debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _currentLine, param);
    1875         stopObjectScript(param);
     2260        debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
     2261        ScriptList::iterator it = objectScripts.begin();
     2262
     2263        for (; it != objectScripts.end(); ++it) {
     2264                if ((*it)->_index == param) {
     2265                        (*it)->_index = -1;
     2266                }
     2267        }
     2268        return 0;
    18762269}
    18772270
    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();
     2271/*! \todo Implement this instruction
     2272 */
     2273int FWScript::o2_op8D() {
     2274        uint16 a = getNextWord();
     2275        uint16 b = getNextWord();
     2276        uint16 c = getNextWord();
     2277        uint16 d = getNextWord();
     2278        uint16 e = getNextWord();
     2279        uint16 f = getNextWord();
     2280        uint16 g = getNextWord();
     2281        uint16 h = getNextWord();
     2282        warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
    18882283        // _currentScriptElement->compareResult = ...
     2284        return 0;
    18892285}
    18902286
    1891 void o2_addBackground() {
     2287int FWScript::o2_addBackground() {
    18922288        byte param1 = getNextByte();
    18932289        const char *param2 = getNextString();
    18942290
    1895         debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _currentLine, param2, param1);
     2291        debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
    18962292        addBackground(param2, param1);
     2293        return 0;
    18972294}
    18982295
    1899 void o2_removeBackground() {
     2296int FWScript::o2_removeBackground() {
    19002297        byte param = getNextByte();
    19012298
    19022299        assert(param);
    19032300
    1904         debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _currentLine, param);
     2301        debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
    19052302
    19062303        if (additionalBgTable[param]) {
    19072304                free(additionalBgTable[param]);
     
    19172314        }
    19182315
    19192316        strcpy(currentBgName[param], "");
     2317        return 0;
    19202318}
    19212319
    1922 void o2_loadAbs() {
     2320int FWScript::o2_loadAbs() {
    19232321        byte param1 = getNextByte();
    19242322        const char *param2 = getNextString();
    19252323
    1926         debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _currentLine, param1, param2);
     2324        debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
    19272325        loadAbs(param2, param1);
     2326        return 0;
    19282327}
    19292328
    1930 void o2_loadBg() {
     2329int FWScript::o2_loadBg() {
    19312330        byte param = getNextByte();
    19322331
    19332332        assert(param <= 8);
    19342333
    1935         debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _currentLine, param);
     2334        debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
    19362335
    19372336        if (additionalBgTable[param]) {
    19382337                currentAdditionalBgIdx = param;
     2338                if (param == 8) {
     2339                        newColorMode = 3;
     2340                } else {
     2341                        newColorMode = bgColorMode + 1;
     2342                }
    19392343                //if (_screenNeedFadeOut == 0) {
    19402344                //      adBgVar1 = 1;
    19412345                //}
    19422346                fadeRequired = true;
    19432347        }
     2348        return 0;
    19442349}
    19452350
    1946 void o2_wasZoneChecked() {
     2351/*! \todo Implement this instruction
     2352 */
     2353int FWScript::o2_wasZoneChecked() {
    19472354        warning("STUB: o2_wasZoneChecked()");
     2355        return 0;
    19482356}
    19492357
    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();
     2358/*! \todo Implement this instruction
     2359 */
     2360int FWScript::o2_op9B() {
     2361        uint16 a = getNextWord();
     2362        uint16 b = getNextWord();
     2363        uint16 c = getNextWord();
     2364        uint16 d = getNextWord();
     2365        uint16 e = getNextWord();
     2366        uint16 f = getNextWord();
     2367        uint16 g = getNextWord();
     2368        uint16 h = getNextWord();
     2369        warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
     2370        return 0;
    19602371}
    19612372
    1962 void o2_op9C() {
    1963         warning("STUB: o2_op9C()");
    1964         getNextWord();
    1965         getNextWord();
    1966         getNextWord();
    1967         getNextWord();
     2373/*! \todo Implement this instruction
     2374 */
     2375int FWScript::o2_op9C() {
     2376        uint16 a = getNextWord();
     2377        uint16 b = getNextWord();
     2378        uint16 c = getNextWord();
     2379        uint16 d = getNextWord();
     2380        warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
     2381        return 0;
    19682382}
    19692383
    1970 void o2_useBgScroll() {
     2384int FWScript::o2_useBgScroll() {
    19712385        byte param = getNextByte();
    19722386
    19732387        assert(param <= 8);
    19742388
    1975         debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _currentLine, param);
     2389        debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
    19762390
    19772391        if (additionalBgTable[param]) {
    19782392                currentAdditionalBgIdx2 = param;
    19792393        }
     2394        return 0;
    19802395}
    19812396
    1982 void o2_setAdditionalBgVScroll() {
     2397int FWScript::o2_setAdditionalBgVScroll() {
    19832398        byte param1 = getNextByte();
    19842399
    19852400        if (param1) {
    19862401                byte param2 = getNextByte();
    19872402
    1988                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _currentLine, param2);
    1989                 additionalBgVScroll = _currentScriptElement->localVars[param2];
     2403                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
     2404                additionalBgVScroll = _localVars[param2];
    19902405        } else {
    19912406                uint16 param2 = getNextWord();
    19922407
    1993                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _currentLine, param2);
     2408                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
    19942409                additionalBgVScroll = param2;
    19952410        }
     2411        return 0;
    19962412}
    19972413
    1998 void o2_op9F() {
     2414/*! \todo Implement this instruction
     2415 */
     2416int FWScript::o2_op9F() {
    19992417        warning("o2_op9F()");
    20002418        getNextWord();
    20012419        getNextWord();
     2420        return 0;
    20022421}
    20032422
    2004 void o2_addGfxElementA0() {
     2423int FWScript::o2_addGfxElementA0() {
    20052424        uint16 param1 = getNextWord();
    20062425        uint16 param2 = getNextWord();
    20072426
    2008         debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _currentLine, param1, param2);
     2427        debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
    20092428        addGfxElementA0(param1, param2);
     2429        return 0;
    20102430}
    20112431
    2012 void o2_opA1() {
    2013         warning("STUB: o2_opA1()");
    2014         getNextWord();
    2015         getNextWord();
    2016         // removeGfxElementA0( ... );
     2432/*! \todo Implement this instruction
     2433 */
     2434int FWScript::o2_removeGfxElementA0() {
     2435        uint16 idx = getNextWord();
     2436        uint16 param = getNextWord();
     2437        warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param);
     2438        removeGfxElementA0(idx, param);
     2439        return 0;
    20172440}
    20182441
    2019 void o2_opA2() {
    2020         warning("STUB: o2_opA2()");
    2021         getNextWord();
    2022         getNextWord();
     2442/*! \todo Implement this instruction
     2443 */
     2444int FWScript::o2_opA2() {
     2445        uint16 a = getNextWord();
     2446        uint16 b = getNextWord();
     2447        warning("STUB: o2_opA2(%x, %x)", a, b);
    20232448        // addGfxElementA2();
     2449        return 0;
    20242450}
    20252451
    2026 void o2_opA3() {
    2027         warning("STUB: o2_opA3()");
    2028         getNextWord();
    2029         getNextWord();
     2452/*! \todo Implement this instruction
     2453 */
     2454int FWScript::o2_opA3() {
     2455        uint16 a = getNextWord();
     2456        uint16 b = getNextWord();
     2457        warning("STUB: o2_opA3(%x, %x)", a, b);
    20302458        // removeGfxElementA2();
     2459        return 0;
    20312460}
    20322461
    2033 void o2_loadMask22() {
     2462int FWScript::o2_loadMask22() {
    20342463        byte param = getNextByte();
    20352464
    2036         debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _currentLine, param);
     2465        debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
    20372466        loadOverlayElement(param, 22);
     2467        return 0;
    20382468}
    20392469
    2040 void o2_unloadMask22() {
     2470int FWScript::o2_unloadMask22() {
    20412471        byte param = getNextByte();
    20422472
    2043         debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _currentLine, param);
     2473        debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
    20442474        freeOverlay(param, 22);
     2475        return 0;
    20452476}
    20462477
    2047 // ------------------------------------------------------------------------
     2478//-----------------------------------------------------------------------
    20482479
    2049 void executeScript(prcLinkedListStruct *scriptElement, uint16 params) {
    2050         assert(scriptElement);
     2480void addGfxElementA0(int16 param1, int16 param2) {
     2481        overlayHeadElement *currentHead = &overlayHead;
     2482        overlayHeadElement *tempHead = currentHead;
     2483        overlayHeadElement *newElement;
    20512484
    2052         if (scriptElement->scriptIdx == -1) {
     2485        currentHead = tempHead->next;
     2486
     2487        while (currentHead) {
     2488                if (objectTable[currentHead->objIdx].mask == objectTable[param1].mask) {
     2489                        if (currentHead->type == 2 || currentHead->objIdx == 3) {
     2490                                break;
     2491                        }
     2492                }
     2493
     2494                tempHead = currentHead;
     2495                currentHead = currentHead->next;
     2496        }
     2497
     2498        if (currentHead && currentHead->objIdx == param1 && currentHead->type == 20 && currentHead->x == param2)
    20532499                return;
     2500
     2501        newElement = new overlayHeadElement;
     2502
     2503        newElement->next = tempHead->next;
     2504        tempHead->next = newElement;
     2505
     2506        newElement->objIdx = param1;
     2507        newElement->type = 20;
     2508
     2509        newElement->x = param2;
     2510        newElement->y = 0;
     2511        newElement->width = 0;
     2512        newElement->color = 0;
     2513
     2514        if (!currentHead)
     2515                currentHead = &overlayHead;
     2516
     2517        newElement->previous = currentHead->previous;
     2518
     2519        currentHead->previous = newElement;
     2520}
     2521
     2522/*! \todo Check that it works
     2523 */
     2524void removeGfxElementA0(int16 idx, int16 param) {
     2525        overlayHeadElement *parent = &overlayHead;
     2526        overlayHeadElement *head = overlayHead.next;
     2527        overlayHeadElement *tmp;
     2528
     2529        while (head) {
     2530                if (head->objIdx == idx && head->x == param) {
     2531                        parent->next = head->next;
     2532                        tmp = head->next ? head->next : &overlayHead;
     2533                        tmp->previous = parent;
     2534                        delete head;
     2535                        return;
     2536                }
     2537
     2538                parent = head;
     2539                head = head->next;
    20542540        }
     2541}
    20552542
    2056         assert(scriptElement->scriptPtr);
     2543void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
     2544        SeqListElement *currentHead = &seqList;
     2545        SeqListElement *tempHead = currentHead;
    20572546
    2058         _currentScriptElement = scriptElement;
    2059         _currentScriptParams = params;
    2060         _currentScriptPtr = scriptElement->scriptPtr;
    2061         _currentPosition = scriptElement->scriptPosition;
     2547        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2548                tempHead = currentHead;
     2549                currentHead = tempHead->next;
     2550        }
    20622551
    2063         _closeScript = 0;
     2552        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2553                currentHead->var4 = -1;
     2554        }
     2555}
    20642556
    2065         while (!_closeScript) {
    2066                 _currentLine = _currentPosition;
     2557uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
     2558        SeqListElement *currentHead = &seqList;
     2559        SeqListElement *tempHead = currentHead;
    20672560
    2068                 byte opcode = getNextByte();
     2561        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2562                tempHead = currentHead;
     2563                currentHead = tempHead->next;
     2564        }
    20692565
    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);
     2566        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2567                return 1;
     2568        }
     2569
     2570        return 0;
     2571}
     2572
     2573void palRotate(byte a, byte b, byte c) {
     2574        if (c == 1) {
     2575                uint16 currentColor = c_palette[b];
     2576
     2577                for (int16 i = b; i > a; i--) {
     2578                        c_palette[i] = c_palette[i - 1];
    20752579                }
     2580
     2581                c_palette[a] = currentColor;
    20762582        }
    20772583}
    20782584
    2079 void executeList1(void) {
    2080         prcLinkedListStruct *currentHead = objScriptList.next;
     2585void addScriptToList0(uint16 idx) {
     2586        ScriptPtr tmp(scriptInfo->create(*scriptTable[idx], idx));
     2587        assert(tmp);
     2588        globalScripts.push_back(tmp);
     2589}
    20812590
    2082         while (currentHead) {
    2083                 prcLinkedListStruct *tempHead;
     2591int16 getZoneFromPosition(byte *page, int16 x, int16 y, int16 width) {
     2592        byte *ptr = page + (y * width) + x / 2;
     2593        byte zoneVar;
    20842594
    2085                 tempHead = currentHead->next;
     2595        if (!(x % 2)) {
     2596                zoneVar = (*(ptr) >> 4) & 0xF;
     2597        } else {
     2598                zoneVar = (*(ptr)) & 0xF;
     2599        }
    20862600
    2087                 executeScript(currentHead, 1);
     2601        return zoneVar;
     2602}
    20882603
    2089                 currentHead = tempHead;
     2604int16 getZoneFromPositionRaw(byte *page, int16 x, int16 y, int16 width) {
     2605        byte *ptr = page + (y * width) + x;
     2606        byte zoneVar;
     2607
     2608        zoneVar = (*(ptr)) & 0xF;
     2609
     2610        return zoneVar;
     2611}
     2612
     2613int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx) {
     2614        int16 lx = objectTable[objIdx].x + x;
     2615        int16 ly = objectTable[objIdx].y + y;
     2616        int16 idx;
     2617
     2618        for (int16 i = 0; i < numZones; i++) {
     2619                idx = getZoneFromPositionRaw(page3Raw, lx + i, ly, 320);
     2620
     2621                assert(idx >= 0 && idx <= NUM_MAX_ZONE);
     2622
     2623                if (zoneData[idx] == zoneIdx) {
     2624                        return 1;
     2625                }
    20902626        }
     2627
     2628        return 0;
    20912629}
    20922630
    2093 void executeList0(void) {
    2094         prcLinkedListStruct *currentHead = globalScriptsHead.next;
     2631uint16 compareVars(int16 a, int16 b) {
     2632        uint16 flag = 0;
    20952633
    2096         while (currentHead) {
    2097                 prcLinkedListStruct *tempHead;
     2634        if (a == b) {
     2635                flag |= kCmpEQ;
     2636        } else if (a > b) {
     2637                flag |= kCmpGT;
     2638        } else if (a < b) {
     2639                flag |= kCmpLT;
     2640        }
    20982641
    2099                 executeScript(currentHead, 0);
     2642        return flag;
     2643}
    21002644
    2101                 tempHead = currentHead->next;
    2102                 currentHead = tempHead;
     2645void executeList1(void) {
     2646        ScriptList::iterator it = objectScripts.begin();
     2647        for (; it != objectScripts.end();) {
     2648                if ((*it)->_index < 0 || (*it)->execute() < 0) {
     2649                        it = objectScripts.erase(it);
     2650                } else {
     2651                        ++it;
     2652                }
    21032653        }
    21042654}
    21052655
     2656void executeList0(void) {
     2657        ScriptList::iterator it = globalScripts.begin();
     2658        for (; it != globalScripts.end();) {
     2659                if ((*it)->_index < 0 || (*it)->execute() < 0) {
     2660                        it = globalScripts.erase(it);
     2661                } else {
     2662                        ++it;
     2663                }
     2664        }
     2665}
     2666
     2667/*! \todo objectScripts.clear()?
     2668 */
    21062669void purgeList1(void) {
    21072670}
    21082671
     
    24633026                        }
    24643027                case 0x1B:
    24653028                        {
    2466                                 sprintf(lineBuffer, "freeBgIncrustList()\n");
     3029                                sprintf(lineBuffer, "bgIncrustList.clear()\n");
    24673030                                break;
    24683031                        }
    24693032                case 0x1D:
     
    28043367                                sprintf(lineBuffer, "disallowPlayerInput()\n");
    28053368                                break;
    28063369                        }
    2807                 case OP_changeDataDisk:
     3370                case 0x6B:
    28083371                        {
    28093372                                byte newDisk;
    28103373
     
    28783441
    28793442                                if (opcode - 1 == 0x77) {
    28803443                                        sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    2881                                 else if (opcode - 1 == 0x78) {
     3444                                } else if (opcode - 1 == 0x78) {
    28823445                                        sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
    28833446                                }
    28843447
  • engines/cine/part.cpp

     
    3333
    3434uint16 numElementInPart;
    3535
    36 AnimData *animDataTable;
    3736PartBuffer *partBuffer;
    3837
    3938void loadPart(const char *partName) {
  • engines/cine/object.cpp

     
    231231                objectTable[objIdx].frame = newValue;
    232232                break;
    233233        case 4:
    234                 if (newValue == -1) {
     234                // is it really in Future Wars? it breaks the newspaper machine
     235                // on the airport in Operation Stealth
     236                if (newValue == -1 && g_cine->getGameType() != Cine::GType_OS) {
    235237                        objectTable[objIdx].costume = globalVars[0];
    236238                } else {
    237239                        objectTable[objIdx].costume = newValue;
     
    243245        }
    244246}
    245247
    246 byte compareObjectParam(byte objIdx, byte type, int16 value) {
    247         byte compareResult = 0;
     248uint16 compareObjectParam(byte objIdx, byte type, int16 value) {
     249        uint16 compareResult = 0;
    248250        int16 objectParam = getObjectParam(objIdx, type);
    249251
    250252        if (objectParam > value) {
  • engines/cine/main_loop.cpp

     
    189189        quitFlag = 0;
    190190
    191191        if (_preLoad == false) {
    192                 freeAnimDataTable();
    193192                resetMessageHead();
    194193                resetSeqList();
    195                 resetglobalScriptsHead();
    196                 resetObjectScriptHead();
    197194                resetBgIncrustList();
    198195
    199196                setTextWindow(0, 0, 20, 200);
     
    318315
    319316        hideMouse();
    320317        g_sound->stopMusic();
    321         freeAnimDataTable();
    322318        unloadAllMasks();
    323         freePrcLinkedList();
    324         releaseObjectScripts();
    325319        // if (g_cine->getGameType() == Cine::GType_OS) {
    326320        //      freeUnkList();
    327321        // }
    328         freeBgIncrustList();
    329322        closePart();
    330323}
    331324
  • 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        bgIncrustList.clear();
     131        freeAnimDataTable();
     132
    127133        memset(objectTable, 0, sizeof(objectTable));
    128         memset(scriptTable, 0, sizeof(scriptTable));
    129134        memset(messageTable, 0, sizeof(messageTable));
    130         memset(relTable, 0, sizeof(relTable));
    131135
    132         for (int i = 0; i < NUM_MAX_ANIMDATA; i++) {
    133                 animDataTable[i].ptr1 = animDataTable[i].ptr2 = NULL;
    134         }
    135 
    136136        overlayHead.next = overlayHead.previous = NULL;
    137137
    138138        var8 = 0;
    139         bgIncrustList = NULL;
     139//      bgIncrustList = NULL;
    140140
    141         objScriptList.next = NULL;
    142         objScriptList.scriptPtr = NULL;
    143 
    144         globalScriptsHead.next = NULL;
    145         globalScriptsHead.scriptPtr = NULL;
    146 
    147141        var2 = var3 = var4 = var5 = 0;
    148142
    149         freePrcLinkedList();
    150 
    151143        _preLoad = false;
    152144        if (ConfMan.hasKey("save_slot")) {
    153145                char saveNameBuffer[256];
  • engines/cine/prc.cpp

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

     
    3737uint16 c_palette[256];
    3838byte colorMode256 = 0;
    3939byte palette256[256 * 3];
     40byte newPalette[256 * 3];
     41byte newColorMode = 0;
     42byte ctColorMode = 0;
     43byte bgColorMode = 0;
    4044
    4145byte *screenBuffer;
    4246byte *page1Raw;
     
    157161        //gfxFlipPage(page2);
    158162}
    159163
    160 void gfxFillSprite(byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
     164void gfxFillSprite(const byte *spritePtr, uint16 width, uint16 height, byte *page, int16 x, int16 y, uint8 fillColor) {
    161165        int16 i, j;
    162166
    163167        for (i = 0; i < height; i++) {
     
    180184        }
    181185}
    182186
    183 void gfxDrawMaskedSprite(byte *spritePtr, byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
     187void gfxDrawMaskedSprite(const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    184188        int16 i, j;
    185189
    186190        for (i = 0; i < height; i++) {
     
    198202        }
    199203}
    200204
    201 void gfxUpdateSpriteMask(byte *spritePtr, byte *spriteMskPtr, int16 width, int16 height, byte *maskPtr,
     205void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    202206        int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx) {
    203207        int16 i, j, d, spritePitch, maskPitch;
    204208
     
    299303        }
    300304}
    301305
    302 int16 gfxGetBit(int16 x, int16 y, byte *ptr, int16 width) {
    303         byte *ptrToData = (ptr) + y * width + x;
     306int16 gfxGetBit(int16 x, int16 y, const byte *ptr, int16 width) {
     307        const byte *ptrToData = (ptr) + y * width + x;
    304308
    305309        if (x > width) {
    306310                return 0;
     
    379383        g_system->copyRectToScreen(screenBuffer, 320, 0, 0, 320, 200);
    380384}
    381385
    382 void drawSpriteRaw(byte *spritePtr, byte *maskPtr, int16 width, int16 height,
     386void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height,
    383387                                   byte *page, int16 x, int16 y) {
    384388        int16 i, j;
    385389
     
    406410        }
    407411}
    408412
    409 void drawSpriteRaw2(byte *spritePtr, byte transColor, int16 width, int16 height,
     413void drawSpriteRaw2(const byte *spritePtr, byte transColor, int16 width, int16 height,
    410414                                        byte *page, int16 x, int16 y) {
    411415        int16 i, j;
    412416
     
    425429        }
    426430}
    427431
     432void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 height,
     433                                   byte *page, int16 x, int16 y) {
     434        int16 i, j;
     435
     436        for (i = 0; i < height; i++) {
     437                byte *destPtr = page + x + y * 320;
     438                const byte *srcPtr = bgPtr + x + y * 320;
     439                destPtr += i * 320;
     440                srcPtr += i * 320;
     441
     442                for (j = 0; j < width * 8; j++) {
     443                        if ((!maskPtr || !(*maskPtr)) && (x + j >= 0
     444                                        && x + j < 320 && i + y >= 0 && i + y < 200)) {
     445                                *destPtr = *srcPtr;
     446                        }
     447
     448                        destPtr++;
     449                        srcPtr++;
     450                        maskPtr++;
     451                }
     452        }
     453}
     454
     455/*! \todo Fix rendering to prevent fadein artifacts
     456 */
     457void fadeFromBlack() {
     458        int i, j;
     459        int r, g, b, tr, tg, tb;
     460        if (newColorMode == 2) {
     461                colorMode256 = 1;
     462                memset(palette256, 0, 256*3);
     463        } else if (newColorMode == 1) {
     464                colorMode256 = 0;
     465                memset(c_palette, 0, 16 * sizeof(uint16));
     466        }
     467
     468        for (i = 0; i < 8; i++ ) {
     469                gfxFlipRawPage(page1Raw);
     470                g_system->updateScreen();
     471                g_system->delayMillis(50);
     472
     473                if (colorMode256) {
     474                        for (j = 0; j < 256*3; j++) {
     475                                r = palette256[j] + (newPalette[j] + 7) / 8;
     476                                palette256[j] = CLIP(r, 0, (int)newPalette[j]);
     477                        }
     478                } else {
     479                        for (j = 0; j < 16; j++) {
     480                                r = c_palette[j] & 0xf;
     481                                g = (c_palette[j] & 0xf0) >> 4;
     482                                b = (c_palette[j] & 0xf00) >> 8;
     483
     484                                tr = tempPalette[j] & 0xf;
     485                                tg = (tempPalette[j] & 0xf0) >> 4;
     486                                tb = (tempPalette[j] & 0xf00) >> 8;
     487
     488                                r = CLIP(r + (tr + 7) / 8, 0, tr);
     489                                g = CLIP(g + (tg + 7) / 8, 0, tg);
     490                                b = CLIP(b + (tb + 7) / 8, 0, tb);
     491
     492                                c_palette[j] = r | (g << 4) | (b << 8);
     493                        }
     494
     495                }
     496        }
     497
     498        if (colorMode256) {
     499                memcpy(palette256, newPalette, 256*3);
     500        } else {
     501                memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     502        }
     503}
     504
    428505void fadeToBlack() {
    429506        for (int i = 0; i < 8; i++) {
    430507                if (colorMode256) {
    431                         for (int j = 0; j < 256; j++) {
    432                                 palette256[j] = transformColor(palette256[j], -1, -1, -1);
     508                        for (int j = 0; j < 256*3; j++) {
     509                                palette256[j] = CLIP(palette256[j] - 32, 0, 255);
    433510                        }
    434511                } else {
    435512                        for (int j = 0; j < 16; j++) {
     
    449526void flip(void) {
    450527        blitRawScreen(page1Raw);
    451528        if (fadeRequired) {
    452                 memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     529                if (newColorMode == 3) {
     530                        newColorMode = ctColorMode + 1;
     531                }
     532
     533                if (newColorMode == 2) {
     534                        colorMode256 = 1;
     535                        memcpy(palette256, newPalette, 256*3);
     536                } else {
     537                        colorMode256 = 0;
     538                        memcpy(c_palette, tempPalette, sizeof(uint16) * 16);
     539                }
    453540                fadeRequired = false;
    454541        }
    455542}
  • 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/sound.cpp

     
    602602        for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
    603603                _instrumentsData[i] = NULL;
    604604
    605                 char instrument[13];
     605                char instrument[64];
    606606                memcpy(instrument, _sfxData + 20 + i * 30, 12);
    607                 instrument[12] = '\0';
     607                instrument[63] = '\0';
    608608
    609609                if (strlen(instrument) != 0) {
    610610                        char *dot = strrchr(instrument, '.');
  • engines/cine/bg.cpp

     
    2929
    3030#include "cine/cine.h"
    3131#include "cine/various.h"
     32#include "cine/bg.h"
    3233
    3334namespace Cine {
    3435
     
    3637byte *additionalBgTable[9];
    3738byte currentAdditionalBgIdx = 0, currentAdditionalBgIdx2 = 0;
    3839
    39 void loadCtHigh(byte * currentPtr) {
    40         memcpy(page3Raw, currentPtr, 320 * 200);
    41 }
    42 
    4340byte loadCt(const char *ctName) {
    4441        uint16 header[32];
    4542        byte *ptr, *dataPtr;
     
    5249        if (g_cine->getGameType() == Cine::GType_OS) {
    5350                uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
    5451                if (bpp == 8) {
     52                        ctColorMode = 1;
     53                        memcpy(newPalette, ptr, 256*3);
    5554                        ptr += 3 * 256;
    56                         loadCtHigh(ptr);
     55                        memcpy(page3Raw, ptr, 320 * 200);
    5756                } else {
    58                         ptr += 32;
     57                        ctColorMode = 0;
     58                        for (int i = 0; i < 16; i++) {
     59                                tempPalette[i] = READ_BE_UINT16(ptr);
     60                                ptr += 2;
     61                        }
     62
    5963                        gfxResetRawPage(page3Raw);
    6064                        gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200);
    6165                }
     
    7882}
    7983
    8084void loadBgHigh(const char *currentPtr) {
    81         memcpy(palette256, currentPtr, 256 * 3);
     85        memcpy(newPalette, currentPtr, 256 * 3);
    8286        currentPtr += 256 * 3;
    8387
    8488        memcpy(page2Raw, currentPtr, 320 * 200);
    8589
    86         colorMode256 = 1;
     90        newColorMode = 2;
     91        bgColorMode = 1;
     92
    8793}
    8894
    8995byte loadBg(const char *bgName) {
     
    99105        if (bpp == 8) {
    100106                loadBgHigh((const char *)ptr);
    101107        } else {
    102                 colorMode256 = 0;
     108                newColorMode = 1;
     109                bgColorMode = 0;
    103110
    104111                for (int i = 0; i < 16; i++) {
    105112                        tempPalette[i] = READ_BE_UINT16(ptr);
     
    127134
    128135        additionalBgTable[bgIdx] = (byte *) malloc(320 * 200);
    129136
     137        debug("addBackground %d", bgIdx);
     138
    130139        uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
     140
    131141        if (bpp == 8) {
     142                bgColorMode = 1;
     143                memcpy(newPalette, ptr, 256*3);
    132144                ptr += 3 * 256;
    133145                memcpy(additionalBgTable[bgIdx], ptr, 320 * 200);
    134146        } else {
    135                 ptr += 32;
     147                bgColorMode = 0;
     148                for (int i = 0; i < 16; i++) {
     149                        tempPalette[i] = READ_BE_UINT16(ptr);
     150                        ptr += 2;
     151                }
     152
    136153                gfxConvertSpriteToRaw(additionalBgTable[bgIdx], ptr, 160, 200);
    137154        }
    138155        free(dataPtr);
  • engines/cine/bg_list.h

     
    2929
    3030#include "common/scummsys.h"
    3131#include "common/savefile.h"
     32#include "common/list.h"
    3233
    3334namespace Cine {
    3435
    35 struct BGIncrustList {
    36         struct BGIncrustList *next;
     36struct BGIncrust {
    3737        byte *unkPtr;
    3838        int16 objIdx;
    3939        int16 param;
     
    4343        int16 part;
    4444};
    4545
    46 extern BGIncrustList *bgIncrustList;
     46extern Common::List<BGIncrust> bgIncrustList;
    4747extern uint32 var8;
    4848
    4949void addToBGList(int16 objIdx, bool addList = true);
    5050void addSpriteFilledToBGList(int16 idx, bool addList = true);
    5151
    5252void createBgIncrustListElement(int16 objIdx, int16 param);
    53 void freeBgIncrustList(void);
    5453void resetBgIncrustList(void);
    55 void loadBgIncrustFromSave(Common::InSaveFile *fHandle);
    56 void reincrustAllBg(void);
     54void loadBgIncrustFromSave(Common::InSaveFile &fHandle);
    5755
    5856} // End of namespace Cine
    5957
  • 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        byte *_data; ///< Image data
     67        byte *_mask; ///< Image mask (may be NULL)
     68        int16 _fileIdx; ///< Source file index in bundle
     69        int16 _frameIdx; ///< Frame number in animation
     70        char _name[10]; ///< Part filename
     71        int _size; ///< _data/_mask size, internal only
     72
     73public:
     74        uint16 _width; ///< Image width (ussually twice the real size)
     75        uint16 _height; ///< Image height
     76        uint16 _bpp; ///< Bit depth/type information
     77        uint16 _var1; ///< Something related to width
     78        int _realWidth; ///< Real image width in bytes
     79
     80        AnimData();
     81        AnimData(const AnimData &src);
     82        ~AnimData();
     83
     84        AnimData &operator=(const AnimData &src);
     85
     86        const byte *data() const { return _data; } ///< Image data
     87        const byte *mask() const { return _mask; } ///< Image mask (may be NULL)
     88        byte getColor(int x, int y);
     89
     90        void load(byte *d, int type, uint16 w, uint16 h, int16 file, int16 frame, const char *n, byte transparent = 0);
     91        void clear();
     92
     93        void save(Common::OutSaveFile &fHandle) const;
     94};
     95
     96#define NUM_MAX_ANIMDATA 255
     97
     98extern AnimData animDataTable[NUM_MAX_ANIMDATA];
     99
    57100void freeAnimDataTable(void);
    58101void freeAnimDataRange(byte startIdx, byte numIdx);
    59102void loadResource(const char *animName);
    60103void loadAbs(const char *resourceName, uint16 idx);
    61 void loadResourcesFromSave();
     104void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken);
    62105
    63106} // End of namespace Cine
    64107