Ticket #8853: overlay.patch

File overlay.patch, 80.6 KB (added by SF/next_ghost, 17 years ago)

Overlay rewrite

  • engines/cine/script_fw.cpp

     
    2424 */
    2525
    2626/*! \file
    27  * Script interpreter file
     27 * Future Wars script interpreter file
    2828 */
    2929
    3030#include "common/endian.h"
     
    204204};
    205205const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable);
    206206
    207 
    208 const 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 };
    423 const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable);
    424 
    425207FWScriptInfo *scriptInfo; ///< Script factory
    426208RawScriptArray scriptTable; ///< Table of script bytecode
    427209
     
    898680        fHandle.writeUint16BE(_index);
    899681}
    900682
    901 /*! \brief Contructor for global scripts
    902  * \param script Script bytecode reference
    903  * \param idx Script bytecode index
    904  */
    905 OSScript::OSScript(const RawScript &script, int16 idx) :
    906         FWScript(script, idx, new OSScriptInfo) {}
    907 
    908 /*! \brief Constructor for object scripts
    909  * \param script Script bytecode reference
    910  * \param idx Script bytecode index
    911  */
    912 OSScript::OSScript(RawObjectScript &script, int16 idx) :
    913         FWScript(script, idx, new OSScriptInfo) {}
    914 
    915 /*! \brief Copy constructor
    916  */
    917 OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
    918 
    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  */
    925 void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
    926         FWScript::load(labels, local, compare, pos);
    927 }
    928683/*! \brief Get opcode info string
    929684 * \param opcode Opcode to look for in opcode table
    930685 */
     
    1003758        return tmp;
    1004759}
    1005760
    1006 /*! \brief Get opcode info string
    1007  * \param opcode Opcode to look for in opcode table
    1008  */
    1009 const char *OSScriptInfo::opcodeInfo(byte opcode) const {
    1010         if (opcode == 0 || opcode > OSScript::_numOpcodes) {
    1011                 return NULL;
    1012         }
    1013 
    1014         if (!OSScript::_opcodeTable[opcode - 1].args) {
    1015                 warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
    1016                 return NULL;
    1017         }
    1018 
    1019         return OSScript::_opcodeTable[opcode - 1].args;
    1020 }
    1021 
    1022 /*! \brief Get opcode handler pointer
    1023  * \param opcode Opcode to look for in opcode table
    1024  */
    1025 opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
    1026         if (opcode == 0 || opcode > OSScript::_numOpcodes) {
    1027                 return NULL;
    1028         }
    1029 
    1030         if (!OSScript::_opcodeTable[opcode - 1].proc) {
    1031                 warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
    1032                 return NULL;
    1033         }
    1034 
    1035         return OSScript::_opcodeTable[opcode - 1].proc;
    1036 }
    1037 
    1038 /*! \brief Create new OSScript instance
    1039  * \param script Script bytecode
    1040  * \param index Bytecode index
    1041  */
    1042 FWScript *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  */
    1050 FWScript *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  */
    1062 FWScript *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  */
    1077 FWScript *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 
    1084761// ------------------------------------------------------------------------
    1085762// FUTURE WARS opcodes
    1086763// ------------------------------------------------------------------------
     
    13751052        byte param = getNextByte();
    13761053
    13771054        debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param);
    1378         loadOverlayElement(param, 0);
     1055        addOverlay(param, 0);
    13791056        return 0;
    13801057}
    13811058
     
    13831060        byte param = getNextByte();
    13841061
    13851062        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param);
    1386         freeOverlay(param, 0);
     1063        removeOverlay(param, 0);
    13871064        return 0;
     1065        return 0;
    13881066}
    13891067
    13901068int FWScript::o1_addToBgList() {
     
    13991077        byte param = getNextByte();
    14001078
    14011079        debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param);
    1402         loadOverlayElement(param, 1);
     1080        addOverlay(param, 1);
    14031081        return 0;
    14041082}
    14051083
     
    14071085        byte param = getNextByte();
    14081086
    14091087        debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param);
    1410         freeOverlay(param, 1);
     1088        removeOverlay(param, 1);
    14111089        return 0;
     1090        return 0;
    14121091}
    14131092
    14141093int FWScript::o1_loadMask4() {
    14151094        byte param = getNextByte();
    14161095
    14171096        debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param);
    1418         loadOverlayElement(param, 4);
     1097        addOverlay(param, 4);
    14191098        return 0;
    14201099}
    14211100
     
    14231102        byte param = getNextByte();
    14241103
    14251104        debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param);
    1426         freeOverlay(param, 4);
     1105        removeOverlay(param, 4);
    14271106        return 0;
    14281107}
    14291108
     
    18251504
    18261505int FWScript::o1_unloadAllMasks() {
    18271506        debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line);
    1828         unloadAllMasks();
     1507        overlayList.clear();
    18291508        return 0;
    18301509}
    18311510
     
    20341713        byte param = getNextByte();
    20351714
    20361715        debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param);
    2037         loadOverlayElement(param, 5);
     1716        addOverlay(param, 5);
    20381717        return 0;
    20391718}
    20401719
     
    20421721        byte param = getNextByte();
    20431722
    20441723        debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param);
    2045         freeOverlay(param, 5);
     1724        removeOverlay(param, 5);
    20461725        return 0;
    20471726}
    20481727
    2049 // ------------------------------------------------------------------------
    2050 // OPERATION STEALTH opcodes
    2051 // ------------------------------------------------------------------------
    2052 
    2053 int FWScript::o2_loadPart() {
    2054         const char *param = getNextString();
    2055 
    2056         debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
    2057         return 0;
    2058 }
    2059 
    2060 int FWScript::o2_playSample() {
    2061         if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
    2062                 // no-op in these versions
    2063                 getNextByte();
    2064                 getNextByte();
    2065                 getNextWord();
    2066                 getNextByte();
    2067                 getNextWord();
    2068                 getNextWord();
    2069                 return 0;
    2070         }
    2071         return o1_playSample();
    2072 }
    2073 
    2074 int FWScript::o2_playSampleAlt() {
    2075         byte num = getNextByte();
    2076         byte channel = getNextByte();
    2077         uint16 frequency = getNextWord();
    2078         getNextByte();
    2079         getNextWord();
    2080         uint16 size = getNextWord();
    2081 
    2082         if (size == 0xFFFF) {
    2083                 size = animDataTable[num]._width * animDataTable[num]._height;
    2084         }
    2085         if (animDataTable[num].data()) {
    2086                 if (g_cine->getPlatform() == Common::kPlatformPC) {
    2087                         // if speaker output is available, play sound on it
    2088                         // if it's another device, don't play anything
    2089                         // TODO: implement this, it's used in the introduction for example
    2090                         // on each letter displayed
    2091                 } else {
    2092                         g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
    2093                 }
    2094         }
    2095         return 0;
    2096 }
    2097 
    2098 int FWScript::o2_addSeqListElement() {
    2099         byte param1 = getNextByte();
    2100         byte param2 = getNextByte();
    2101         byte param3 = getNextByte();
    2102         byte param4 = getNextByte();
    2103         uint16 param5 = getNextWord();
    2104         uint16 param6 = getNextWord();
    2105         uint16 param7 = getNextWord();
    2106 
    2107         debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
    2108         addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
    2109         return 0;
    2110 }
    2111 
    2112 int FWScript::o2_removeSeq() {
    2113         byte a = getNextByte();
    2114         byte b = getNextByte();
    2115 
    2116         debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
    2117         removeSeq(a, 0, b);
    2118         return 0;
    2119 }
    2120 
    2121 /*! \todo Implement this instruction
    2122  */
    2123 int FWScript::o2_op81() {
    2124         warning("STUB: o2_op81()");
    2125         // freeUnkList();
    2126         return 0;
    2127 }
    2128 
    2129 /*! \todo Implement this instruction
    2130  */
    2131 int 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;
    2137 }
    2138 
    2139 int FWScript::o2_isSeqRunning() {
    2140         byte a = getNextByte();
    2141         byte b = getNextByte();
    2142 
    2143         debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
    2144 
    2145         if (isSeqRunning(a, 0, b)) {
    2146                 _compare = 1;
    2147         } else {
    2148                 _compare = 0;
    2149         }
    2150         return 0;
    2151 }
    2152 
    2153 /*! \todo The assert may produce false positives and requires testing
    2154  */
    2155 int FWScript::o2_gotoIfSupNearest() {
    2156         byte labelIdx = getNextByte();
    2157 
    2158         if (_compare == kCmpGT) {
    2159                 assert(_labels[labelIdx] != -1);
    2160 
    2161                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
    2162                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2163         } else {
    2164                 debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
    2165         }
    2166         return 0;
    2167 }
    2168 
    2169 /*! \todo The assert may produce false positives and requires testing
    2170  */
    2171 int FWScript::o2_gotoIfSupEquNearest() {
    2172         byte labelIdx = getNextByte();
    2173 
    2174         if (_compare & (kCmpGT | kCmpEQ)) {
    2175                 assert(_labels[labelIdx] != -1);
    2176 
    2177                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
    2178                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2179         } else {
    2180                 debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
    2181         }
    2182         return 0;
    2183 }
    2184 
    2185 /*! \todo The assert may produce false positives and requires testing
    2186  */
    2187 int FWScript::o2_gotoIfInfNearest() {
    2188         byte labelIdx = getNextByte();
    2189 
    2190         if (_compare == kCmpLT) {
    2191                 assert(_labels[labelIdx] != -1);
    2192 
    2193                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
    2194                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2195         } else {
    2196                 debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
    2197         }
    2198         return 0;
    2199 }
    2200 
    2201 /*! \todo The assert may produce false positives and requires testing
    2202  */
    2203 int FWScript::o2_gotoIfInfEquNearest() {
    2204         byte labelIdx = getNextByte();
    2205 
    2206         if (_compare & (kCmpLT | kCmpEQ)) {
    2207                 assert(_labels[labelIdx] != -1);
    2208 
    2209                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
    2210                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2211         } else {
    2212                 debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
    2213         }
    2214         return 0;
    2215 }
    2216 
    2217 /*! \todo The assert may produce false positives and requires testing
    2218  */
    2219 int FWScript::o2_gotoIfEquNearest() {
    2220         byte labelIdx = getNextByte();
    2221 
    2222         if (_compare == kCmpEQ) {
    2223                 assert(_labels[labelIdx] != -1);
    2224 
    2225                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
    2226                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2227         } else {
    2228                 debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
    2229         }
    2230         return 0;
    2231 }
    2232 
    2233 /*! \todo The assert may produce false positives and requires testing
    2234  */
    2235 int FWScript::o2_gotoIfDiffNearest() {
    2236         byte labelIdx = getNextByte();
    2237 
    2238         if (_compare != kCmpEQ) {
    2239                 assert(_labels[labelIdx] != -1);
    2240 
    2241                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
    2242                 _pos = _script.getLabel(*_info, labelIdx, _pos);
    2243         } else {
    2244                 debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
    2245         }
    2246         return 0;
    2247 }
    2248 
    2249 int FWScript::o2_startObjectScript() {
    2250         byte param = getNextByte();
    2251 
    2252         debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
    2253         runObjectScript(param);
    2254         return 0;
    2255 }
    2256 
    2257 int FWScript::o2_stopObjectScript() {
    2258         byte param = getNextByte();
    2259 
    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;
    2269 }
    2270 
    2271 /*! \todo Implement this instruction
    2272  */
    2273 int 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);
    2283         // _currentScriptElement->compareResult = ...
    2284         return 0;
    2285 }
    2286 
    2287 int FWScript::o2_addBackground() {
    2288         byte param1 = getNextByte();
    2289         const char *param2 = getNextString();
    2290 
    2291         debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
    2292         addBackground(param2, param1);
    2293         return 0;
    2294 }
    2295 
    2296 int FWScript::o2_removeBackground() {
    2297         byte param = getNextByte();
    2298 
    2299         assert(param);
    2300 
    2301         debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
    2302 
    2303         if (additionalBgTable[param]) {
    2304                 free(additionalBgTable[param]);
    2305                 additionalBgTable[param] = NULL;
    2306         }
    2307 
    2308         if (currentAdditionalBgIdx == param) {
    2309                 currentAdditionalBgIdx = 0;
    2310         }
    2311 
    2312         if (currentAdditionalBgIdx2 == param) {
    2313                 currentAdditionalBgIdx2 = 0;
    2314         }
    2315 
    2316         strcpy(currentBgName[param], "");
    2317         return 0;
    2318 }
    2319 
    2320 int FWScript::o2_loadAbs() {
    2321         byte param1 = getNextByte();
    2322         const char *param2 = getNextString();
    2323 
    2324         debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
    2325         loadAbs(param2, param1);
    2326         return 0;
    2327 }
    2328 
    2329 int FWScript::o2_loadBg() {
    2330         byte param = getNextByte();
    2331 
    2332         assert(param <= 8);
    2333 
    2334         debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
    2335 
    2336         if (additionalBgTable[param]) {
    2337                 currentAdditionalBgIdx = param;
    2338                 if (param == 8) {
    2339                         newColorMode = 3;
    2340                 } else {
    2341                         newColorMode = bgColorMode + 1;
    2342                 }
    2343                 //if (_screenNeedFadeOut == 0) {
    2344                 //      adBgVar1 = 1;
    2345                 //}
    2346                 fadeRequired = true;
    2347         }
    2348         return 0;
    2349 }
    2350 
    2351 /*! \todo Implement this instruction
    2352  */
    2353 int FWScript::o2_wasZoneChecked() {
    2354         warning("STUB: o2_wasZoneChecked()");
    2355         return 0;
    2356 }
    2357 
    2358 /*! \todo Implement this instruction
    2359  */
    2360 int 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;
    2371 }
    2372 
    2373 /*! \todo Implement this instruction
    2374  */
    2375 int 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;
    2382 }
    2383 
    2384 int FWScript::o2_useBgScroll() {
    2385         byte param = getNextByte();
    2386 
    2387         assert(param <= 8);
    2388 
    2389         debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
    2390 
    2391         if (additionalBgTable[param]) {
    2392                 currentAdditionalBgIdx2 = param;
    2393         }
    2394         return 0;
    2395 }
    2396 
    2397 int FWScript::o2_setAdditionalBgVScroll() {
    2398         byte param1 = getNextByte();
    2399 
    2400         if (param1) {
    2401                 byte param2 = getNextByte();
    2402 
    2403                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
    2404                 additionalBgVScroll = _localVars[param2];
    2405         } else {
    2406                 uint16 param2 = getNextWord();
    2407 
    2408                 debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
    2409                 additionalBgVScroll = param2;
    2410         }
    2411         return 0;
    2412 }
    2413 
    2414 /*! \todo Implement this instruction
    2415  */
    2416 int FWScript::o2_op9F() {
    2417         warning("o2_op9F()");
    2418         getNextWord();
    2419         getNextWord();
    2420         return 0;
    2421 }
    2422 
    2423 int FWScript::o2_addGfxElementA0() {
    2424         uint16 param1 = getNextWord();
    2425         uint16 param2 = getNextWord();
    2426 
    2427         debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
    2428         addGfxElementA0(param1, param2);
    2429         return 0;
    2430 }
    2431 
    2432 /*! \todo Implement this instruction
    2433  */
    2434 int 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;
    2440 }
    2441 
    2442 /*! \todo Implement this instruction
    2443  */
    2444 int FWScript::o2_opA2() {
    2445         uint16 a = getNextWord();
    2446         uint16 b = getNextWord();
    2447         warning("STUB: o2_opA2(%x, %x)", a, b);
    2448         // addGfxElementA2();
    2449         return 0;
    2450 }
    2451 
    2452 /*! \todo Implement this instruction
    2453  */
    2454 int FWScript::o2_opA3() {
    2455         uint16 a = getNextWord();
    2456         uint16 b = getNextWord();
    2457         warning("STUB: o2_opA3(%x, %x)", a, b);
    2458         // removeGfxElementA2();
    2459         return 0;
    2460 }
    2461 
    2462 int FWScript::o2_loadMask22() {
    2463         byte param = getNextByte();
    2464 
    2465         debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
    2466         loadOverlayElement(param, 22);
    2467         return 0;
    2468 }
    2469 
    2470 int FWScript::o2_unloadMask22() {
    2471         byte param = getNextByte();
    2472 
    2473         debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
    2474         freeOverlay(param, 22);
    2475         return 0;
    2476 }
    2477 
    24781728//-----------------------------------------------------------------------
    24791729
    2480 void addGfxElementA0(int16 param1, int16 param2) {
    2481         overlayHeadElement *currentHead = &overlayHead;
    2482         overlayHeadElement *tempHead = currentHead;
    2483         overlayHeadElement *newElement;
    2484 
    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)
    2499                 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  */
    2524 void 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;
    2540         }
    2541 }
    2542 
    2543 void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
    2544         SeqListElement *currentHead = &seqList;
    2545         SeqListElement *tempHead = currentHead;
    2546 
    2547         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    2548                 tempHead = currentHead;
    2549                 currentHead = tempHead->next;
    2550         }
    2551 
    2552         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    2553                 currentHead->var4 = -1;
    2554         }
    2555 }
    2556 
    2557 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
    2558         SeqListElement *currentHead = &seqList;
    2559         SeqListElement *tempHead = currentHead;
    2560 
    2561         while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    2562                 tempHead = currentHead;
    2563                 currentHead = tempHead->next;
    2564         }
    2565 
    2566         if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
    2567                 return 1;
    2568         }
    2569 
    2570         return 0;
    2571 }
    2572 
    25731730void palRotate(byte a, byte b, byte c) {
    25741731        if (c == 1) {
    25751732                uint16 currentColor = c_palette[b];
  • engines/cine/module.mk

     
    1414        part.o \
    1515        prc.o \
    1616        rel.o \
    17         script.o \
     17        script_fw.o \
     18        script_os.o \
    1819        sound.o \
    1920        texte.o \
    2021        unpack.o \
  • engines/cine/object.h

     
    4040        uint16 part;
    4141};
    4242
    43 struct overlayHeadElement {
    44         struct overlayHeadElement *next;
    45         struct overlayHeadElement *previous;
     43struct overlay {
    4644        uint16 objIdx;
    4745        uint16 type;
    4846        int16 x;
     
    5755extern objectStruct objectTable[NUM_MAX_OBJECT];
    5856extern ScriptVars globalVars;
    5957
    60 extern overlayHeadElement overlayHead;
     58extern Common::List<overlay> overlayList;
    6159
    62 void unloadAllMasks(void);
    63 void resetMessageHead(void);
     60//void unloadAllMasks(void);
     61//void resetMessageHead(void);
    6462
    6563void loadObject(char *pObjectName);
    6664void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4);
    6765void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue);
    6866
    69 void loadOverlayElement(uint16 objIdx, uint16 param);
    70 int8 removeOverlayElement(uint16 objIdx, uint16 param);
     67void addOverlay(uint16 objIdx, uint16 param);
     68int removeOverlay(uint16 objIdx, uint16 param);
     69void addGfxElementA0(int16 objIdx, int16 param);
     70void removeGfxElementA0(int16 objIdx, int16 param);
    7171
    7272int16 getObjectParam(uint16 objIdx, uint16 paramIdx);
    73 int16 freeOverlay(uint16 objIdx, uint16 param);
    7473
    7574void addObjectParam(byte objIdx, byte paramIdx, int16 newValue);
    7675void subObjectParam(byte objIdx, byte paramIdx, int16 newValue);
  • engines/cine/bg_list.cpp

     
    7777void addSpriteFilledToBGList(int16 objIdx, bool addList) {
    7878        int16 x = objectTable[objIdx].x;
    7979        int16 y = objectTable[objIdx].y;
    80         int16 width = animDataTable[objectTable[objIdx].frame]._width;
     80        int16 width = animDataTable[objectTable[objIdx].frame]._realWidth;
    8181        int16 height = animDataTable[objectTable[objIdx].frame]._height;
    8282        const byte *data = animDataTable[objectTable[objIdx].frame].data();
    8383
     
    8686                if (g_cine->getGameType() == GType_OS) {
    8787                        for (int i = 0; i < 8; i++) {
    8888                                if (additionalBgTable[i]) {
    89                                         gfxFillSprite(data, width / 2, height, additionalBgTable[i], x, y);
     89                                        gfxFillSprite(data, width, height, additionalBgTable[i], x, y);
    9090                                }
    9191                        }
    9292                } else {
    93                         gfxFillSprite(data, width / 2, height, page2Raw, x, y);
     93                        gfxFillSprite(data, width, height, page2Raw, x, y);
    9494                }
    9595        }
    9696
  • engines/cine/anim.cpp

     
    186186};
    187187
    188188void convertMask(byte *dest, const byte *source, int16 width, int16 height);
    189 void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
    190189void convert8BBP(byte *dest, const byte *source, int16 width, int16 height);
    191190void convert8BBP2(byte *dest, byte *source, int16 width, int16 height);
    192191
  • engines/cine/various.cpp

     
    130130        objectScripts.push_back(tmp);
    131131}
    132132
     133/*! \brief Add action result message to overlay list
     134 * \param cmd Message description
     135 * \todo Why are x, y, width and color left uninitialized?
     136 */
    133137void addPlayerCommandMessage(int16 cmd) {
    134         overlayHeadElement *currentHeadPtr = overlayHead.next;
    135         overlayHeadElement *tempHead = &overlayHead;
    136         overlayHeadElement *pNewElement;
     138        overlay tmp;
     139        tmp.objIdx = cmd;
     140        tmp.type = 3;
    137141
    138         while (currentHeadPtr) {
    139                 tempHead = currentHeadPtr;
    140                 currentHeadPtr = tempHead->next;
    141         }
    142 
    143         pNewElement = new overlayHeadElement;
    144 
    145         assert(pNewElement);
    146 
    147         pNewElement->next = tempHead->next;
    148         tempHead->next = pNewElement;
    149 
    150         pNewElement->objIdx = cmd;
    151         pNewElement->type = 3;
    152 
    153         if (!currentHeadPtr) {
    154                 currentHeadPtr = &overlayHead;
    155         }
    156 
    157         pNewElement->previous = currentHeadPtr->previous;
    158         currentHeadPtr->previous = pNewElement;
     142        overlayList.push_back(tmp);
    159143}
    160144
    161145int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) {
     
    180164        return found;
    181165}
    182166
     167/*! \brief Find index of the object under cursor
     168 * \param x Mouse cursor coordinate
     169 * \param y Mouse cursor coordinate
     170 * \todo Fix displaced type 1 objects
     171 */
    183172int16 getObjectUnderCursor(uint16 x, uint16 y) {
    184         overlayHeadElement *currentHead = overlayHead.previous;
     173        Common::List<overlay>::iterator it;
    185174
    186175        int16 objX, objY, frame, part, threshold, height, xdif, ydif;
    187176        int width;
    188177
    189         while (currentHead) {
    190                 if (currentHead->type < 2) {
    191                         if (objectTable[currentHead->objIdx].name[0]) {
    192                                 objX = objectTable[currentHead->objIdx].x;
    193                                 objY = objectTable[currentHead->objIdx].y;
     178        // reverse_iterator would be nice
     179        for (it = overlayList.reverse_begin(); it != overlayList.end(); --it) {
     180                if (it->type >= 2 || !objectTable[it->objIdx].name[0]) {
     181                        continue;
     182                }
    194183
    195                                 frame = ABS((int16)(objectTable[currentHead->objIdx].frame));
     184                objX = objectTable[it->objIdx].x;
     185                objY = objectTable[it->objIdx].y;
    196186
    197                                 part = objectTable[currentHead->objIdx].part;
     187                frame = ABS((int16)(objectTable[it->objIdx].frame));
     188                part = objectTable[it->objIdx].part;
    198189
    199                                 if (currentHead->type == 0) {
    200                                         threshold = animDataTable[frame]._var1;
    201                                 } else {
    202                                         threshold = animDataTable[frame]._width / 2;
    203                                 }
     190                if (it->type == 0) {
     191                        threshold = animDataTable[frame]._var1;
     192                } else {
     193                        threshold = animDataTable[frame]._width / 2;
     194                }
    204195
    205                                 height = animDataTable[frame]._height;
    206                                 width = animDataTable[frame]._realWidth;
     196                height = animDataTable[frame]._height;
     197                width = animDataTable[frame]._realWidth;
    207198
    208                                 xdif = x - objX;
    209                                 ydif = y - objY;
     199                xdif = x - objX;
     200                ydif = y - objY;
    210201
    211                                 if ((xdif >= 0) && ((threshold << 4) > xdif) && (ydif > 0) && (ydif < height)) {
    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)) {
    215                                                                 return currentHead->objIdx;
    216                                                         }
    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                                                         }
    221                                                 } else if (currentHead->type == 1) { // is mask
    222                                                         if (gfxGetBit(x - objX, y - objY, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
    223                                                                 return currentHead->objIdx;
    224                                                         }
    225                                                 }
    226                                         }
    227                                 }
    228                         }
     202                if ((xdif < 0) || ((threshold << 4) <= xdif) || (ydif < 0) || (ydif >= height) || !animDataTable[frame].data()) {
     203                        continue;
    229204                }
    230205
    231                 currentHead = currentHead->previous;
     206                if (g_cine->getGameType() == Cine::GType_OS) {
     207                        if (xdif >= width) {
     208                                continue;
     209                        }
     210
     211                        if (it->type == 0 && animDataTable[frame].getColor(xdif, ydif) != part) {
     212                                return it->objIdx;
     213                        } else if (it->type == 1 && gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
     214                                return it->objIdx;
     215                        }
     216                } else if (it->type == 0)       { // use generated mask
     217                        if (gfxGetBit(xdif, ydif, animDataTable[frame].mask(), animDataTable[frame]._width)) {
     218                                return it->objIdx;
     219                        }
     220                } else if (it->type == 1) { // is mask
     221                        if (gfxGetBit(xdif, ydif, animDataTable[frame].data(), animDataTable[frame]._width * 4)) {
     222                                return it->objIdx;
     223                        }
     224                }
    232225        }
    233226
    234227        return -1;
     
    285278        }
    286279}
    287280
    288 void loadOverlayFromSave(Common::InSaveFile *fHandle) {
    289         overlayHeadElement *newElement;
    290         overlayHeadElement *currentHead = &overlayHead;
    291         overlayHeadElement *tempHead = currentHead;
     281/*! \brief Restore overlay sprites from savefile
     282 * \param fHandle Savefile open for reading
     283 */
     284void loadOverlayFromSave(Common::InSaveFile &fHandle) {
     285        overlay tmp;
    292286
    293         currentHead = tempHead->next;
     287        fHandle.readUint32BE();
     288        fHandle.readUint32BE();
    294289
    295         while (currentHead) {
    296                 tempHead = currentHead;
    297                 currentHead = tempHead->next;
    298         }
     290        tmp.objIdx = fHandle.readUint16BE();
     291        tmp.type = fHandle.readUint16BE();
     292        tmp.x = fHandle.readSint16BE();
     293        tmp.y = fHandle.readSint16BE();
     294        tmp.width = fHandle.readSint16BE();
     295        tmp.color = fHandle.readSint16BE();
    299296
    300         newElement = new overlayHeadElement;
    301 
    302         fHandle->readUint32BE();
    303         fHandle->readUint32BE();
    304 
    305         newElement->objIdx = fHandle->readUint16BE();
    306         newElement->type = fHandle->readUint16BE();
    307         newElement->x = fHandle->readSint16BE();
    308         newElement->y = fHandle->readSint16BE();
    309         newElement->width = fHandle->readSint16BE();
    310         newElement->color = fHandle->readSint16BE();
    311 
    312         newElement->next = tempHead->next;
    313         tempHead->next = newElement;
    314 
    315         if (!currentHead)
    316                 currentHead = &overlayHead;
    317 
    318         newElement->previous = currentHead->previous;
    319         currentHead->previous = newElement;
     297        overlayList.push_back(tmp);
    320298}
    321299
    322300/*! \brief Savefile format tester
     
    433411
    434412        g_sound->stopMusic();
    435413        freeAnimDataTable();
    436         unloadAllMasks();
     414        overlayList.clear();
    437415        // if (g_cine->getGameType() == Cine::GType_OS) {
    438416        //      freeUnkList();
    439417        // }
     
    599577
    600578        size = fHandle->readSint16BE();
    601579        for (i = 0; i < size; i++) {
    602                 loadOverlayFromSave(fHandle);
     580                loadOverlayFromSave(*fHandle);
    603581        }
    604582
    605583        loadBgIncrustFromSave(*fHandle);
     
    722700        }
    723701
    724702        {
    725                 int16 numScript = 0;
    726                 overlayHeadElement *currentHead = overlayHead.next;
     703                Common::List<overlay>::iterator it;
    727704
    728                 while (currentHead) {
    729                         numScript++;
    730                         currentHead = currentHead->next;
    731                 }
     705                fHandle->writeUint16BE(overlayList.size());
    732706
    733                 fHandle->writeUint16BE(numScript);
    734 
    735                 // actual save
    736                 currentHead = overlayHead.next;
    737 
    738                 while (currentHead) {
     707                for (it = overlayList.begin(); it != overlayList.end(); ++it) {
    739708                        fHandle->writeUint32BE(0);
    740709                        fHandle->writeUint32BE(0);
    741                         fHandle->writeUint16BE(currentHead->objIdx);
    742                         fHandle->writeUint16BE(currentHead->type);
    743                         fHandle->writeSint16BE(currentHead->x);
    744                         fHandle->writeSint16BE(currentHead->y);
    745                         fHandle->writeSint16BE(currentHead->width);
    746                         fHandle->writeSint16BE(currentHead->color);
    747 
    748                         currentHead = currentHead->next;
     710                        fHandle->writeUint16BE(it->objIdx);
     711                        fHandle->writeUint16BE(it->type);
     712                        fHandle->writeSint16BE(it->x);
     713                        fHandle->writeSint16BE(it->y);
     714                        fHandle->writeSint16BE(it->width);
     715                        fHandle->writeSint16BE(it->color);
    749716                }
    750717        }
    751718
     
    762729                fHandle->writeUint16BE(it->frame);
    763730                fHandle->writeUint16BE(it->part);
    764731        }
    765 /*
    766         int numBgIncrustList = 0;
    767         BGIncrustList *bgIncrustPtr = bgIncrustList;
    768732
    769         while (bgIncrustPtr) {
    770                 numBgIncrustList++;
    771                 bgIncrustPtr = bgIncrustPtr->next;
    772         }
    773 
    774         fHandle->writeUint16BE(numBgIncrustList);
    775         bgIncrustPtr = bgIncrustList;
    776         while (bgIncrustPtr) {
    777                 fHandle->writeUint32BE(0); // next
    778                 fHandle->writeUint32BE(0); // unkPtr
    779                 fHandle->writeUint16BE(bgIncrustPtr->objIdx);
    780                 fHandle->writeUint16BE(bgIncrustPtr->param);
    781                 fHandle->writeUint16BE(bgIncrustPtr->x);
    782                 fHandle->writeUint16BE(bgIncrustPtr->y);
    783                 fHandle->writeUint16BE(bgIncrustPtr->frame);
    784                 fHandle->writeUint16BE(bgIncrustPtr->part);
    785 
    786                 bgIncrustPtr = bgIncrustPtr->next;
    787         }
    788 */
    789 
    790733        delete fHandle;
    791734
    792735        setMouseCursor(MOUSE_CURSOR_NORMAL);
     
    16821625        return var_5E;
    16831626}
    16841627
    1685 void drawSprite(overlayHeadElement *currentOverlay, const byte *spritePtr,
    1686                                 const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    1687         byte *ptr = NULL;
     1628void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) {
    16881629        byte *msk = NULL;
    1689         byte i = 0;
    1690         uint16 si = 0;
    1691         overlayHeadElement *pCurrentOverlay = currentOverlay;
    16921630        int16 maskX, maskY, maskWidth, maskHeight;
    16931631        uint16 maskSpriteIdx;
    16941632
     1633        msk = (byte *)malloc(width * height);
     1634
    16951635        if (g_cine->getGameType() == Cine::GType_OS) {
    1696                 drawSpriteRaw2(spritePtr, objectTable[currentOverlay->objIdx].part, width, height, page, x, y);
    1697                 return;
     1636                generateMask(spritePtr, msk, width * height, objectTable[it->objIdx].part);
     1637        } else {
     1638                memcpy(msk, maskPtr, width * height);
    16981639        }
    16991640
    1700         while (pCurrentOverlay) {
    1701                 if (pCurrentOverlay->type == 5) {
    1702                         if (!si) {
    1703                                 ptr = (byte *)malloc(width * 8 * height);
    1704                                 msk = (byte *)malloc(width * 8 * height);
    1705                                 si = 1;
    1706                         }
     1641        for (++it; it != overlayList.end(); ++it) {
     1642                if (it->type != 5) {
     1643                        continue;
     1644                }
    17071645
    1708                         maskX = objectTable[pCurrentOverlay->objIdx].x;
    1709                         maskY = objectTable[pCurrentOverlay->objIdx].y;
     1646                maskX = objectTable[it->objIdx].x;
     1647                maskY = objectTable[it->objIdx].y;
    17101648
    1711                         maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;
     1649                maskSpriteIdx = ABS((int16)(objectTable[it->objIdx].frame));
    17121650
    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++);
     1651                maskWidth = animDataTable[maskSpriteIdx]._realWidth;
     1652                maskHeight = animDataTable[maskSpriteIdx]._height;
     1653                gfxUpdateSpriteMask(msk, x, y, width, height, animDataTable[maskSpriteIdx].data(), maskX, maskY, maskWidth, maskHeight);
     1654
    17161655#ifdef DEBUG_SPRITE_MASK
    1717                         gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
     1656                gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1);
    17181657#endif
    1719                 }
    1720 
    1721                 pCurrentOverlay = pCurrentOverlay->next;
    17221658        }
    17231659
    1724         if (si) {
    1725                 gfxDrawMaskedSprite(ptr, msk, width, height, page, x, y);
    1726                 free(ptr);
    1727                 free(msk);
    1728         } else {
    1729                 gfxDrawMaskedSprite(spritePtr, maskPtr, width, height, page, x, y);
    1730         }
     1660        gfxDrawMaskedSprite(spritePtr, msk, width, height, page, x, y);
     1661        free(msk);
    17311662}
    17321663
    17331664int16 additionalBgVScroll = 0;
     
    18271758        const char *messagePtr = (const char *)messageTable[msgIdx].ptr;
    18281759
    18291760        if (!messagePtr) {
    1830                 freeOverlay(msgIdx, 2);
     1761                removeOverlay(msgIdx, 2);
    18311762                return;
    18321763        }
    18331764
     
    18351766
    18361767        drawMessage(messagePtr, x, y, width, color);
    18371768
    1838         freeOverlay(msgIdx, 2);
     1769        removeOverlay(msgIdx, 2);
    18391770}
    18401771
    18411772void drawFailureMessage(byte cmd) {
     
    18571788
    18581789        drawMessage(messagePtr, x, y, width, color);
    18591790
    1860         freeOverlay(cmd, 3);
     1791        removeOverlay(cmd, 3);
    18611792}
    18621793
    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  */
    18671794void drawOverlays(void) {
    1868         uint16 partVar1, partVar2;
     1795        uint16 width, height;
    18691796        AnimData *pPart;
    1870         overlayHeadElement *currentOverlay, *nextOverlay;
    18711797        int16 x, y;
    18721798        objectStruct *objPtr;
    18731799        byte messageIdx;
    1874         int16 part;
     1800        Common::List<overlay>::iterator it;
    18751801
    18761802        backupOverlayPage();
    18771803
    18781804        _messageLen = 0;
    18791805
    1880         currentOverlay = (&overlayHead)->next;
     1806        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     1807                switch (it->type) {
     1808                case 0: // sprite
     1809                        assert(it->objIdx < NUM_MAX_OBJECT);
    18811810
    1882         while (currentOverlay) {
    1883                 nextOverlay = currentOverlay->next;
     1811                        objPtr = &objectTable[it->objIdx];
     1812                        x = objPtr->x;
     1813                        y = objPtr->y;
    18841814
    1885                 switch (currentOverlay->type) {
    1886                 case 0: // sprite
    1887                         {
    1888                                 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
     1815                        if (objPtr->frame < 0) {
     1816                                continue;
     1817                        }
    18891818
    1890                                 objPtr = &objectTable[currentOverlay->objIdx];
     1819                        pPart = &animDataTable[objPtr->frame];
     1820                        width = pPart->_realWidth;
     1821                        height = pPart->_height;
    18911822
    1892                                 x = objPtr->x;
    1893                                 y = objPtr->y;
     1823                        if (!pPart->data()) {
     1824                                continue;
     1825                        }
    18941826
    1895                                 if (objPtr->frame >= 0) {
    1896                                         if (g_cine->getGameType() == Cine::GType_OS) {
    1897                                                 pPart = &animDataTable[objPtr->frame];
     1827                        // drawSprite ignores masks of Operation Stealth sprites
     1828                        drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y);
     1829                        break;
    18981830
    1899                                                 partVar1 = pPart->_var1;
    1900                                                 partVar2 = pPart->_height;
     1831                case 2: // text
     1832                        // gfxWaitVSync();
     1833                        // hideMouse();
    19011834
    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);
    1906                                                 }
    1907                                         } else {
    1908                                                 part = objPtr->part;
     1835                        messageIdx = it->objIdx;
     1836                        x = it->x;
     1837                        y = it->y;
     1838                        width = it->width;
     1839                        height = it->color;
    19091840
    1910                                                 assert(part >= 0 && part <= NUM_MAX_ANIMDATA);
     1841                        blitRawScreen(page1Raw);
    19111842
    1912                                                 pPart = &animDataTable[objPtr->frame];
     1843                        drawDialogueMessage(messageIdx, x, y, width, height);
    19131844
    1914                                                 partVar1 = pPart->_var1;
    1915                                                 partVar2 = pPart->_height;
     1845                        // blitScreen(page0, NULL);
     1846                        // gfxRedrawMouseCursor();
    19161847
    1917                                                 if (pPart->data()) {
    1918                                                         drawSprite(currentOverlay, pPart->data(), pPart->mask(), partVar1, partVar2, page1Raw, x, y);
    1919                                                 }
    1920                                         }
    1921                                 }
    1922                                 break;
    1923                         }
    1924                 case 2: // text
    1925                         {
    1926                                 // gfxWaitVSync();
    1927                                 // hideMouse();
     1848                        waitForPlayerClick = 1;
    19281849
    1929                                 messageIdx = currentOverlay->objIdx;
    1930                                 x = currentOverlay->x;
    1931                                 y = currentOverlay->y;
    1932                                 partVar1 = currentOverlay->width;
    1933                                 partVar2 = currentOverlay->color;
     1850                        break;
    19341851
    1935                                 blitRawScreen(page1Raw);
     1852                case 3:
     1853                        // gfxWaitSync()
     1854                        // hideMouse();
    19361855
    1937                                 drawDialogueMessage(messageIdx, x, y, partVar1, partVar2);
     1856                        blitRawScreen(page1Raw);
    19381857
    1939                                 // blitScreen(page0, NULL);
    1940                                 // gfxRedrawMouseCursor();
     1858                        drawFailureMessage(it->objIdx);
    19411859
    1942                                 waitForPlayerClick = 1;
     1860                        // blitScreen(page0, NULL);
     1861                        // gfxRedrawMouseCursor();
    19431862
    1944                                 break;
    1945                         }
    1946                 case 3:
    1947                         {
    1948                                 // gfxWaitSync()
    1949                                 // hideMouse();
     1863                        waitForPlayerClick = 1;
    19501864
    1951                                 blitRawScreen(page1Raw);
     1865                        break;
    19521866
    1953                                 drawFailureMessage(currentOverlay->objIdx);
     1867                case 4:
     1868                        assert(it->objIdx < NUM_MAX_OBJECT);
    19541869
    1955                                 // blitScreen(page0, NULL);
    1956                                 // gfxRedrawMouseCursor();
     1870                        objPtr = &objectTable[it->objIdx];
     1871                        x = objPtr->x;
     1872                        y = objPtr->y;
    19571873
    1958                                 waitForPlayerClick = 1;
    1959 
    1960                                 break;
     1874                        if (objPtr->frame < 0) {
     1875                                continue;
    19611876                        }
    1962                 case 4:
    1963                         {
    1964                                 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
    19651877
    1966                                 objPtr = &objectTable[currentOverlay->objIdx];
     1878                        assert(objPtr->frame < NUM_MAX_ANIMDATA);
    19671879
    1968                                 x = objPtr->x;
    1969                                 y = objPtr->y;
     1880                        pPart = &animDataTable[objPtr->frame];
    19701881
     1882                        width = pPart->_realWidth;
     1883                        height = pPart->_height;
    19711884
    1972                                 if (objPtr->frame >= 0) {
    1973                                         part = objPtr->part;
     1885                        if (!pPart->data()) {
     1886                                continue;
     1887                        }
    19741888
    1975                                         assert(part >= 0 && part <= NUM_MAX_ANIMDATA);
     1889                        gfxFillSprite(pPart->data(), width, height, page1Raw, x, y);
     1890                        break;
    19761891
    1977                                         pPart = &animDataTable[objPtr->frame];
     1892                case 20:
     1893                        assert(it->objIdx < NUM_MAX_OBJECT);
    19781894
    1979                                         partVar1 = pPart->_width / 2;
    1980                                         partVar2 = pPart->_height;
     1895                        objPtr = &objectTable[it->objIdx];
     1896                        x = objPtr->x;
     1897                        y = objPtr->y;
     1898                        var5 = it->x;
    19811899
    1982                                         if (pPart->data()) {
    1983                                                 gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y);
    1984                                         }
    1985                                 }
    1986                                 break;
     1900                        if (objPtr->frame < 0 || var5 > 8 || !additionalBgTable[var5] || animDataTable[objPtr->frame]._bpp != 1) {
     1901                                continue;
    19871902                        }
    1988                 case 20:
    1989                         {
    1990                                 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);
    19911903
    1992                                 objPtr = &objectTable[currentOverlay->objIdx];
     1904                        width = animDataTable[objPtr->frame]._width / 2;
     1905                        height = animDataTable[objPtr->frame]._height;
    19931906
    1994                                 x = objPtr->x;
    1995                                 y = objPtr->y;
    1996 
    1997                                 var5 = currentOverlay->x;
    1998 
    1999                                 if (objPtr->frame >= 0 && var5 <= 8 && additionalBgTable[var5] && animDataTable[objPtr->frame]._bpp == 1) {
    2000                                         int16 x2;
    2001                                         int16 y2;
    2002 
    2003                                         x2 = animDataTable[objPtr->frame]._width / 2;
    2004                                         y2 = animDataTable[objPtr->frame]._height;
    2005 
    2006                                         if (animDataTable[objPtr->frame].data()) {
    2007                                                 maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), x2, y2, page1Raw, x, y);
    2008                                         }
    2009                                 }
    2010                                 break;
     1907                        if (!animDataTable[objPtr->frame].data()) {
     1908                                continue;
    20111909                        }
    2012                 }
    20131910
    2014                 currentOverlay = nextOverlay;
     1911                        maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y);
     1912                        break;
     1913                }
    20151914        }
    20161915}
    20171916
     
    20401939        }
    20411940
    20421941        if (newObjectName[0] != 0) {
    2043                 unloadAllMasks();
    2044                 resetMessageHead();
     1942                overlayList.clear();
    20451943
    20461944                loadObject(newObjectName);
    20471945
     
    20711969}
    20721970
    20731971void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5) {
    2074         overlayHeadElement *currentHead = &overlayHead;
    2075         overlayHeadElement *tempHead = currentHead;
    2076         overlayHeadElement *newElement;
     1972        overlay tmp;
    20771973
    2078         currentHead = tempHead->next;
     1974        tmp.objIdx = param1;
     1975        tmp.type = 2;
     1976        tmp.x = param2;
     1977        tmp.y = param3;
     1978        tmp.width = param4;
     1979        tmp.color = param5;
    20791980
    2080         while (currentHead) {
     1981        overlayList.push_back(tmp);
     1982}
     1983
     1984SeqListElement seqList;
     1985
     1986void removeSeq(uint16 param1, uint16 param2, uint16 param3) {
     1987        SeqListElement *currentHead = &seqList;
     1988        SeqListElement *tempHead = currentHead;
     1989
     1990        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
    20811991                tempHead = currentHead;
    20821992                currentHead = tempHead->next;
    20831993        }
    20841994
    2085         newElement = new overlayHeadElement;
     1995        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     1996                currentHead->var4 = -1;
     1997        }
     1998}
    20861999
    2087         newElement->next = tempHead->next;
    2088         tempHead->next = newElement;
     2000uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) {
     2001        SeqListElement *currentHead = &seqList;
     2002        SeqListElement *tempHead = currentHead;
    20892003
    2090         newElement->objIdx = param1;
    2091         newElement->type = 2;
     2004        while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) {
     2005                tempHead = currentHead;
     2006                currentHead = tempHead->next;
     2007        }
    20922008
    2093         newElement->x = param2;
    2094         newElement->y = param3;
    2095         newElement->width = param4;
    2096         newElement->color = param5;
     2009        if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) {
     2010                return 1;
     2011        }
    20972012
    2098         if (!currentHead)
    2099                 currentHead = &overlayHead;
    2100 
    2101         newElement->previous = currentHead->previous;
    2102 
    2103         currentHead->previous = newElement;
     2013        return 0;
    21042014}
    21052015
    2106 SeqListElement seqList;
    2107 
    21082016void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) {
    21092017        SeqListElement *currentHead = &seqList;
    21102018        SeqListElement *tempHead = currentHead;
  • engines/cine/gfx.h

     
    5353void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y);
    5454void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0);
    5555
    56 void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    57     int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx);
     56void gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *maskPtr, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight);
    5857
    5958void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
    6059void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color);
  • engines/cine/xref.txt

     
    144144reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and
    145145        loadBgIncrustFromSave() implementation)
    146146freeBgIncrustList() - removed (obsoleted by Common::List::clear())
     147
     148object.cpp
     149unloadAllMasks() - removed (obsoleted by Common::List::clear())
     150resetMessageHead() - removed (obsoleted by Common::List)
     151freeOverlay() - removed (duplicate of removeOverlay)
     152removeOverlayElement() - renamed to removeOverlay
     153loadOverlayElement() - renamed to addOverlay
  • engines/cine/script_os.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/cine/script.cpp $
     22 * $Id: script.cpp 31444 2008-04-07 20:24:40Z sev $
     23 *
     24 */
     25
     26/*! \file
     27 * Operation Stealth script interpreter file
     28 */
     29
     30#include "common/endian.h"
     31
     32#include "cine/cine.h"
     33#include "cine/bg_list.h"
     34#include "cine/object.h"
     35#include "cine/sound.h"
     36#include "cine/various.h"
     37#include "cine/script.h"
     38
     39namespace Cine {
     40
     41const Opcode OSScript::_opcodeTable[] = {
     42        /* 00 */
     43        { &FWScript::o1_modifyObjectParam, "bbw" },
     44        { &FWScript::o1_getObjectParam, "bbb" },
     45        { &FWScript::o1_addObjectParam, "bbw" },
     46        { &FWScript::o1_subObjectParam, "bbw" },
     47        /* 04 */
     48        { &FWScript::o1_add2ObjectParam, "bbw" },
     49        { &FWScript::o1_sub2ObjectParam, "bbw" },
     50        { &FWScript::o1_compareObjectParam, "bbw" },
     51        { &FWScript::o1_setupObject, "bwwww" },
     52        /* 08 */
     53        { &FWScript::o1_checkCollision, "bwwww" },
     54        { &FWScript::o1_loadVar, "bc" },
     55        { &FWScript::o1_addVar, "bc" },
     56        { &FWScript::o1_subVar, "bc" },
     57        /* 0C */
     58        { &FWScript::o1_mulVar, "bc" },
     59        { &FWScript::o1_divVar, "bc" },
     60        { &FWScript::o1_compareVar, "bc" },
     61        { &FWScript::o1_modifyObjectParam2, "bbb" },
     62        /* 10 */
     63        { 0, 0 },
     64        { 0, 0 },
     65        { 0, 0 },
     66        { &FWScript::o1_loadMask0, "b" },
     67        /* 14 */
     68        { &FWScript::o1_unloadMask0, "b" },
     69        { &FWScript::o1_addToBgList, "b" },
     70        { &FWScript::o1_loadMask1, "b" },
     71        { &FWScript::o1_unloadMask1, "b" },
     72        /* 18 */
     73        { &FWScript::o1_loadMask4, "b" },
     74        { &FWScript::o1_unloadMask4, "b" },
     75        { &FWScript::o1_addSpriteFilledToBgList, "b" },
     76        { &FWScript::o1_op1B, "" },
     77        /* 1C */
     78        { 0, 0 },
     79        { &FWScript::o1_label, "l" },
     80        { &FWScript::o1_goto, "b" },
     81        { &FWScript::o1_gotoIfSup, "b" },
     82        /* 20 */
     83        { &FWScript::o1_gotoIfSupEqu, "b" },
     84        { &FWScript::o1_gotoIfInf, "b" },
     85        { &FWScript::o1_gotoIfInfEqu, "b" },
     86        { &FWScript::o1_gotoIfEqu, "b" },
     87        /* 24 */
     88        { &FWScript::o1_gotoIfDiff, "b" },
     89        { &FWScript::o1_removeLabel, "b" },
     90        { &FWScript::o1_loop, "bb" },
     91        { 0, 0 },
     92        /* 28 */
     93        { 0, 0 },
     94        { 0, 0 },
     95        { 0, 0 },
     96        { 0, 0 },
     97        /* 2C */
     98        { 0, 0 },
     99        { 0, 0 },
     100        { 0, 0 },
     101        { 0, 0 },
     102        /* 30 */
     103        { 0, 0 },
     104        { &FWScript::o1_startGlobalScript, "b" },
     105        { &FWScript::o1_endGlobalScript, "b" },
     106        { 0, 0 },
     107        /* 34 */
     108        { 0, 0 },
     109        { 0, 0 },
     110        { 0, 0 },
     111        { 0, 0 },
     112        /* 38 */
     113        { 0, 0 },
     114        { 0, 0 },
     115        { 0, 0 },
     116        { &FWScript::o1_loadAnim, "s" },
     117        /* 3C */
     118        { &FWScript::o1_loadBg, "s" },
     119        { &FWScript::o1_loadCt, "s" },
     120        { 0, 0 },
     121        { &FWScript::o2_loadPart, "s" },
     122        /* 40 */
     123        { 0, 0 }, /* o1_closePart, triggered by some scripts (STARTA.PRC 4 for ex.) */
     124        { &FWScript::o1_loadNewPrcName, "bs" },
     125        { &FWScript::o1_requestCheckPendingDataLoad, "" },
     126        { 0, 0 },
     127        /* 44 */
     128        { 0, 0 },
     129        { &FWScript::o1_blitAndFade, "" },
     130        { &FWScript::o1_fadeToBlack, "" },
     131        { &FWScript::o1_transformPaletteRange, "bbwww" },
     132        /* 48 */
     133        { 0, 0 },
     134        { &FWScript::o1_setDefaultMenuColor2, "b" },
     135        { &FWScript::o1_palRotate, "bbb" },
     136        { 0, 0 },
     137        /* 4C */
     138        { 0, 0 },
     139        { 0, 0 },
     140        { 0, 0 },
     141        { &FWScript::o1_break, "" },
     142        /* 50 */
     143        { &FWScript::o1_endScript, "x" },
     144        { &FWScript::o1_message, "bwwww" },
     145        { &FWScript::o1_loadGlobalVar, "bc" },
     146        { &FWScript::o1_compareGlobalVar, "bc" },
     147        /* 54 */
     148        { 0, 0 },
     149        { 0, 0 },
     150        { 0, 0 },
     151        { 0, 0 },
     152        /* 58 */
     153        { 0, 0 },
     154        { &FWScript::o1_declareFunctionName, "s" },
     155        { &FWScript::o1_freePartRange, "bb" },
     156        { &FWScript::o1_unloadAllMasks, "" },
     157        // 5C */
     158        { 0, 0 },
     159        { 0, 0 },
     160        { 0, 0 },
     161        { 0, 0 },
     162        /* 60 */
     163        { 0, 0 },
     164        { 0, 0 },
     165        { 0, 0 },
     166        { &FWScript::o1_setScreenDimensions, "wwww" },
     167        /* 64 */
     168        { &FWScript::o1_displayBackground, "" },
     169        { &FWScript::o1_initializeZoneData, "" },
     170        { &FWScript::o1_setZoneDataEntry, "bw" },
     171        { &FWScript::o1_getZoneDataEntry, "bb" },
     172        /* 68 */
     173        { &FWScript::o1_setDefaultMenuColor, "b" },
     174        { &FWScript::o1_allowPlayerInput, "" },
     175        { &FWScript::o1_disallowPlayerInput, "" },
     176        { &FWScript::o1_changeDataDisk, "b" },
     177        /* 6C */
     178        { 0, 0 },
     179        { &FWScript::o1_loadMusic, "s" },
     180        { &FWScript::o1_playMusic, "" },
     181        { &FWScript::o1_fadeOutMusic, "" },
     182        /* 70 */
     183        { &FWScript::o1_stopSample, "" },
     184        { &FWScript::o1_op71, "bw" },
     185        { &FWScript::o1_op72, "wbw" },
     186        { &FWScript::o1_op72, "wbw" },
     187        /* 74 */
     188        { 0, 0 },
     189        { 0, 0 },
     190        { 0, 0 },
     191        { &FWScript::o2_playSample, "bbwbww" },
     192        /* 78 */
     193        { &FWScript::o2_playSampleAlt, "bbwbww" },
     194        { &FWScript::o1_disableSystemMenu, "b" },
     195        { &FWScript::o1_loadMask5, "b" },
     196        { &FWScript::o1_unloadMask5, "b" },
     197        /* 7C */
     198        { 0, 0 },
     199        { 0, 0 },
     200        { 0, 0 },
     201        { &FWScript::o2_addSeqListElement, "bbbbwww" },
     202        /* 80 */
     203        { &FWScript::o2_removeSeq, "bb" },
     204        { &FWScript::o2_op81, "" },
     205        { &FWScript::o2_op82, "bbw" },
     206        { &FWScript::o2_isSeqRunning, "bb" },
     207        /* 84 */
     208        { &FWScript::o2_gotoIfSupNearest, "b" },
     209        { &FWScript::o2_gotoIfSupEquNearest, "b" },
     210        { &FWScript::o2_gotoIfInfNearest, "b" },
     211        { &FWScript::o2_gotoIfInfEquNearest, "b" },
     212        /* 88 */
     213        { &FWScript::o2_gotoIfEquNearest, "b" },
     214        { &FWScript::o2_gotoIfDiffNearest, "b" },
     215        { 0, 0 },
     216        { &FWScript::o2_startObjectScript, "b" },
     217        /* 8C */
     218        { &FWScript::o2_stopObjectScript, "b" },
     219        { &FWScript::o2_op8D, "wwwwwwww" },
     220        { &FWScript::o2_addBackground, "bs" },
     221        { &FWScript::o2_removeBackground, "b" },
     222        /* 90 */
     223        { &FWScript::o2_loadAbs, "bs" },
     224        { &FWScript::o2_loadBg, "b" },
     225        { 0, 0 },
     226        { 0, 0 },
     227        /* 94 */
     228        { 0, 0 },
     229        { &FWScript::o1_changeDataDisk, "b" },
     230        { 0, 0 },
     231        { 0, 0 },
     232        /* 98 */
     233        { 0, 0 },
     234        { 0, 0 },
     235        { &FWScript::o2_wasZoneChecked, "" },
     236        { &FWScript::o2_op9B, "wwwwwwww" },
     237        /* 9C */
     238        { &FWScript::o2_op9C, "wwww" },
     239        { &FWScript::o2_useBgScroll, "b" },
     240        { &FWScript::o2_setAdditionalBgVScroll, "c" },
     241        { &FWScript::o2_op9F, "ww" },
     242        /* A0 */
     243        { &FWScript::o2_addGfxElementA0, "ww" },
     244        { &FWScript::o2_removeGfxElementA0, "ww" },
     245        { &FWScript::o2_opA2, "ww" },
     246        { &FWScript::o2_opA3, "ww" },
     247        /* A4 */
     248        { &FWScript::o2_loadMask22, "b" },
     249        { &FWScript::o2_unloadMask22, "b" },
     250        { 0, 0 },
     251        { 0, 0 },
     252        /* A8 */
     253        { 0, 0 },
     254        { &FWScript::o1_changeDataDisk, "b" }
     255};
     256const unsigned int OSScript::_numOpcodes = ARRAYSIZE(OSScript::_opcodeTable);
     257
     258/*! \brief Contructor for global scripts
     259 * \param script Script bytecode reference
     260 * \param idx Script bytecode index
     261 */
     262OSScript::OSScript(const RawScript &script, int16 idx) :
     263        FWScript(script, idx, new OSScriptInfo) {}
     264
     265/*! \brief Constructor for object scripts
     266 * \param script Script bytecode reference
     267 * \param idx Script bytecode index
     268 */
     269OSScript::OSScript(RawObjectScript &script, int16 idx) :
     270        FWScript(script, idx, new OSScriptInfo) {}
     271
     272/*! \brief Copy constructor
     273 */
     274OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}
     275
     276/*! \brief Restore script state from savefile
     277 * \param labels Restored script labels
     278 * \param local Restored local script variables
     279 * \param compare Restored last comparison result
     280 * \param pos Restored script position
     281 */
     282void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {
     283        FWScript::load(labels, local, compare, pos);
     284}
     285
     286/*! \brief Get opcode info string
     287 * \param opcode Opcode to look for in opcode table
     288 */
     289const char *OSScriptInfo::opcodeInfo(byte opcode) const {
     290        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     291                return NULL;
     292        }
     293
     294        if (!OSScript::_opcodeTable[opcode - 1].args) {
     295                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeInfo", opcode - 1);
     296                return NULL;
     297        }
     298
     299        return OSScript::_opcodeTable[opcode - 1].args;
     300}
     301
     302/*! \brief Get opcode handler pointer
     303 * \param opcode Opcode to look for in opcode table
     304 */
     305opFunc OSScriptInfo::opcodeHandler(byte opcode) const {
     306        if (opcode == 0 || opcode > OSScript::_numOpcodes) {
     307                return NULL;
     308        }
     309
     310        if (!OSScript::_opcodeTable[opcode - 1].proc) {
     311                warning("Undefined opcode 0x%02X in OSScriptInfo::opcodeHandler", opcode - 1);
     312                return NULL;
     313        }
     314
     315        return OSScript::_opcodeTable[opcode - 1].proc;
     316}
     317
     318/*! \brief Create new OSScript instance
     319 * \param script Script bytecode
     320 * \param index Bytecode index
     321 */
     322FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {
     323        return new OSScript(script, index);
     324}
     325
     326/*! \brief Create new OSScript instance
     327 * \param script Object script bytecode
     328 * \param index Bytecode index
     329 */
     330FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {
     331        return new OSScript(script, index);
     332}
     333
     334/*! \brief Load saved OSScript instance
     335 * \param script Script bytecode
     336 * \param index Bytecode index
     337 * \param local Local variables
     338 * \param labels Script labels
     339 * \param compare Last compare result
     340 * \param pos Position in script
     341 */
     342FWScript *OSScriptInfo::create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     343        OSScript *tmp = new OSScript(script, index);
     344        assert(tmp);
     345        tmp->load(labels, local, compare, pos);
     346        return tmp;
     347}
     348
     349/*! \brief Load saved OSScript instance
     350 * \param script Object script bytecode
     351 * \param index Bytecode index
     352 * \param local Local variables
     353 * \param labels Script labels
     354 * \param compare Last compare result
     355 * \param pos Position in script
     356 */
     357FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const {
     358        OSScript *tmp = new OSScript(script, index);
     359        assert(tmp);
     360        tmp->load(labels, local, compare, pos);
     361        return tmp;
     362}
     363
     364// ------------------------------------------------------------------------
     365// OPERATION STEALTH opcodes
     366// ------------------------------------------------------------------------
     367
     368int FWScript::o2_loadPart() {
     369        const char *param = getNextString();
     370
     371        debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param);
     372        return 0;
     373}
     374
     375int FWScript::o2_playSample() {
     376        if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
     377                // no-op in these versions
     378                getNextByte();
     379                getNextByte();
     380                getNextWord();
     381                getNextByte();
     382                getNextWord();
     383                getNextWord();
     384                return 0;
     385        }
     386        return o1_playSample();
     387}
     388
     389int FWScript::o2_playSampleAlt() {
     390        byte num = getNextByte();
     391        byte channel = getNextByte();
     392        uint16 frequency = getNextWord();
     393        getNextByte();
     394        getNextWord();
     395        uint16 size = getNextWord();
     396
     397        if (size == 0xFFFF) {
     398                size = animDataTable[num]._width * animDataTable[num]._height;
     399        }
     400        if (animDataTable[num].data()) {
     401                if (g_cine->getPlatform() == Common::kPlatformPC) {
     402                        // if speaker output is available, play sound on it
     403                        // if it's another device, don't play anything
     404                        // TODO: implement this, it's used in the introduction for example
     405                        // on each letter displayed
     406                } else {
     407                        g_sound->playSound(channel, frequency, animDataTable[num].data(), size, 0, 0, 63, 0);
     408                }
     409        }
     410        return 0;
     411}
     412
     413int FWScript::o2_addSeqListElement() {
     414        byte param1 = getNextByte();
     415        byte param2 = getNextByte();
     416        byte param3 = getNextByte();
     417        byte param4 = getNextByte();
     418        uint16 param5 = getNextWord();
     419        uint16 param6 = getNextWord();
     420        uint16 param7 = getNextWord();
     421
     422        debugC(5, kCineDebugScript, "Line: %d: addSeqListElement(%d,%d,%d,%d,%d,%d,%d)", _line, param1, param2, param3, param4, param5, param6, param7);
     423        addSeqListElement(param1, 0, param2, param3, param4, param5, param6, 0, param7);
     424        return 0;
     425}
     426
     427int FWScript::o2_removeSeq() {
     428        byte a = getNextByte();
     429        byte b = getNextByte();
     430
     431        debugC(5, kCineDebugScript, "Line: %d: removeSeq(%d,%d) -> TODO", _line, a, b);
     432        removeSeq(a, 0, b);
     433        return 0;
     434}
     435
     436/*! \todo Implement this instruction
     437 */
     438int FWScript::o2_op81() {
     439        warning("STUB: o2_op81()");
     440        // freeUnkList();
     441        return 0;
     442}
     443
     444/*! \todo Implement this instruction
     445 */
     446int FWScript::o2_op82() {
     447        byte a = getNextByte();
     448        byte b = getNextByte();
     449        uint16 c = getNextWord();
     450        warning("STUB: o2_op82(%x, %x, %x)", a, b, c);
     451        return 0;
     452}
     453
     454int FWScript::o2_isSeqRunning() {
     455        byte a = getNextByte();
     456        byte b = getNextByte();
     457
     458        debugC(5, kCineDebugScript, "Line: %d: OP83(%d,%d) -> TODO", _line, a, b);
     459
     460        if (isSeqRunning(a, 0, b)) {
     461                _compare = 1;
     462        } else {
     463                _compare = 0;
     464        }
     465        return 0;
     466}
     467
     468/*! \todo The assert may produce false positives and requires testing
     469 */
     470int FWScript::o2_gotoIfSupNearest() {
     471        byte labelIdx = getNextByte();
     472
     473        if (_compare == kCmpGT) {
     474                assert(_labels[labelIdx] != -1);
     475
     476                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (true)", _line, labelIdx);
     477                _pos = _script.getLabel(*_info, labelIdx, _pos);
     478        } else {
     479                debugC(5, kCineDebugScript, "Line: %d: if(>) goto nearest %d (false)", _line, labelIdx);
     480        }
     481        return 0;
     482}
     483
     484/*! \todo The assert may produce false positives and requires testing
     485 */
     486int FWScript::o2_gotoIfSupEquNearest() {
     487        byte labelIdx = getNextByte();
     488
     489        if (_compare & (kCmpGT | kCmpEQ)) {
     490                assert(_labels[labelIdx] != -1);
     491
     492                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (true)", _line, labelIdx);
     493                _pos = _script.getLabel(*_info, labelIdx, _pos);
     494        } else {
     495                debugC(5, kCineDebugScript, "Line: %d: if(>=) goto nearest %d (false)", _line, labelIdx);
     496        }
     497        return 0;
     498}
     499
     500/*! \todo The assert may produce false positives and requires testing
     501 */
     502int FWScript::o2_gotoIfInfNearest() {
     503        byte labelIdx = getNextByte();
     504
     505        if (_compare == kCmpLT) {
     506                assert(_labels[labelIdx] != -1);
     507
     508                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (true)", _line, labelIdx);
     509                _pos = _script.getLabel(*_info, labelIdx, _pos);
     510        } else {
     511                debugC(5, kCineDebugScript, "Line: %d: if(<) goto nearest %d (false)", _line, labelIdx);
     512        }
     513        return 0;
     514}
     515
     516/*! \todo The assert may produce false positives and requires testing
     517 */
     518int FWScript::o2_gotoIfInfEquNearest() {
     519        byte labelIdx = getNextByte();
     520
     521        if (_compare & (kCmpLT | kCmpEQ)) {
     522                assert(_labels[labelIdx] != -1);
     523
     524                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (true)", _line, labelIdx);
     525                _pos = _script.getLabel(*_info, labelIdx, _pos);
     526        } else {
     527                debugC(5, kCineDebugScript, "Line: %d: if(<=) goto nearest %d (false)", _line, labelIdx);
     528        }
     529        return 0;
     530}
     531
     532/*! \todo The assert may produce false positives and requires testing
     533 */
     534int FWScript::o2_gotoIfEquNearest() {
     535        byte labelIdx = getNextByte();
     536
     537        if (_compare == kCmpEQ) {
     538                assert(_labels[labelIdx] != -1);
     539
     540                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (true)", _line, labelIdx);
     541                _pos = _script.getLabel(*_info, labelIdx, _pos);
     542        } else {
     543                debugC(5, kCineDebugScript, "Line: %d: if(==) goto nearest %d (false)", _line, labelIdx);
     544        }
     545        return 0;
     546}
     547
     548/*! \todo The assert may produce false positives and requires testing
     549 */
     550int FWScript::o2_gotoIfDiffNearest() {
     551        byte labelIdx = getNextByte();
     552
     553        if (_compare != kCmpEQ) {
     554                assert(_labels[labelIdx] != -1);
     555
     556                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (true)", _line, labelIdx);
     557                _pos = _script.getLabel(*_info, labelIdx, _pos);
     558        } else {
     559                debugC(5, kCineDebugScript, "Line: %d: if(!=) goto nearest %d (false)", _line, labelIdx);
     560        }
     561        return 0;
     562}
     563
     564int FWScript::o2_startObjectScript() {
     565        byte param = getNextByte();
     566
     567        debugC(5, kCineDebugScript, "Line: %d: startObjectScript(%d)", _line, param);
     568        runObjectScript(param);
     569        return 0;
     570}
     571
     572int FWScript::o2_stopObjectScript() {
     573        byte param = getNextByte();
     574
     575        debugC(5, kCineDebugScript, "Line: %d: stopObjectScript(%d)", _line, param);
     576        ScriptList::iterator it = objectScripts.begin();
     577
     578        for (; it != objectScripts.end(); ++it) {
     579                if ((*it)->_index == param) {
     580                        (*it)->_index = -1;
     581                }
     582        }
     583        return 0;
     584}
     585
     586/*! \todo Implement this instruction
     587 */
     588int FWScript::o2_op8D() {
     589        uint16 a = getNextWord();
     590        uint16 b = getNextWord();
     591        uint16 c = getNextWord();
     592        uint16 d = getNextWord();
     593        uint16 e = getNextWord();
     594        uint16 f = getNextWord();
     595        uint16 g = getNextWord();
     596        uint16 h = getNextWord();
     597        warning("STUB: o2_op8D(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
     598        // _currentScriptElement->compareResult = ...
     599        return 0;
     600}
     601
     602int FWScript::o2_addBackground() {
     603        byte param1 = getNextByte();
     604        const char *param2 = getNextString();
     605
     606        debugC(5, kCineDebugScript, "Line: %d: addBackground(%s,%d)", _line, param2, param1);
     607        addBackground(param2, param1);
     608        return 0;
     609}
     610
     611int FWScript::o2_removeBackground() {
     612        byte param = getNextByte();
     613
     614        assert(param);
     615
     616        debugC(5, kCineDebugScript, "Line: %d: removeBackground(%d)", _line, param);
     617
     618        if (additionalBgTable[param]) {
     619                free(additionalBgTable[param]);
     620                additionalBgTable[param] = NULL;
     621        }
     622
     623        if (currentAdditionalBgIdx == param) {
     624                currentAdditionalBgIdx = 0;
     625        }
     626
     627        if (currentAdditionalBgIdx2 == param) {
     628                currentAdditionalBgIdx2 = 0;
     629        }
     630
     631        strcpy(currentBgName[param], "");
     632        return 0;
     633}
     634
     635int FWScript::o2_loadAbs() {
     636        byte param1 = getNextByte();
     637        const char *param2 = getNextString();
     638
     639        debugC(5, kCineDebugScript, "Line: %d: loadABS(%d,%s)", _line, param1, param2);
     640        loadAbs(param2, param1);
     641        return 0;
     642}
     643
     644int FWScript::o2_loadBg() {
     645        byte param = getNextByte();
     646
     647        assert(param <= 8);
     648
     649        debugC(5, kCineDebugScript, "Line: %d: useBg(%d)", _line, param);
     650
     651        if (additionalBgTable[param]) {
     652                currentAdditionalBgIdx = param;
     653                if (param == 8) {
     654                        newColorMode = 3;
     655                } else {
     656                        newColorMode = bgColorMode + 1;
     657                }
     658                //if (_screenNeedFadeOut == 0) {
     659                //      adBgVar1 = 1;
     660                //}
     661                fadeRequired = true;
     662        }
     663        return 0;
     664}
     665
     666/*! \todo Implement this instruction
     667 */
     668int FWScript::o2_wasZoneChecked() {
     669        warning("STUB: o2_wasZoneChecked()");
     670        return 0;
     671}
     672
     673/*! \todo Implement this instruction
     674 */
     675int FWScript::o2_op9B() {
     676        uint16 a = getNextWord();
     677        uint16 b = getNextWord();
     678        uint16 c = getNextWord();
     679        uint16 d = getNextWord();
     680        uint16 e = getNextWord();
     681        uint16 f = getNextWord();
     682        uint16 g = getNextWord();
     683        uint16 h = getNextWord();
     684        warning("STUB: o2_op9B(%x, %x, %x, %x, %x, %x, %x, %x)", a, b, c, d, e, f, g, h);
     685        return 0;
     686}
     687
     688/*! \todo Implement this instruction
     689 */
     690int FWScript::o2_op9C() {
     691        uint16 a = getNextWord();
     692        uint16 b = getNextWord();
     693        uint16 c = getNextWord();
     694        uint16 d = getNextWord();
     695        warning("STUB: o2_op9C(%x, %x, %x, %x)", a, b, c, d);
     696        return 0;
     697}
     698
     699int FWScript::o2_useBgScroll() {
     700        byte param = getNextByte();
     701
     702        assert(param <= 8);
     703
     704        debugC(5, kCineDebugScript, "Line: %d: useBgScroll(%d)", _line, param);
     705
     706        if (additionalBgTable[param]) {
     707                currentAdditionalBgIdx2 = param;
     708        }
     709        return 0;
     710}
     711
     712int FWScript::o2_setAdditionalBgVScroll() {
     713        byte param1 = getNextByte();
     714
     715        if (param1) {
     716                byte param2 = getNextByte();
     717
     718                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = var[%d]", _line, param2);
     719                additionalBgVScroll = _localVars[param2];
     720        } else {
     721                uint16 param2 = getNextWord();
     722
     723                debugC(5, kCineDebugScript, "Line: %d: additionalBgVScroll = %d", _line, param2);
     724                additionalBgVScroll = param2;
     725        }
     726        return 0;
     727}
     728
     729/*! \todo Implement this instruction
     730 */
     731int FWScript::o2_op9F() {
     732        warning("o2_op9F()");
     733        getNextWord();
     734        getNextWord();
     735        return 0;
     736}
     737
     738int FWScript::o2_addGfxElementA0() {
     739        uint16 param1 = getNextWord();
     740        uint16 param2 = getNextWord();
     741
     742        debugC(5, kCineDebugScript, "Line: %d: addGfxElementA0(%d,%d)", _line, param1, param2);
     743        addGfxElementA0(param1, param2);
     744        return 0;
     745}
     746
     747/*! \todo Implement this instruction
     748 */
     749int FWScript::o2_removeGfxElementA0() {
     750        uint16 idx = getNextWord();
     751        uint16 param = getNextWord();
     752        warning("STUB? o2_removeGfxElementA0(%x, %x)", idx, param);
     753        removeGfxElementA0(idx, param);
     754        return 0;
     755}
     756
     757/*! \todo Implement this instruction
     758 */
     759int FWScript::o2_opA2() {
     760        uint16 a = getNextWord();
     761        uint16 b = getNextWord();
     762        warning("STUB: o2_opA2(%x, %x)", a, b);
     763        // addGfxElementA2();
     764        return 0;
     765}
     766
     767/*! \todo Implement this instruction
     768 */
     769int FWScript::o2_opA3() {
     770        uint16 a = getNextWord();
     771        uint16 b = getNextWord();
     772        warning("STUB: o2_opA3(%x, %x)", a, b);
     773        // removeGfxElementA2();
     774        return 0;
     775}
     776
     777int FWScript::o2_loadMask22() {
     778        byte param = getNextByte();
     779
     780        debugC(5, kCineDebugScript, "Line: %d: addOverlay22(%d)", _line, param);
     781        addOverlay(param, 22);
     782        return 0;
     783}
     784
     785int FWScript::o2_unloadMask22() {
     786        byte param = getNextByte();
     787
     788        debugC(5, kCineDebugScript, "Line: %d: removeOverlay22(%d)", _line, param);
     789        removeOverlay(param, 22);
     790        return 0;
     791}
     792
     793} // End of namespace Cine
  • engines/cine/object.cpp

     
    3737
    3838objectStruct objectTable[NUM_MAX_OBJECT];
    3939ScriptVars globalVars(NUM_MAX_VAR);
    40 overlayHeadElement overlayHead;
     40Common::List<overlay> overlayList;
    4141
    42 void unloadAllMasks(void) {
    43         overlayHeadElement *current = overlayHead.next;
    44 
    45         while (current) {
    46                 overlayHeadElement *next = current->next;
    47 
    48                 delete current;
    49 
    50                 current = next;
    51         }
    52 
    53         resetMessageHead();
    54 }
    55 
    56 void resetMessageHead(void) {
    57         overlayHead.next = NULL;
    58         overlayHead.previous = NULL;
    59 }
    60 
    6142void loadObject(char *pObjectName) {
    6243        uint16 numEntry;
    6344        uint16 entrySize;
     
    10081        free(dataPtr);
    10182}
    10283
    103 int8 removeOverlayElement(uint16 objIdx, uint16 param) {
    104         overlayHeadElement *currentHeadPtr = &overlayHead;
    105         overlayHeadElement *tempHead = currentHeadPtr;
    106         overlayHeadElement *tempPtr2;
     84/*! \brief Remove overlay sprite from the list
     85 * \param objIdx Remove overlay associated with this object
     86 * \param param Remove overlay of this type
     87 */
     88int removeOverlay(uint16 objIdx, uint16 param) {
     89        Common::List<overlay>::iterator it;
    10790
    108         currentHeadPtr = tempHead->next;
    109 
    110         while (currentHeadPtr && (currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param)) {
    111                 tempHead = currentHeadPtr;
    112                 currentHeadPtr = tempHead->next;
     91        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     92                if (it->objIdx == objIdx && it->type == param) {
     93                        overlayList.erase(it);
     94                        return 1;
     95                }
    11396        }
    11497
    115         if (!currentHeadPtr || currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param) {
    116                 return -1;
    117         }
     98        return 0;
     99}
    118100
    119         tempHead->next = tempPtr2 = currentHeadPtr->next;
     101/*! \brief Add new overlay sprite to the list
     102 * \param objIdx Associate the overlay with this object
     103 * \param param Type of new overlay
     104 * \todo Why are x, y, width and color left uninitialized?
     105 */
     106void addOverlay(uint16 objIdx, uint16 param) {
     107        Common::List<overlay>::iterator it;
     108        overlay tmp;
    120109
    121         if (!tempPtr2) {
    122                 tempPtr2 = &overlayHead;
     110        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     111                if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) {
     112                        break;
     113                }
    123114        }
    124115
    125         tempPtr2->previous = currentHeadPtr->previous;
     116        tmp.objIdx = objIdx;
     117        tmp.type = param;
    126118
    127         delete currentHeadPtr;
    128 
    129         return 0;
     119        overlayList.insert(it, tmp);
    130120}
    131121
    132 int16 freeOverlay(uint16 objIdx, uint16 param) {
    133         overlayHeadElement *currentHeadPtr = overlayHead.next;
    134         overlayHeadElement *previousPtr = &overlayHead;
    135         overlayHeadElement *tempPtr2;
     122/*! \brief Add new background mask overlay
     123 * \param objIdx Associate the overlay with this object
     124 * \param param source background index
     125 */
     126void addGfxElementA0(int16 objIdx, int16 param) {
     127        Common::List<overlay>::iterator it;
     128        overlay tmp;
    136129
    137         while (currentHeadPtr && ((currentHeadPtr->objIdx != objIdx) || (currentHeadPtr->type != param))) {
    138                 previousPtr = currentHeadPtr;
    139                 currentHeadPtr = previousPtr->next;
     130        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     131                // wtf?!
     132                if (objectTable[it->objIdx].mask == objectTable[objIdx].mask &&
     133                        (it->type == 2 || it->type == 3)) {
     134                        break;
     135                }
    140136        }
    141137
    142         if (!currentHeadPtr || !((currentHeadPtr->objIdx == objIdx) && (currentHeadPtr->type == param))) {
    143                 return -1;
     138        if (it != overlayList.end() && it->objIdx == objIdx && it->type == 20 && it->x == param) {
     139                return;
    144140        }
    145141
    146         previousPtr->next = tempPtr2 = currentHeadPtr->next;
     142        tmp.objIdx = objIdx;
     143        tmp.type = 20;
     144        tmp.x = param;
     145        tmp.y = 0;
     146        tmp.width = 0;
     147        tmp.color = 0;
    147148
    148         if (!tempPtr2) {
    149                 tempPtr2 = &overlayHead;
    150         }
    151 
    152         tempPtr2->previous = currentHeadPtr->previous;
    153 
    154         delete currentHeadPtr;
    155         return 0;
     149        overlayList.insert(it, tmp);
    156150}
    157151
    158 void loadOverlayElement(uint16 objIdx, uint16 param) {
    159         overlayHeadElement *currentHeadPtr = &overlayHead;
    160         overlayHeadElement *pNewElement;
     152/*! \brief Remove background mask overlay
     153 * \param objIdx Remove overlay associated with this object
     154 * \param param Remove overlay using this background
     155 * \todo Check that it works
     156 */
     157void removeGfxElementA0(int16 objIdx, int16 param) {
     158        Common::List<overlay>::iterator it;
    161159
    162         uint16 si = objectTable[objIdx].mask;
    163 
    164         overlayHeadElement *tempHead = currentHeadPtr;
    165 
    166         currentHeadPtr = tempHead->next;
    167 
    168         while (currentHeadPtr && (objectTable[currentHeadPtr->objIdx].mask < si)) {
    169                 tempHead = currentHeadPtr;
    170                 currentHeadPtr = tempHead->next;
     160        for (it = overlayList.begin(); it != overlayList.end(); ++it) {
     161                if (it->objIdx == objIdx && it->type == 20 && it->x == param) {
     162                        overlayList.erase(it);
     163                        return;
     164                }
    171165        }
    172 
    173         pNewElement = new overlayHeadElement;
    174 
    175         assert(pNewElement);
    176 
    177         pNewElement->next = tempHead->next;
    178         tempHead->next = pNewElement;
    179 
    180         pNewElement->objIdx = objIdx;
    181         pNewElement->type = param;
    182 
    183         if (!currentHeadPtr) {
    184                 currentHeadPtr = &overlayHead;
    185         }
    186 
    187         pNewElement->previous = currentHeadPtr->previous;
    188         currentHeadPtr->previous = pNewElement;
    189166}
    190167
    191168void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4) {
     
    194171        objectTable[objIdx].mask = param3;
    195172        objectTable[objIdx].frame = param4;
    196173
    197         if (!removeOverlayElement(objIdx, 0)) {
    198                 loadOverlayElement(objIdx, 0);
     174        if (removeOverlay(objIdx, 0)) {
     175                addOverlay(objIdx, 0);
    199176        }
    200177}
    201178
     
    223200        case 2:
    224201                objectTable[objIdx].mask = newValue;
    225202
    226                 if (!removeOverlayElement(objIdx, 0)) {
    227                         loadOverlayElement(objIdx, 0);
     203                if (removeOverlay(objIdx, 0)) {
     204                        addOverlay(objIdx, 0);
    228205                }
    229206                break;
    230207        case 3:
  • engines/cine/main_loop.cpp

     
    189189        quitFlag = 0;
    190190
    191191        if (_preLoad == false) {
    192                 resetMessageHead();
    193192                resetSeqList();
    194193                resetBgIncrustList();
    195194
     
    315314
    316315        hideMouse();
    317316        g_sound->stopMusic();
    318         unloadAllMasks();
    319317        // if (g_cine->getGameType() == Cine::GType_OS) {
    320318        //      freeUnkList();
    321319        // }
  • engines/cine/cine.cpp

     
    129129        globalScripts.clear();
    130130        bgIncrustList.clear();
    131131        freeAnimDataTable();
     132        overlayList.clear();
    132133
    133134        memset(objectTable, 0, sizeof(objectTable));
    134135        memset(messageTable, 0, sizeof(messageTable));
    135136
    136         overlayHead.next = overlayHead.previous = NULL;
    137 
    138137        var8 = 0;
    139 //      bgIncrustList = NULL;
    140138
    141139        var2 = var3 = var4 = var5 = 0;
    142140
  • engines/cine/gfx.cpp

     
    168168                byte *destPtr = page + x + y * 320;
    169169                destPtr += i * 320;
    170170
    171                 for (j = 0; j < width * 8; j++) {
     171                for (j = 0; j < width; j++) {
    172172                        if (x + j >= 0 && x + j < 320 && i + y >= 0
    173173                            && i + y < 200) {
    174174                                if (!*(spritePtr++)) {
     
    191191                byte *destPtr = page + x + y * 320;
    192192                destPtr += i * 320;
    193193
    194                 for (j = 0; j < width * 8; j++) {
     194                for (j = 0; j < width; j++) {
    195195                        if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && *maskPtr == 0) {
    196196                                *destPtr = *spritePtr;
    197197                        }
     
    202202        }
    203203}
    204204
    205 void gfxUpdateSpriteMask(const byte *spritePtr, const byte *spriteMskPtr, int16 width, int16 height, const byte *maskPtr,
    206         int16 maskWidth, int16 maskHeight, byte *bufferSprPtr, byte *bufferMskPtr, int16 xs, int16 ys, int16 xm, int16 ym, byte maskIdx) {
     205void gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *srcMask, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight) {
    207206        int16 i, j, d, spritePitch, maskPitch;
    208207
    209         width *= 8;
    210         maskWidth *= 8;
    211 
    212208        spritePitch = width;
    213209        maskPitch = maskWidth;
    214210
    215         if (maskIdx == 0) {
    216                 memcpy(bufferSprPtr, spritePtr, spritePitch * height);
    217                 memcpy(bufferMskPtr, spriteMskPtr, spritePitch * height);
    218         }
    219 
    220         if (ys > ym) {
    221                 d = ys - ym;
    222                 maskPtr += d * maskPitch;
     211        // crop update area to overlapping parts of masks
     212        if (y > ym) {
     213                d = y - ym;
     214                srcMask += d * maskPitch;
    223215                maskHeight -= d;
    224         }
    225         if (maskHeight <= 0) {
    226                 return;
    227         }
    228         if (xs > xm) {
    229                 d = xs - xm;
    230                 maskPtr += d;
    231                 maskWidth -= d;
    232         }
    233         if (maskWidth <= 0) {
    234                 return;
    235         }
    236         if (ys < ym) {
    237                 d = ym - ys;
    238                 spriteMskPtr += d * spritePitch;
    239                 bufferMskPtr += d * spritePitch;
     216        } else if (y < ym) {
     217                d = ym - y;
     218                destMask += d * spritePitch;
    240219                height -= d;
    241220        }
    242         if (height <= 0) {
    243                 return;
    244         }
    245         if (xs < xm) {
    246                 d = xm - xs;
    247                 spriteMskPtr += d;
    248                 bufferMskPtr += d;
     221
     222        if (x > xm) {
     223                d = x - xm;
     224                srcMask += d;
     225                maskWidth -= d;
     226        } else if (x < xm) {
     227                d = xm - x;
     228                destMask += d;
    249229                width -= d;
    250230        }
    251         if (width <= 0) {
    252                 return;
    253         }
     231
     232        // update mask
    254233        for (j = 0; j < MIN(maskHeight, height); ++j) {
    255234                for (i = 0; i < MIN(maskWidth, width); ++i) {
    256                         bufferMskPtr[i] |= maskPtr[i] ^ 1;
     235                        destMask[i] |= srcMask[i] ^ 1;
    257236                }
    258                 bufferMskPtr += spritePitch;
    259                 maskPtr += maskPitch;
     237                destMask += spritePitch;
     238                srcMask += maskPitch;
    260239        }
    261240}
    262241
  • engines/cine/bg.cpp

     
    134134
    135135        additionalBgTable[bgIdx] = (byte *) malloc(320 * 200);
    136136
    137         debug("addBackground %d", bgIdx);
    138 
    139137        uint16 bpp = READ_BE_UINT16(ptr); ptr += 2;
    140138
    141139        if (bpp == 8) {
  • engines/cine/anim.h

     
    102102void loadResource(const char *animName);
    103103void loadAbs(const char *resourceName, uint16 idx);
    104104void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken);
     105void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
    105106
    106107} // End of namespace Cine
    107108
  • engines/cine/various.h

     
    149149
    150150extern int16 additionalBgVScroll;
    151151
     152void removeSeq(uint16 param1, uint16 param2, uint16 param3);
     153uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3);
    152154void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8);
    153155void resetSeqList();
    154156void processSeqList(void);