Ticket #8853: message.patch
File message.patch, 87.5 KB (added by , 17 years ago) |
---|
-
engines/cine/script_fw.cpp
24 24 */ 25 25 26 26 /*! \file 27 * Script interpreter file27 * Future Wars script interpreter file 28 28 */ 29 29 30 30 #include "common/endian.h" … … 38 38 39 39 namespace Cine { 40 40 41 ScriptVars globalVars(NUM_MAX_VAR); 42 41 43 uint16 compareVars(int16 a, int16 b); 42 44 void palRotate(byte a, byte b, byte c); 43 45 void removeSeq(uint16 param1, uint16 param2, uint16 param3); … … 161 163 { &FWScript::o1_declareFunctionName, "s" }, 162 164 { &FWScript::o1_freePartRange, "bb" }, 163 165 { &FWScript::o1_unloadAllMasks, "" }, 164 / /5C */166 /* 5C */ 165 167 { 0, 0 }, 166 168 { 0, 0 }, 167 169 { 0, 0 }, … … 204 206 }; 205 207 const unsigned int FWScript::_numOpcodes = ARRAYSIZE(FWScript::_opcodeTable); 206 208 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 425 209 FWScriptInfo *scriptInfo; ///< Script factory 426 210 RawScriptArray scriptTable; ///< Table of script bytecode 427 211 … … 898 682 fHandle.writeUint16BE(_index); 899 683 } 900 684 901 /*! \brief Contructor for global scripts902 * \param script Script bytecode reference903 * \param idx Script bytecode index904 */905 OSScript::OSScript(const RawScript &script, int16 idx) :906 FWScript(script, idx, new OSScriptInfo) {}907 908 /*! \brief Constructor for object scripts909 * \param script Script bytecode reference910 * \param idx Script bytecode index911 */912 OSScript::OSScript(RawObjectScript &script, int16 idx) :913 FWScript(script, idx, new OSScriptInfo) {}914 915 /*! \brief Copy constructor916 */917 OSScript::OSScript(const OSScript &src) : FWScript(src, new OSScriptInfo) {}918 919 /*! \brief Restore script state from savefile920 * \param labels Restored script labels921 * \param local Restored local script variables922 * \param compare Restored last comparison result923 * \param pos Restored script position924 */925 void OSScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) {926 FWScript::load(labels, local, compare, pos);927 }928 685 /*! \brief Get opcode info string 929 686 * \param opcode Opcode to look for in opcode table 930 687 */ … … 1003 760 return tmp; 1004 761 } 1005 762 1006 /*! \brief Get opcode info string1007 * \param opcode Opcode to look for in opcode table1008 */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 pointer1023 * \param opcode Opcode to look for in opcode table1024 */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 instance1039 * \param script Script bytecode1040 * \param index Bytecode index1041 */1042 FWScript *OSScriptInfo::create(const RawScript &script, int16 index) const {1043 return new OSScript(script, index);1044 }1045 1046 /*! \brief Create new OSScript instance1047 * \param script Object script bytecode1048 * \param index Bytecode index1049 */1050 FWScript *OSScriptInfo::create(const RawObjectScript &script, int16 index) const {1051 return new OSScript(script, index);1052 }1053 1054 /*! \brief Load saved OSScript instance1055 * \param script Script bytecode1056 * \param index Bytecode index1057 * \param local Local variables1058 * \param labels Script labels1059 * \param compare Last compare result1060 * \param pos Position in script1061 */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 instance1070 * \param script Object script bytecode1071 * \param index Bytecode index1072 * \param local Local variables1073 * \param labels Script labels1074 * \param compare Last compare result1075 * \param pos Position in script1076 */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 1084 763 // ------------------------------------------------------------------------ 1085 764 // FUTURE WARS opcodes 1086 765 // ------------------------------------------------------------------------ … … 1375 1054 byte param = getNextByte(); 1376 1055 1377 1056 debugC(5, kCineDebugScript, "Line: %d: addSpriteOverlay(%d)", _line, param); 1378 loadOverlayElement(param, 0);1057 addOverlay(param, 0); 1379 1058 return 0; 1380 1059 } 1381 1060 … … 1383 1062 byte param = getNextByte(); 1384 1063 1385 1064 debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay(%d)", _line, param); 1386 freeOverlay(param, 0);1065 removeOverlay(param, 0); 1387 1066 return 0; 1067 return 0; 1388 1068 } 1389 1069 1390 1070 int FWScript::o1_addToBgList() { … … 1399 1079 byte param = getNextByte(); 1400 1080 1401 1081 debugC(5, kCineDebugScript, "Line: %d: addOverlay1(%d)", _line, param); 1402 loadOverlayElement(param, 1);1082 addOverlay(param, 1); 1403 1083 return 0; 1404 1084 } 1405 1085 … … 1407 1087 byte param = getNextByte(); 1408 1088 1409 1089 debugC(5, kCineDebugScript, "Line: %d: removeOverlay1(%d)", _line, param); 1410 freeOverlay(param, 1);1090 removeOverlay(param, 1); 1411 1091 return 0; 1412 1092 } 1413 1093 … … 1415 1095 byte param = getNextByte(); 1416 1096 1417 1097 debugC(5, kCineDebugScript, "Line: %d: addOverlayType4(%d)", _line, param); 1418 loadOverlayElement(param, 4);1098 addOverlay(param, 4); 1419 1099 return 0; 1420 1100 } 1421 1101 … … 1423 1103 byte param = getNextByte(); 1424 1104 1425 1105 debugC(5, kCineDebugScript, "Line: %d: removeSpriteOverlay4(%d)", _line, param); 1426 freeOverlay(param, 4);1106 removeOverlay(param, 4); 1427 1107 return 0; 1428 1108 } 1429 1109 … … 1825 1505 1826 1506 int FWScript::o1_unloadAllMasks() { 1827 1507 debugC(5, kCineDebugScript, "Line: %d: unloadAllMasks()", _line); 1828 unloadAllMasks();1508 overlayList.clear(); 1829 1509 return 0; 1830 1510 } 1831 1511 … … 2034 1714 byte param = getNextByte(); 2035 1715 2036 1716 debugC(5, kCineDebugScript, "Line: %d: addOverlay5(%d)", _line, param); 2037 loadOverlayElement(param, 5);1717 addOverlay(param, 5); 2038 1718 return 0; 2039 1719 } 2040 1720 … … 2042 1722 byte param = getNextByte(); 2043 1723 2044 1724 debugC(5, kCineDebugScript, "Line: %d: freeOverlay5(%d)", _line, param); 2045 freeOverlay(param, 5);1725 removeOverlay(param, 5); 2046 1726 return 0; 2047 1727 } 2048 1728 2049 // ------------------------------------------------------------------------2050 // OPERATION STEALTH opcodes2051 // ------------------------------------------------------------------------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 versions2063 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 it2088 // if it's another device, don't play anything2089 // TODO: implement this, it's used in the introduction for example2090 // on each letter displayed2091 } 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 instruction2122 */2123 int FWScript::o2_op81() {2124 warning("STUB: o2_op81()");2125 // freeUnkList();2126 return 0;2127 }2128 2129 /*! \todo Implement this instruction2130 */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 testing2154 */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 testing2170 */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 testing2186 */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 testing2202 */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 testing2218 */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 testing2234 */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 instruction2272 */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 instruction2352 */2353 int FWScript::o2_wasZoneChecked() {2354 warning("STUB: o2_wasZoneChecked()");2355 return 0;2356 }2357 2358 /*! \todo Implement this instruction2359 */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 instruction2374 */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 instruction2415 */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 instruction2433 */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 instruction2443 */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 instruction2453 */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 2478 1729 //----------------------------------------------------------------------- 2479 1730 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 works2523 */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 2573 1731 void palRotate(byte a, byte b, byte c) { 2574 1732 if (c == 1) { 2575 1733 uint16 currentColor = c_palette[b]; -
engines/cine/script.h
358 358 359 359 extern RawScriptArray scriptTable; 360 360 extern FWScriptInfo *scriptInfo; 361 extern ScriptVars globalVars; 361 362 362 363 void setupOpcodes(); 363 364 -
engines/cine/module.mk
14 14 part.o \ 15 15 prc.o \ 16 16 rel.o \ 17 script.o \ 17 script_fw.o \ 18 script_os.o \ 18 19 sound.o \ 19 20 texte.o \ 20 21 unpack.o \ -
engines/cine/object.h
40 40 uint16 part; 41 41 }; 42 42 43 struct overlayHeadElement { 44 struct overlayHeadElement *next; 45 struct overlayHeadElement *previous; 43 struct overlay { 46 44 uint16 objIdx; 47 45 uint16 type; 48 46 int16 x; … … 55 53 #define NUM_MAX_VAR 256 56 54 57 55 extern objectStruct objectTable[NUM_MAX_OBJECT]; 58 extern ScriptVars globalVars;59 56 60 extern overlayHeadElement overlayHead;57 extern Common::List<overlay> overlayList; 61 58 62 void unloadAllMasks(void);63 void resetMessageHead(void);64 65 59 void loadObject(char *pObjectName); 66 60 void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4); 67 61 void modifyObjectParam(byte objIdx, byte paramIdx, int16 newValue); 68 62 69 void loadOverlayElement(uint16 objIdx, uint16 param); 70 int8 removeOverlayElement(uint16 objIdx, uint16 param); 63 void addOverlay(uint16 objIdx, uint16 param); 64 int removeOverlay(uint16 objIdx, uint16 param); 65 void addGfxElementA0(int16 objIdx, int16 param); 66 void removeGfxElementA0(int16 objIdx, int16 param); 71 67 72 68 int16 getObjectParam(uint16 objIdx, uint16 paramIdx); 73 int16 freeOverlay(uint16 objIdx, uint16 param);74 69 75 70 void addObjectParam(byte objIdx, byte paramIdx, int16 newValue); 76 71 void subObjectParam(byte objIdx, byte paramIdx, int16 newValue); -
engines/cine/bg_list.cpp
77 77 void addSpriteFilledToBGList(int16 objIdx, bool addList) { 78 78 int16 x = objectTable[objIdx].x; 79 79 int16 y = objectTable[objIdx].y; 80 int16 width = animDataTable[objectTable[objIdx].frame]._ width;80 int16 width = animDataTable[objectTable[objIdx].frame]._realWidth; 81 81 int16 height = animDataTable[objectTable[objIdx].frame]._height; 82 82 const byte *data = animDataTable[objectTable[objIdx].frame].data(); 83 83 … … 86 86 if (g_cine->getGameType() == GType_OS) { 87 87 for (int i = 0; i < 8; i++) { 88 88 if (additionalBgTable[i]) { 89 gfxFillSprite(data, width / 2, height, additionalBgTable[i], x, y);89 gfxFillSprite(data, width, height, additionalBgTable[i], x, y); 90 90 } 91 91 } 92 92 } else { 93 gfxFillSprite(data, width / 2, height, page2Raw, x, y);93 gfxFillSprite(data, width, height, page2Raw, x, y); 94 94 } 95 95 } 96 96 -
engines/cine/anim.cpp
186 186 }; 187 187 188 188 void convertMask(byte *dest, const byte *source, int16 width, int16 height); 189 void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);190 189 void convert8BBP(byte *dest, const byte *source, int16 width, int16 height); 191 190 void convert8BBP2(byte *dest, byte *source, int16 width, int16 height); 192 191 -
engines/cine/msg.cpp
31 31 32 32 namespace Cine { 33 33 34 uint16 messageCount;34 Common::StringList messageTable; 35 35 36 36 void loadMsg(char *pMsgName) { 37 uint16 i;37 int i, count, len; 38 38 byte *ptr, *dataPtr; 39 const char *messagePtr; 39 40 40 41 checkDataDisk(-1); 41 42 42 message Count = 0;43 messageTable.clear(); 43 44 44 for (i = 0; i < NUM_MAX_MESSAGE; i++) {45 messageTable[i].len = 0;46 if (messageTable[i].ptr) {47 free(messageTable[i].ptr);48 messageTable[i].ptr = NULL;49 }50 }51 52 45 ptr = dataPtr = readBundleFile(findFileInBundle(pMsgName)); 53 46 54 47 setMouseCursor(MOUSE_CURSOR_DISK); 55 48 56 messageCount = READ_BE_UINT16(ptr); ptr += 2; 49 count = READ_BE_UINT16(ptr); 50 ptr += 2; 57 51 58 assert(messageCount <= NUM_MAX_MESSAGE);52 messagePtr = (const char*)(ptr + 2 * count); 59 53 60 for (i = 0; i < messageCount; i++) { 61 messageTable[i].len = READ_BE_UINT16(ptr); ptr += 2; 54 for (i = 0; i < count; i++) { 55 len = READ_BE_UINT16(ptr); 56 ptr += 2; 57 58 messageTable.push_back(messagePtr); 59 messagePtr += len; 62 60 } 63 61 64 for (i = 0; i < messageCount; i++) {65 if (messageTable[i].len) {66 messageTable[i].ptr = (byte *) malloc(messageTable[i].len);67 68 assert(messageTable[i].ptr);69 70 memcpy(messageTable[i].ptr, ptr, messageTable[i].len);71 ptr += messageTable[i].len;72 }73 }74 75 62 free(dataPtr); 76 63 } 77 64 -
engines/cine/various.cpp
44 44 int16 commandVar1; 45 45 int16 commandVar2; 46 46 47 Message messageTable[NUM_MAX_MESSAGE];47 //Message messageTable[NUM_MAX_MESSAGE]; 48 48 49 49 uint16 var2; 50 50 uint16 var3; … … 130 130 objectScripts.push_back(tmp); 131 131 } 132 132 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 */ 133 137 void addPlayerCommandMessage(int16 cmd) { 134 overlay HeadElement *currentHeadPtr = overlayHead.next;135 overlayHeadElement *tempHead = &overlayHead;136 overlayHeadElement *pNewElement;138 overlay tmp; 139 tmp.objIdx = cmd; 140 tmp.type = 3; 137 141 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); 159 143 } 160 144 161 145 int16 getRelEntryForObject(uint16 param1, uint16 param2, SelectedObjStruct *pSelectedObject) { … … 180 164 return found; 181 165 } 182 166 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 */ 183 172 int16 getObjectUnderCursor(uint16 x, uint16 y) { 184 overlayHeadElement *currentHead = overlayHead.previous;173 Common::List<overlay>::iterator it; 185 174 186 175 int16 objX, objY, frame, part, threshold, height, xdif, ydif; 187 176 int width; 188 177 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 } 194 183 195 frame = ABS((int16)(objectTable[currentHead->objIdx].frame)); 184 objX = objectTable[it->objIdx].x; 185 objY = objectTable[it->objIdx].y; 196 186 197 part = objectTable[currentHead->objIdx].part; 187 frame = ABS((int16)(objectTable[it->objIdx].frame)); 188 part = objectTable[it->objIdx].part; 198 189 199 if (currentHead->type == 0) {200 201 202 203 190 if (it->type == 0) { 191 threshold = animDataTable[frame]._var1; 192 } else { 193 threshold = animDataTable[frame]._width / 2; 194 } 204 195 205 206 196 height = animDataTable[frame]._height; 197 width = animDataTable[frame]._realWidth; 207 198 208 209 199 xdif = x - objX; 200 ydif = y - objY; 210 201 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; 229 204 } 230 205 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 } 232 225 } 233 226 234 227 return -1; … … 285 278 } 286 279 } 287 280 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 */ 284 void loadOverlayFromSave(Common::InSaveFile &fHandle) { 285 overlay tmp; 292 286 293 currentHead = tempHead->next; 287 fHandle.readUint32BE(); 288 fHandle.readUint32BE(); 294 289 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(); 299 296 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); 320 298 } 321 299 322 300 /*! \brief Savefile format tester … … 433 411 434 412 g_sound->stopMusic(); 435 413 freeAnimDataTable(); 436 unloadAllMasks();414 overlayList.clear(); 437 415 // if (g_cine->getGameType() == Cine::GType_OS) { 438 416 // freeUnkList(); 439 417 // } … … 444 422 globalScripts.clear(); 445 423 relTable.clear(); 446 424 scriptTable.clear(); 425 messageTable.clear(); 447 426 448 for (i = 0; i < NUM_MAX_MESSAGE; i++) {449 messageTable[i].len = 0;450 451 if (messageTable[i].ptr) {452 free(messageTable[i].ptr);453 messageTable[i].ptr = NULL;454 }455 }456 457 427 for (i = 0; i < NUM_MAX_OBJECT; i++) { 458 428 objectTable[i].part = 0; 459 429 objectTable[i].name[0] = 0; … … 599 569 600 570 size = fHandle->readSint16BE(); 601 571 for (i = 0; i < size; i++) { 602 loadOverlayFromSave( fHandle);572 loadOverlayFromSave(*fHandle); 603 573 } 604 574 605 575 loadBgIncrustFromSave(*fHandle); … … 722 692 } 723 693 724 694 { 725 int16 numScript = 0; 726 overlayHeadElement *currentHead = overlayHead.next; 695 Common::List<overlay>::iterator it; 727 696 728 while (currentHead) { 729 numScript++; 730 currentHead = currentHead->next; 731 } 697 fHandle->writeUint16BE(overlayList.size()); 732 698 733 fHandle->writeUint16BE(numScript); 734 735 // actual save 736 currentHead = overlayHead.next; 737 738 while (currentHead) { 699 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 739 700 fHandle->writeUint32BE(0); 740 701 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; 702 fHandle->writeUint16BE(it->objIdx); 703 fHandle->writeUint16BE(it->type); 704 fHandle->writeSint16BE(it->x); 705 fHandle->writeSint16BE(it->y); 706 fHandle->writeSint16BE(it->width); 707 fHandle->writeSint16BE(it->color); 749 708 } 750 709 } 751 710 … … 762 721 fHandle->writeUint16BE(it->frame); 763 722 fHandle->writeUint16BE(it->part); 764 723 } 765 /*766 int numBgIncrustList = 0;767 BGIncrustList *bgIncrustPtr = bgIncrustList;768 724 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); // next778 fHandle->writeUint32BE(0); // unkPtr779 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 790 725 delete fHandle; 791 726 792 727 setMouseCursor(MOUSE_CURSOR_NORMAL); … … 1682 1617 return var_5E; 1683 1618 } 1684 1619 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; 1620 void drawSprite(Common::List<overlay>::iterator it, const byte *spritePtr, const byte *maskPtr, uint16 width, uint16 height, byte *page, int16 x, int16 y) { 1688 1621 byte *msk = NULL; 1689 byte i = 0;1690 uint16 si = 0;1691 overlayHeadElement *pCurrentOverlay = currentOverlay;1692 1622 int16 maskX, maskY, maskWidth, maskHeight; 1693 1623 uint16 maskSpriteIdx; 1694 1624 1625 msk = (byte *)malloc(width * height); 1626 1695 1627 if (g_cine->getGameType() == Cine::GType_OS) { 1696 drawSpriteRaw2(spritePtr, objectTable[currentOverlay->objIdx].part, width, height, page, x, y); 1697 return; 1628 generateMask(spritePtr, msk, width * height, objectTable[it->objIdx].part); 1629 } else { 1630 memcpy(msk, maskPtr, width * height); 1698 1631 } 1699 1632 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 } 1633 for (++it; it != overlayList.end(); ++it) { 1634 if (it->type != 5) { 1635 continue; 1636 } 1707 1637 1708 maskX = objectTable[pCurrentOverlay->objIdx].x;1709 maskY = objectTable[pCurrentOverlay->objIdx].y;1638 maskX = objectTable[it->objIdx].x; 1639 maskY = objectTable[it->objIdx].y; 1710 1640 1711 maskSpriteIdx = objectTable[pCurrentOverlay->objIdx].frame;1641 maskSpriteIdx = ABS((int16)(objectTable[it->objIdx].frame)); 1712 1642 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++); 1643 maskWidth = animDataTable[maskSpriteIdx]._realWidth; 1644 maskHeight = animDataTable[maskSpriteIdx]._height; 1645 gfxUpdateSpriteMask(msk, x, y, width, height, animDataTable[maskSpriteIdx].data(), maskX, maskY, maskWidth, maskHeight); 1646 1716 1647 #ifdef DEBUG_SPRITE_MASK 1717 1648 gfxFillSprite(animDataTable[maskSpriteIdx].data(), maskWidth, maskHeight, page, maskX, maskY, 1); 1718 1649 #endif 1719 }1720 1721 pCurrentOverlay = pCurrentOverlay->next;1722 1650 } 1723 1651 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 } 1652 gfxDrawMaskedSprite(spritePtr, msk, width, height, page, x, y); 1653 free(msk); 1731 1654 } 1732 1655 1733 1656 int16 additionalBgVScroll = 0; … … 1824 1747 } 1825 1748 1826 1749 void drawDialogueMessage(byte msgIdx, int16 x, int16 y, int16 width, int16 color) { 1827 const char *messagePtr = (const char *)messageTable[msgIdx].ptr; 1828 1829 if (!messagePtr) { 1830 freeOverlay(msgIdx, 2); 1750 if (msgIdx >= messageTable.size()) { 1751 removeOverlay(msgIdx, 2); 1831 1752 return; 1832 1753 } 1833 1754 1834 _messageLen += strlen(messagePtr); 1755 _messageLen += messageTable[msgIdx].size(); 1756 drawMessage(messageTable[msgIdx].c_str(), x, y, width, color); 1835 1757 1836 drawMessage(messagePtr, x, y, width, color); 1837 1838 freeOverlay(msgIdx, 2); 1758 removeOverlay(msgIdx, 2); 1839 1759 } 1840 1760 1841 1761 void drawFailureMessage(byte cmd) { … … 1857 1777 1858 1778 drawMessage(messagePtr, x, y, width, color); 1859 1779 1860 freeOverlay(cmd, 3);1780 removeOverlay(cmd, 3); 1861 1781 } 1862 1782 1863 /*! \todo Fix Operation Stealth logo in intro (the green text after the plane1864 * takes off). Each letter should slowly grow top-down, it has something to1865 * do with object 10 (some mask or something)1866 */1867 1783 void drawOverlays(void) { 1868 uint16 partVar1, partVar2;1784 uint16 width, height; 1869 1785 AnimData *pPart; 1870 overlayHeadElement *currentOverlay, *nextOverlay;1871 1786 int16 x, y; 1872 1787 objectStruct *objPtr; 1873 1788 byte messageIdx; 1874 int16 part;1789 Common::List<overlay>::iterator it; 1875 1790 1876 1791 backupOverlayPage(); 1877 1792 1878 1793 _messageLen = 0; 1879 1794 1880 currentOverlay = (&overlayHead)->next; 1795 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 1796 switch (it->type) { 1797 case 0: // sprite 1798 assert(it->objIdx < NUM_MAX_OBJECT); 1881 1799 1882 while (currentOverlay) { 1883 nextOverlay = currentOverlay->next; 1800 objPtr = &objectTable[it->objIdx]; 1801 x = objPtr->x; 1802 y = objPtr->y; 1884 1803 1885 switch (currentOverlay->type) { 1886 case 0: // sprite 1887 { 1888 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT); 1804 if (objPtr->frame < 0) { 1805 continue; 1806 } 1889 1807 1890 objPtr = &objectTable[currentOverlay->objIdx]; 1808 pPart = &animDataTable[objPtr->frame]; 1809 width = pPart->_realWidth; 1810 height = pPart->_height; 1891 1811 1892 x = objPtr->x; 1893 y = objPtr->y; 1812 if (!pPart->data()) { 1813 continue; 1814 } 1894 1815 1895 if (objPtr->frame >= 0) {1896 if (g_cine->getGameType() == Cine::GType_OS) {1897 pPart = &animDataTable[objPtr->frame];1816 // drawSprite ignores masks of Operation Stealth sprites 1817 drawSprite(it, pPart->data(), pPart->mask(), width, height, page1Raw, x, y); 1818 break; 1898 1819 1899 partVar1 = pPart->_var1; 1900 partVar2 = pPart->_height; 1820 case 2: // text 1821 // gfxWaitVSync(); 1822 // hideMouse(); 1901 1823 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; 1824 messageIdx = it->objIdx; 1825 x = it->x; 1826 y = it->y; 1827 width = it->width; 1828 height = it->color; 1909 1829 1910 assert(part >= 0 && part <= NUM_MAX_ANIMDATA);1830 blitRawScreen(page1Raw); 1911 1831 1912 pPart = &animDataTable[objPtr->frame];1832 drawDialogueMessage(messageIdx, x, y, width, height); 1913 1833 1914 partVar1 = pPart->_var1;1915 partVar2 = pPart->_height;1834 // blitScreen(page0, NULL); 1835 // gfxRedrawMouseCursor(); 1916 1836 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(); 1837 waitForPlayerClick = 1; 1928 1838 1929 messageIdx = currentOverlay->objIdx; 1930 x = currentOverlay->x; 1931 y = currentOverlay->y; 1932 partVar1 = currentOverlay->width; 1933 partVar2 = currentOverlay->color; 1839 break; 1934 1840 1935 blitRawScreen(page1Raw); 1841 case 3: 1842 // gfxWaitSync() 1843 // hideMouse(); 1936 1844 1937 drawDialogueMessage(messageIdx, x, y, partVar1, partVar2);1845 blitRawScreen(page1Raw); 1938 1846 1939 // blitScreen(page0, NULL); 1940 // gfxRedrawMouseCursor(); 1847 drawFailureMessage(it->objIdx); 1941 1848 1942 waitForPlayerClick = 1; 1849 // blitScreen(page0, NULL); 1850 // gfxRedrawMouseCursor(); 1943 1851 1944 break; 1945 } 1946 case 3: 1947 { 1948 // gfxWaitSync() 1949 // hideMouse(); 1852 waitForPlayerClick = 1; 1950 1853 1951 blitRawScreen(page1Raw);1854 break; 1952 1855 1953 drawFailureMessage(currentOverlay->objIdx); 1856 case 4: 1857 assert(it->objIdx < NUM_MAX_OBJECT); 1954 1858 1955 // blitScreen(page0, NULL); 1956 // gfxRedrawMouseCursor(); 1859 objPtr = &objectTable[it->objIdx]; 1860 x = objPtr->x; 1861 y = objPtr->y; 1957 1862 1958 waitForPlayerClick = 1; 1959 1960 break; 1863 if (objPtr->frame < 0) { 1864 continue; 1961 1865 } 1962 case 4:1963 {1964 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);1965 1866 1966 objPtr = &objectTable[currentOverlay->objIdx];1867 assert(objPtr->frame < NUM_MAX_ANIMDATA); 1967 1868 1968 x = objPtr->x; 1969 y = objPtr->y; 1869 pPart = &animDataTable[objPtr->frame]; 1970 1870 1871 width = pPart->_realWidth; 1872 height = pPart->_height; 1971 1873 1972 if (objPtr->frame >= 0) { 1973 part = objPtr->part; 1874 if (!pPart->data()) { 1875 continue; 1876 } 1974 1877 1975 assert(part >= 0 && part <= NUM_MAX_ANIMDATA); 1878 gfxFillSprite(pPart->data(), width, height, page1Raw, x, y); 1879 break; 1976 1880 1977 pPart = &animDataTable[objPtr->frame]; 1881 case 20: 1882 assert(it->objIdx < NUM_MAX_OBJECT); 1978 1883 1979 partVar1 = pPart->_width / 2; 1980 partVar2 = pPart->_height; 1884 objPtr = &objectTable[it->objIdx]; 1885 x = objPtr->x; 1886 y = objPtr->y; 1887 var5 = it->x; 1981 1888 1982 if (pPart->data()) { 1983 gfxFillSprite(pPart->data(), partVar1, partVar2, page1Raw, x, y); 1984 } 1985 } 1986 break; 1889 if (objPtr->frame < 0 || var5 > 8 || !additionalBgTable[var5] || animDataTable[objPtr->frame]._bpp != 1) { 1890 continue; 1987 1891 } 1988 case 20:1989 {1990 assert(currentOverlay->objIdx <= NUM_MAX_OBJECT);1991 1892 1992 objPtr = &objectTable[currentOverlay->objIdx]; 1893 width = animDataTable[objPtr->frame]._realWidth; 1894 height = animDataTable[objPtr->frame]._height; 1993 1895 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; 1896 if (!animDataTable[objPtr->frame].data()) { 1897 continue; 2011 1898 } 2012 }2013 1899 2014 currentOverlay = nextOverlay; 1900 maskBgOverlay(additionalBgTable[var5], animDataTable[objPtr->frame].data(), width, height, page1Raw, x, y); 1901 break; 1902 } 2015 1903 } 2016 1904 } 2017 1905 … … 2040 1928 } 2041 1929 2042 1930 if (newObjectName[0] != 0) { 2043 unloadAllMasks(); 2044 resetMessageHead(); 1931 overlayList.clear(); 2045 1932 2046 1933 loadObject(newObjectName); 2047 1934 … … 2071 1958 } 2072 1959 2073 1960 void addMessage(byte param1, int16 param2, int16 param3, int16 param4, int16 param5) { 2074 overlayHeadElement *currentHead = &overlayHead; 2075 overlayHeadElement *tempHead = currentHead; 2076 overlayHeadElement *newElement; 1961 overlay tmp; 2077 1962 2078 currentHead = tempHead->next; 1963 tmp.objIdx = param1; 1964 tmp.type = 2; 1965 tmp.x = param2; 1966 tmp.y = param3; 1967 tmp.width = param4; 1968 tmp.color = param5; 2079 1969 2080 while (currentHead) { 1970 overlayList.push_back(tmp); 1971 } 1972 1973 SeqListElement seqList; 1974 1975 void removeSeq(uint16 param1, uint16 param2, uint16 param3) { 1976 SeqListElement *currentHead = &seqList; 1977 SeqListElement *tempHead = currentHead; 1978 1979 while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { 2081 1980 tempHead = currentHead; 2082 1981 currentHead = tempHead->next; 2083 1982 } 2084 1983 2085 newElement = new overlayHeadElement; 1984 if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { 1985 currentHead->var4 = -1; 1986 } 1987 } 2086 1988 2087 newElement->next = tempHead->next; 2088 tempHead->next = newElement; 1989 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3) { 1990 SeqListElement *currentHead = &seqList; 1991 SeqListElement *tempHead = currentHead; 2089 1992 2090 newElement->objIdx = param1; 2091 newElement->type = 2; 1993 while (currentHead && (currentHead->var6 != param1 || currentHead->var4 != param2 || currentHead->varE != param3)) { 1994 tempHead = currentHead; 1995 currentHead = tempHead->next; 1996 } 2092 1997 2093 newElement->x = param2; 2094 newElement->y = param3; 2095 newElement->width = param4; 2096 newElement->color = param5; 1998 if (currentHead && currentHead->var6 == param1 && currentHead->var4 == param2 && currentHead->varE == param3) { 1999 return 1; 2000 } 2097 2001 2098 if (!currentHead) 2099 currentHead = &overlayHead; 2100 2101 newElement->previous = currentHead->previous; 2102 2103 currentHead->previous = newElement; 2002 return 0; 2104 2003 } 2105 2004 2106 SeqListElement seqList;2107 2108 2005 void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8) { 2109 2006 SeqListElement *currentHead = &seqList; 2110 2007 SeqListElement *tempHead = currentHead; -
engines/cine/gfx.h
53 53 void gfxDrawMaskedSprite(const byte *ptr, const byte *msk, uint16 width, uint16 height, byte *page, int16 x, int16 y); 54 54 void gfxFillSprite(const byte *src4, uint16 sw, uint16 sh, byte *dst4, int16 sx, int16 sy, uint8 fillColor = 0); 55 55 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); 56 void gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *maskPtr, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight); 58 57 59 58 void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page); 60 59 void gfxDrawPlainBox(int16 x1, int16 y1, int16 x2, int16 y2, byte color); -
engines/cine/xref.txt
144 144 reincrustAllBg() - removed (obsoleted by new loadResourcesFromSave() and 145 145 loadBgIncrustFromSave() implementation) 146 146 freeBgIncrustList() - removed (obsoleted by Common::List::clear()) 147 148 object.cpp 149 unloadAllMasks() - removed (obsoleted by Common::List::clear()) 150 resetMessageHead() - removed (obsoleted by Common::List) 151 freeOverlay() - removed (duplicate of removeOverlay) 152 removeOverlayElement() - renamed to removeOverlay 153 loadOverlayElement() - 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 39 namespace Cine { 40 41 const 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 }; 256 const 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 */ 262 OSScript::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 */ 269 OSScript::OSScript(RawObjectScript &script, int16 idx) : 270 FWScript(script, idx, new OSScriptInfo) {} 271 272 /*! \brief Copy constructor 273 */ 274 OSScript::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 */ 282 void 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 */ 289 const 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 */ 305 opFunc 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 */ 322 FWScript *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 */ 330 FWScript *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 */ 342 FWScript *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 */ 357 FWScript *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 368 int FWScript::o2_loadPart() { 369 const char *param = getNextString(); 370 371 debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _line, param); 372 return 0; 373 } 374 375 int 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 389 int 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 413 int 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 427 int 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 */ 438 int FWScript::o2_op81() { 439 warning("STUB: o2_op81()"); 440 // freeUnkList(); 441 return 0; 442 } 443 444 /*! \todo Implement this instruction 445 */ 446 int 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 454 int 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 */ 470 int 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 */ 486 int 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 */ 502 int 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 */ 518 int 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 */ 534 int 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 */ 550 int 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 564 int 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 572 int 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 */ 588 int 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 602 int 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 611 int 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 635 int 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 644 int 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 */ 668 int FWScript::o2_wasZoneChecked() { 669 warning("STUB: o2_wasZoneChecked()"); 670 return 0; 671 } 672 673 /*! \todo Implement this instruction 674 */ 675 int 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 */ 690 int 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 699 int 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 712 int 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 */ 731 int FWScript::o2_op9F() { 732 warning("o2_op9F()"); 733 getNextWord(); 734 getNextWord(); 735 return 0; 736 } 737 738 int 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 */ 749 int 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 */ 759 int 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 */ 769 int 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 777 int 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 785 int 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
36 36 namespace Cine { 37 37 38 38 objectStruct objectTable[NUM_MAX_OBJECT]; 39 ScriptVars globalVars(NUM_MAX_VAR); 40 overlayHeadElement overlayHead; 39 Common::List<overlay> overlayList; 41 40 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 61 41 void loadObject(char *pObjectName) { 62 42 uint16 numEntry; 63 43 uint16 entrySize; … … 100 80 free(dataPtr); 101 81 } 102 82 103 int8 removeOverlayElement(uint16 objIdx, uint16 param) { 104 overlayHeadElement *currentHeadPtr = &overlayHead; 105 overlayHeadElement *tempHead = currentHeadPtr; 106 overlayHeadElement *tempPtr2; 83 /*! \brief Remove overlay sprite from the list 84 * \param objIdx Remove overlay associated with this object 85 * \param param Remove overlay of this type 86 */ 87 int removeOverlay(uint16 objIdx, uint16 param) { 88 Common::List<overlay>::iterator it; 107 89 108 currentHeadPtr = tempHead->next;109 110 while (currentHeadPtr && (currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param)) {111 tempHead = currentHeadPtr;112 currentHeadPtr = tempHead->next;90 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 91 if (it->objIdx == objIdx && it->type == param) { 92 overlayList.erase(it); 93 return 1; 94 } 113 95 } 114 96 115 if (!currentHeadPtr || currentHeadPtr->objIdx != objIdx || currentHeadPtr->type != param) { 116 return -1; 117 } 97 return 0; 98 } 118 99 119 tempHead->next = tempPtr2 = currentHeadPtr->next; 100 /*! \brief Add new overlay sprite to the list 101 * \param objIdx Associate the overlay with this object 102 * \param param Type of new overlay 103 * \todo Why are x, y, width and color left uninitialized? 104 */ 105 void addOverlay(uint16 objIdx, uint16 param) { 106 Common::List<overlay>::iterator it; 107 overlay tmp; 120 108 121 if (!tempPtr2) { 122 tempPtr2 = &overlayHead; 109 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 110 if (objectTable[it->objIdx].mask >= objectTable[objIdx].mask) { 111 break; 112 } 123 113 } 124 114 125 tempPtr2->previous = currentHeadPtr->previous; 115 tmp.objIdx = objIdx; 116 tmp.type = param; 126 117 127 delete currentHeadPtr; 128 129 return 0; 118 overlayList.insert(it, tmp); 130 119 } 131 120 132 int16 freeOverlay(uint16 objIdx, uint16 param) { 133 overlayHeadElement *currentHeadPtr = overlayHead.next; 134 overlayHeadElement *previousPtr = &overlayHead; 135 overlayHeadElement *tempPtr2; 121 /*! \brief Add new background mask overlay 122 * \param objIdx Associate the overlay with this object 123 * \param param source background index 124 */ 125 void addGfxElementA0(int16 objIdx, int16 param) { 126 Common::List<overlay>::iterator it; 127 overlay tmp; 136 128 137 while (currentHeadPtr && ((currentHeadPtr->objIdx != objIdx) || (currentHeadPtr->type != param))) { 138 previousPtr = currentHeadPtr; 139 currentHeadPtr = previousPtr->next; 129 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 130 // wtf?! 131 if (objectTable[it->objIdx].mask == objectTable[objIdx].mask && 132 (it->type == 2 || it->type == 3)) { 133 break; 134 } 140 135 } 141 136 142 if ( !currentHeadPtr || !((currentHeadPtr->objIdx == objIdx) && (currentHeadPtr->type == param))) {143 return -1;137 if (it != overlayList.end() && it->objIdx == objIdx && it->type == 20 && it->x == param) { 138 return; 144 139 } 145 140 146 previousPtr->next = tempPtr2 = currentHeadPtr->next; 141 tmp.objIdx = objIdx; 142 tmp.type = 20; 143 tmp.x = param; 144 tmp.y = 0; 145 tmp.width = 0; 146 tmp.color = 0; 147 147 148 if (!tempPtr2) { 149 tempPtr2 = &overlayHead; 150 } 151 152 tempPtr2->previous = currentHeadPtr->previous; 153 154 delete currentHeadPtr; 155 return 0; 148 overlayList.insert(it, tmp); 156 149 } 157 150 158 void loadOverlayElement(uint16 objIdx, uint16 param) { 159 overlayHeadElement *currentHeadPtr = &overlayHead; 160 overlayHeadElement *pNewElement; 151 /*! \brief Remove background mask overlay 152 * \param objIdx Remove overlay associated with this object 153 * \param param Remove overlay using this background 154 * \todo Check that it works 155 */ 156 void removeGfxElementA0(int16 objIdx, int16 param) { 157 Common::List<overlay>::iterator it; 161 158 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; 159 for (it = overlayList.begin(); it != overlayList.end(); ++it) { 160 if (it->objIdx == objIdx && it->type == 20 && it->x == param) { 161 overlayList.erase(it); 162 return; 163 } 171 164 } 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;189 165 } 190 166 191 167 void setupObject(byte objIdx, uint16 param1, uint16 param2, uint16 param3, uint16 param4) { … … 194 170 objectTable[objIdx].mask = param3; 195 171 objectTable[objIdx].frame = param4; 196 172 197 if ( !removeOverlayElement(objIdx, 0)) {198 loadOverlayElement(objIdx, 0);173 if (removeOverlay(objIdx, 0)) { 174 addOverlay(objIdx, 0); 199 175 } 200 176 } 201 177 … … 223 199 case 2: 224 200 objectTable[objIdx].mask = newValue; 225 201 226 if ( !removeOverlayElement(objIdx, 0)) {227 loadOverlayElement(objIdx, 0);202 if (removeOverlay(objIdx, 0)) { 203 addOverlay(objIdx, 0); 228 204 } 229 205 break; 230 206 case 3: -
engines/cine/main_loop.cpp
189 189 quitFlag = 0; 190 190 191 191 if (_preLoad == false) { 192 resetMessageHead();193 192 resetSeqList(); 194 193 resetBgIncrustList(); 195 194 … … 315 314 316 315 hideMouse(); 317 316 g_sound->stopMusic(); 318 unloadAllMasks();319 317 // if (g_cine->getGameType() == Cine::GType_OS) { 320 318 // freeUnkList(); 321 319 // } -
engines/cine/cine.cpp
129 129 globalScripts.clear(); 130 130 bgIncrustList.clear(); 131 131 freeAnimDataTable(); 132 overlayList.clear(); 133 messageTable.clear(); 132 134 133 135 memset(objectTable, 0, sizeof(objectTable)); 134 memset(messageTable, 0, sizeof(messageTable));135 136 136 overlayHead.next = overlayHead.previous = NULL;137 138 137 var8 = 0; 139 // bgIncrustList = NULL;140 138 141 139 var2 = var3 = var4 = var5 = 0; 142 140 -
engines/cine/gfx.cpp
25 25 26 26 #include "cine/cine.h" 27 27 #include "cine/bg.h" 28 #include "cine/bg_list.h" 28 29 #include "cine/various.h" 29 30 30 31 #include "common/endian.h" … … 168 169 byte *destPtr = page + x + y * 320; 169 170 destPtr += i * 320; 170 171 171 for (j = 0; j < width * 8; j++) {172 for (j = 0; j < width; j++) { 172 173 if (x + j >= 0 && x + j < 320 && i + y >= 0 173 174 && i + y < 200) { 174 175 if (!*(spritePtr++)) { … … 191 192 byte *destPtr = page + x + y * 320; 192 193 destPtr += i * 320; 193 194 194 for (j = 0; j < width * 8; j++) {195 for (j = 0; j < width; j++) { 195 196 if (x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200 && *maskPtr == 0) { 196 197 *destPtr = *spritePtr; 197 198 } … … 202 203 } 203 204 } 204 205 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) { 206 void gfxUpdateSpriteMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *srcMask, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight) { 207 207 int16 i, j, d, spritePitch, maskPitch; 208 208 209 width *= 8;210 maskWidth *= 8;211 212 209 spritePitch = width; 213 210 maskPitch = maskWidth; 214 211 215 if (maskIdx == 0) { 216 memcpy(bufferSprPtr, spritePtr, spritePitch * height); 217 memcpy(bufferMskPtr, spriteMskPtr, spritePitch * height); 212 // crop update area to overlapping parts of masks 213 if (y > ym) { 214 d = y - ym; 215 srcMask += d * maskPitch; 216 maskHeight -= d; 217 } else if (y < ym) { 218 d = ym - y; 219 destMask += d * spritePitch; 220 height -= d; 218 221 } 219 222 220 if (ys > ym) { 221 d = ys - ym; 222 maskPtr += d * maskPitch; 223 maskHeight -= d; 224 } 225 if (maskHeight <= 0) { 226 return; 227 } 228 if (xs > xm) { 229 d = xs - xm; 230 maskPtr += d; 223 if (x > xm) { 224 d = x - xm; 225 srcMask += d; 231 226 maskWidth -= d; 227 } else if (x < xm) { 228 d = xm - x; 229 destMask += d; 230 width -= d; 232 231 } 233 if (maskWidth <= 0) { 234 return; 232 233 // update mask 234 for (j = 0; j < MIN(maskHeight, height); ++j) { 235 for (i = 0; i < MIN(maskWidth, width); ++i) { 236 destMask[i] |= srcMask[i] ^ 1; 237 } 238 destMask += spritePitch; 239 srcMask += maskPitch; 235 240 } 236 if (ys < ym) { 237 d = ym - ys; 238 spriteMskPtr += d * spritePitch; 239 bufferMskPtr += d * spritePitch; 241 } 242 243 void gfxUpdateIncrustMask(byte *destMask, int16 x, int16 y, int16 width, int16 height, const byte *srcMask, int16 xm, int16 ym, int16 maskWidth, int16 maskHeight) { 244 int16 i, j, d, spritePitch, maskPitch; 245 246 spritePitch = width; 247 maskPitch = maskWidth; 248 249 // crop update area to overlapping parts of masks 250 if (y > ym) { 251 d = y - ym; 252 srcMask += d * maskPitch; 253 maskHeight -= d; 254 } else if (y < ym) { 255 d = ym - y > height ? height : ym - y; 256 memset(destMask, 1, d * spritePitch); 257 destMask += d * spritePitch; 240 258 height -= d; 241 259 } 242 if (height <= 0) { 243 return; 260 261 if (x > xm) { 262 d = x - xm; 263 xm = x; 264 srcMask += d; 265 maskWidth -= d; 244 266 } 245 if (xs < xm) { 246 d = xm - xs; 247 spriteMskPtr += d; 248 bufferMskPtr += d; 249 width -= d; 250 } 251 if (width <= 0) { 252 return; 253 } 267 268 d = xm - x; 269 maskWidth += d; 270 271 // update mask 254 272 for (j = 0; j < MIN(maskHeight, height); ++j) { 255 for (i = 0; i < MIN(maskWidth, width); ++i) {256 bufferMskPtr[i] |= maskPtr[i] ^ 1;273 for (i = 0; i < width; ++i) { 274 destMask[i] |= i < d || i >= maskWidth ? 1 : srcMask[i - d]; 257 275 } 258 bufferMskPtr+= spritePitch;259 maskPtr+= maskPitch;276 destMask += spritePitch; 277 srcMask += maskPitch; 260 278 } 279 280 if (j < height) { 281 memset(destMask, 1, (height - j) * spritePitch); 282 } 261 283 } 262 284 263 285 void gfxDrawLine(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page) { … … 431 453 432 454 void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 height, 433 455 byte *page, int16 x, int16 y) { 434 int16 i, j; 456 int16 i, j, tmpWidth, tmpHeight; 457 Common::List<BGIncrust>::iterator it; 458 byte *mask; 459 const byte *backup = maskPtr; 435 460 461 // background pass 436 462 for (i = 0; i < height; i++) { 437 463 byte *destPtr = page + x + y * 320; 438 464 const byte *srcPtr = bgPtr + x + y * 320; 439 465 destPtr += i * 320; 440 466 srcPtr += i * 320; 441 467 442 for (j = 0; j < width * 8; j++) {468 for (j = 0; j < width; j++) { 443 469 if ((!maskPtr || !(*maskPtr)) && (x + j >= 0 444 470 && x + j < 320 && i + y >= 0 && i + y < 200)) { 445 471 *destPtr = *srcPtr; … … 450 476 maskPtr++; 451 477 } 452 478 } 479 480 maskPtr = backup; 481 482 // incrust pass 483 for (it = bgIncrustList.begin(); it != bgIncrustList.end(); ++it) { 484 tmpWidth = animDataTable[it->frame]._realWidth; 485 tmpHeight = animDataTable[it->frame]._height; 486 mask = (byte*)malloc(tmpWidth * tmpHeight); 487 488 if (it->param == 0) { 489 generateMask(animDataTable[it->frame].data(), mask, tmpWidth * tmpHeight, it->part); 490 gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height); 491 gfxDrawMaskedSprite(animDataTable[it->frame].data(), mask, tmpWidth, tmpHeight, page, it->x, it->y); 492 } else { 493 memcpy(mask, animDataTable[it->frame].data(), tmpWidth * tmpHeight); 494 gfxUpdateIncrustMask(mask, it->x, it->y, tmpWidth, tmpHeight, maskPtr, x, y, width, height); 495 gfxFillSprite(mask, tmpWidth, tmpHeight, page, it->x, it->y); 496 } 497 498 free(mask); 499 } 453 500 } 454 501 455 502 /*! \todo Fix rendering to prevent fadein artifacts -
engines/cine/bg.cpp
50 50 uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; 51 51 if (bpp == 8) { 52 52 ctColorMode = 1; 53 memcpy(newPalette, ptr, 256 *3);53 memcpy(newPalette, ptr, 256 * 3); 54 54 ptr += 3 * 256; 55 55 memcpy(page3Raw, ptr, 320 * 200); 56 56 } else { … … 134 134 135 135 additionalBgTable[bgIdx] = (byte *) malloc(320 * 200); 136 136 137 debug("addBackground %d", bgIdx);138 139 137 uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; 140 138 141 139 if (bpp == 8) { 142 140 bgColorMode = 1; 143 memcpy(newPalette, ptr, 256 *3);141 memcpy(newPalette, ptr, 256 * 3); 144 142 ptr += 3 * 256; 145 143 memcpy(additionalBgTable[bgIdx], ptr, 320 * 200); 146 144 } else { -
engines/cine/anim.h
102 102 void loadResource(const char *animName); 103 103 void loadAbs(const char *resourceName, uint16 idx); 104 104 void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken); 105 void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency); 105 106 106 107 } // End of namespace Cine 107 108 -
engines/cine/msg.h
26 26 #ifndef CINE_MSG_H 27 27 #define CINE_MSG_H 28 28 29 #include "common/str.h" 30 29 31 namespace Cine { 30 32 33 #define NUM_MAX_MESSAGE 255 34 35 extern Common::StringList messageTable; 36 31 37 void loadMsg(char *pMsgName); 32 38 33 39 } // End of namespace Cine -
engines/cine/various.h
42 42 extern bool disableSystemMenu; 43 43 extern bool inMenu; 44 44 45 struct Message {46 byte *ptr;47 uint16 len;48 };49 50 #define NUM_MAX_MESSAGE 25551 52 extern Message messageTable[NUM_MAX_MESSAGE];53 54 45 struct SeqListElement { 55 46 struct SeqListElement *next; 56 47 int16 var4; … … 149 140 150 141 extern int16 additionalBgVScroll; 151 142 143 void removeSeq(uint16 param1, uint16 param2, uint16 param3); 144 uint16 isSeqRunning(uint16 param1, uint16 param2, uint16 param3); 152 145 void addSeqListElement(int16 param0, int16 param1, int16 param2, int16 param3, int16 param4, int16 param5, int16 param6, int16 param7, int16 param8); 153 146 void resetSeqList(); 154 147 void processSeqList(void);