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 */ 22 23 #ifndef CINE_SCRIPT_H 24 #define CINE_SCRIPT_H 25 26 #include "common/savefile.h" 27 #include "common/array.h" 28 #include "common/list.h" 29 #include "common/ptr.h" 30 31 namespace Cine { 32 33 #define SCRIPT_STACK_SIZE 50 34 #define LOCAL_VARS_SIZE 50 35 36 /** 37 * Fixed size array of script variables. 38 * 39 * Array size can be set in constructors, once the instance is created, 40 * it cannot be changed directly. 41 */ 42 43 class FWScript; 44 45 typedef int (FWScript::*OpFunc)(); 46 47 struct Opcode { 48 OpFunc proc; 49 const char *args; 50 }; 51 52 /** 53 * Fixed size array for script variables 54 */ 55 class ScriptVars { 56 private: 57 unsigned int _size; ///< Size of array 58 int16 *_vars; ///< Variable values 59 60 public: 61 // Explicit to prevent var=0 instead of var[i]=0 typos. 62 explicit ScriptVars(unsigned int len = 50); 63 ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len = 50); 64 ScriptVars(const ScriptVars &src); 65 ~ScriptVars(); 66 67 void reinit(unsigned int len); 68 ScriptVars &operator=(const ScriptVars &src); 69 int16 &operator[](unsigned int idx); 70 int16 operator[](unsigned int idx) const; 71 72 void save(Common::OutSaveFile &fHandle) const; 73 void save(Common::OutSaveFile &fHandle, unsigned int len) const; 74 void load(Common::SeekableReadStream &fHandle); 75 void load(Common::SeekableReadStream &fHandle, unsigned int len); 76 void reset(); 77 }; 78 79 class FWScriptInfo; 80 81 /** 82 * Script bytecode and initial labels, ScriptStruct replacement. 83 * 84 * _data is one byte longer to make sure strings in bytecode are properly 85 * terminated 86 */ 87 class RawScript { 88 private: 89 byte *_data; ///< Script bytecode 90 ScriptVars _labels; ///< Initial script labels 91 92 protected: 93 void computeLabels(const FWScriptInfo &info); 94 int getNextLabel(const FWScriptInfo &info, int offset) const; 95 96 public: 97 uint16 _size; ///< Bytecode length 98 99 explicit RawScript(uint16 size); 100 RawScript(const FWScriptInfo &info, const byte *data, uint16 size); 101 RawScript(const RawScript &src); 102 ~RawScript(); 103 104 RawScript &operator=(const RawScript &src); 105 106 void setData(const FWScriptInfo &info, const byte *data); 107 const ScriptVars &labels() const; 108 byte getByte(unsigned int pos) const; 109 uint16 getWord(unsigned int pos) const; 110 const char *getString(unsigned int pos) const; 111 uint16 getLabel(const FWScriptInfo &info, byte index, uint16 offset) const; 112 }; 113 114 /** 115 * Object script class, RelObjectScript replacement 116 * 117 * Script parameters are not used, this class is required by different 118 * script initialization of object scripts 119 */ 120 class RawObjectScript : public RawScript { 121 public: 122 int16 _runCount; ///< How many times the script was used 123 uint16 _param1; ///< Additional parameter not used at the moment 124 uint16 _param2; ///< Additional parameter not used at the moment 125 uint16 _param3; ///< Additional parameter not used at the moment 126 127 RawObjectScript(uint16 size, uint16 p1, uint16 p2, uint16 p3); 128 RawObjectScript(const FWScriptInfo &info, const byte *data, uint16 size, uint16 p1, uint16 p2, uint16 p3); 129 130 /** 131 * Run the script one more time. 132 * @return Run count before incrementation 133 */ run()134 int16 run() { return _runCount++; } 135 }; 136 137 /** 138 * Future Wars script, prcLinkedListStruct replacement. 139 * @todo Rewrite _globalVars initialization 140 */ 141 class FWScript { 142 private: 143 const RawScript &_script; ///< Script bytecode reference 144 uint16 _pos; ///< Current position in script 145 uint16 _line; ///< Current opcode index in bytecode for debugging 146 uint16 _compare; ///< Last compare result 147 ScriptVars _labels; ///< Current script labels 148 ScriptVars _localVars; ///< Local script variables 149 ScriptVars &_globalVars; ///< Global variables reference 150 FWScriptInfo *_info; ///< Script info 151 152 protected: 153 static const Opcode *_opcodeTable; 154 static unsigned int _numOpcodes; 155 156 int o1_modifyObjectParam(); 157 int o1_getObjectParam(); 158 int o1_addObjectParam(); 159 int o1_subObjectParam(); 160 int o1_mulObjectParam(); 161 int o1_divObjectParam(); 162 int o1_compareObjectParam(); 163 int o1_setupObject(); 164 int o1_checkCollision(); 165 int o1_loadVar(); 166 int o1_addVar(); 167 int o1_subVar(); 168 int o1_mulVar(); 169 int o1_divVar(); 170 int o1_compareVar(); 171 int o1_modifyObjectParam2(); 172 int o1_loadMask0(); 173 int o1_unloadMask0(); 174 int o1_addToBgList(); 175 int o1_loadMask1(); 176 int o1_unloadMask1(); 177 int o1_loadMask4(); 178 int o1_unloadMask4(); 179 int o1_addSpriteFilledToBgList(); 180 int o1_clearBgIncrustList(); 181 int o1_label(); 182 int o1_goto(); 183 int o1_gotoIfSup(); 184 int o1_gotoIfSupEqu(); 185 int o1_gotoIfInf(); 186 int o1_gotoIfInfEqu(); 187 int o1_gotoIfEqu(); 188 int o1_gotoIfDiff(); 189 int o1_removeLabel(); 190 int o1_loop(); 191 int o1_startGlobalScript(); 192 int o1_endGlobalScript(); 193 int o1_loadAnim(); 194 int o1_loadBg(); 195 int o1_loadCt(); 196 int o1_loadPart(); 197 int o1_closePart(); 198 int o1_loadNewPrcName(); 199 int o1_requestCheckPendingDataLoad(); 200 int o1_blitAndFade(); 201 int o1_fadeToBlack(); 202 int o1_transformPaletteRange(); 203 int o1_setDefaultMenuBgColor(); 204 int o1_palRotate(); 205 int o1_break(); 206 int o1_endScript(); 207 int o1_message(); 208 int o1_loadGlobalVar(); 209 int o1_compareGlobalVar(); 210 int o1_declareFunctionName(); 211 int o1_freePartRange(); 212 int o1_unloadAllMasks(); 213 int o1_setScreenDimensions(); 214 int o1_displayBackground(); 215 int o1_initializeZoneData(); 216 int o1_setZoneDataEntry(); 217 int o1_getZoneDataEntry(); 218 int o1_setPlayerCommandPosY(); 219 int o1_allowPlayerInput(); 220 int o1_disallowPlayerInput(); 221 int o1_changeDataDisk(); 222 int o1_loadMusic(); 223 int o1_playMusic(); 224 int o1_fadeOutMusic(); 225 int o1_stopSample(); 226 int o1_op71(); 227 int o1_op72(); 228 int o1_op73(); 229 int o1_playSample(); 230 int o1_playSampleSwapped(); 231 int o1_disableSystemMenu(); 232 int o1_loadMask5(); 233 int o1_unloadMask5(); 234 235 // pointers to member functions in C++ suck... 236 int o2_loadCt(); 237 int o2_loadPart(); 238 int o2_addSeqListElement(); 239 int o2_removeSeq(); 240 int o2_playSample(); 241 int o2_playSampleAlt(); 242 int o2_clearSeqList(); 243 int o2_modifySeqListElement(); 244 int o2_isSeqRunning(); 245 int o2_gotoIfSupNearest(); 246 int o2_gotoIfSupEquNearest(); 247 int o2_gotoIfInfNearest(); 248 int o2_gotoIfInfEquNearest(); 249 int o2_gotoIfEquNearest(); 250 int o2_gotoIfDiffNearest(); 251 int o2_startObjectScript(); 252 int o2_stopObjectScript(); 253 int o2_op8D(); 254 int o2_addBackground(); 255 int o2_removeBackground(); 256 int o2_loadAbs(); 257 int o2_loadBg(); 258 int o2_wasZoneChecked(); 259 int o2_op9B(); 260 int o2_op9C(); 261 int o2_useBgScroll(); 262 int o2_setAdditionalBgVScroll(); 263 int o2_op9F(); 264 int o2_addGfxElementType20(); 265 int o2_removeGfxElementType20(); 266 int o2_addGfxElementType21(); 267 int o2_removeGfxElementType21(); 268 int o2_loadMask22(); 269 int o2_unloadMask22(); 270 271 byte getNextByte(); 272 uint16 getNextWord(); 273 const char *getNextString(); 274 275 void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos); 276 277 FWScript(const RawScript &script, int16 index, FWScriptInfo *info); 278 FWScript(RawObjectScript &script, int16 index, FWScriptInfo *info); 279 FWScript(const FWScript &src, FWScriptInfo *info); 280 281 public: 282 int16 _index; ///< Index in script table 283 284 static void setupTable(); 285 286 FWScript(const RawScript &script, int16 index); 287 // FWScript(const RawObjectScript &script, int16 index); 288 FWScript(const FWScript &src); 289 ~FWScript(); 290 291 int execute(); 292 void save(Common::OutSaveFile &fHandle) const; 293 294 friend class FWScriptInfo; 295 296 // workaround for bug in g++ which prevents protected member functions 297 // of FWScript from being used in OSScript::_opcodeTable[] 298 // initialization ("error: protected within this context") 299 friend class OSScript; 300 }; 301 302 /** 303 * Operation Stealth script, prcLinkedListStruct replacement 304 */ 305 class OSScript : public FWScript { 306 private: 307 static const Opcode *_opcodeTable; 308 static unsigned int _numOpcodes; 309 310 protected: 311 void load(const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos); 312 313 public: 314 static void setupTable(); 315 316 OSScript(const RawScript &script, int16 index); 317 OSScript(RawObjectScript &script, int16 index); 318 OSScript(const OSScript &src); 319 320 friend class OSScriptInfo; 321 }; 322 323 /** 324 * Future Wars script factory and info 325 */ 326 class FWScriptInfo { 327 protected: 328 virtual OpFunc opcodeHandler(byte opcode) const; 329 330 public: ~FWScriptInfo()331 virtual ~FWScriptInfo() {} 332 333 virtual const char *opcodeInfo(byte opcode) const; 334 virtual FWScript *create(const RawScript &script, int16 index) const; 335 virtual FWScript *create(const RawObjectScript &script, int16 index) const; 336 virtual FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; 337 virtual FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const; 338 339 friend class FWScript; 340 }; 341 342 /** 343 * Operation Stealth script factory and info 344 */ 345 class OSScriptInfo : public FWScriptInfo { 346 protected: 347 OpFunc opcodeHandler(byte opcode) const override; 348 349 public: ~OSScriptInfo()350 ~OSScriptInfo() override {} 351 352 const char *opcodeInfo(byte opcode) const override; 353 FWScript *create(const RawScript &script, int16 index) const override; 354 FWScript *create(const RawObjectScript &script, int16 index) const override; 355 FWScript *create(const RawScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const override; 356 FWScript *create(const RawObjectScript &script, int16 index, const ScriptVars &labels, const ScriptVars &local, uint16 compare, uint16 pos) const override; 357 358 friend class FWScript; 359 }; 360 361 typedef Common::SharedPtr<FWScript> ScriptPtr; 362 typedef Common::SharedPtr<RawScript> RawScriptPtr; 363 typedef Common::SharedPtr<RawObjectScript> RawObjectScriptPtr; 364 typedef Common::List<ScriptPtr> ScriptList; 365 typedef Common::Array<RawScriptPtr> RawScriptArray; 366 typedef Common::Array<RawObjectScriptPtr> RawObjectScriptArray; 367 368 #define NUM_MAX_SCRIPT 50 369 370 extern FWScriptInfo *scriptInfo; 371 372 void setupOpcodes(); 373 374 void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx); 375 void dumpScript(char *dumpName); 376 377 #define OP_loadPart 0x3F 378 #define OP_loadNewPrcName 0x41 379 #define OP_requestCheckPendingDataLoad 0x42 380 #define OP_endScript 0x50 381 382 void addScriptToGlobalScripts(uint16 idx); 383 int16 checkCollision(int16 objIdx, int16 x, int16 y, int16 numZones, int16 zoneIdx); 384 385 void runObjectScript(int16 entryIdx); 386 387 void executeObjectScripts(); 388 void executeGlobalScripts(); 389 390 void purgeObjectScripts(); 391 void purgeGlobalScripts(); 392 393 } // End of namespace Cine 394 395 #endif 396