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 PRINCE_SCRIPT_H 24 #define PRINCE_SCRIPT_H 25 26 #include "common/random.h" 27 #include "common/endian.h" 28 #include "common/array.h" 29 #include "common/stream.h" 30 31 #include "prince/flags.h" 32 33 namespace Prince { 34 35 class PrinceEngine; 36 class Animation; 37 class Object; 38 struct Anim; 39 struct BackgroundAnim; 40 struct Mask; 41 42 class Room { 43 public: 44 Room(); 45 int _mobs; // mob flag offset 46 int _backAnim; // offset to array of animation numbers 47 int _obj; // offset to array of object numbers 48 int _nak; // offset to array of masks 49 int _itemUse; 50 int _itemGive; 51 int _walkTo; // offset to array of WALKTO events or 0 52 int _examine; // offset to array of EXAMINE events or 0 53 int _pickup; 54 int _use; 55 int _pushOpen; 56 int _pullClose; 57 int _talk; 58 int _give; 59 60 bool loadStream(Common::SeekableReadStream &stream); 61 bool loadRoom(byte *roomData); 62 int getOptionOffset(int option); 63 64 private: 65 66 typedef void (Room::*LoadingStep)(Common::SeekableReadStream &stream); 67 68 void nextLoadStep(Common::SeekableReadStream &stream, LoadingStep step); 69 70 void loadMobs(Common::SeekableReadStream &stream); 71 void loadBackAnim(Common::SeekableReadStream &stream); 72 void loadObj(Common::SeekableReadStream &stream); 73 void loadNak(Common::SeekableReadStream &stream); 74 void loadItemUse(Common::SeekableReadStream &stream); 75 void loadItemGive(Common::SeekableReadStream &stream); 76 void loadWalkTo(Common::SeekableReadStream &stream); 77 void loadExamine(Common::SeekableReadStream &stream); 78 void loadPickup(Common::SeekableReadStream &stream); 79 void loadUse(Common::SeekableReadStream &stream); 80 void loadPushOpen(Common::SeekableReadStream &stream); 81 void loadPullClose(Common::SeekableReadStream &stream); 82 void loadTalk(Common::SeekableReadStream &stream); 83 void loadGive(Common::SeekableReadStream &stream); 84 }; 85 86 87 class Script { 88 public: 89 static const int16 kMaxRooms = 60; 90 91 Script(PrinceEngine *vm); 92 ~Script(); 93 94 struct ScriptInfo { 95 int rooms; 96 int startGame; 97 int restoreGame; 98 int stdExamine; 99 int stdPickup; 100 int stdUse; 101 int stdOpen; 102 int stdClose; 103 int stdTalk; 104 int stdGive; 105 int usdCode; 106 int invObjExam; 107 int invObjUse; 108 int invObjUU; 109 int stdUseItem; 110 int lightSources; 111 int specRout; 112 int invObjGive; 113 int stdGiveItem; 114 int goTester; 115 }; 116 117 ScriptInfo _scriptInfo; 118 119 bool loadStream(Common::SeekableReadStream &stream); 120 121 uint16 readScript16(uint32 address); 122 uint32 readScript32(uint32 address); 123 124 uint32 getStartGameOffset(); 125 uint32 getLocationInitScript(int initRoomTableOffset, int roomNr); 126 int16 getLightX(int locationNr); 127 int16 getLightY(int locationNr); 128 int32 getShadowScale(int locationNr); 129 uint8 *getRoomOffset(int locationNr); 130 int32 getOptionStandardOffset(int option); 131 uint8 *getHeroAnimName(int offset); 132 133 void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset); 134 void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset); 135 void installObjects(int offset); 136 bool loadAllMasks(Common::Array<Mask> &maskList, int offset); 137 138 int scanMobEvents(int mobMask, int dataEventOffset); 139 int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask); 140 141 byte getMobVisible(int roomMobOffset, uint16 mob); 142 void setMobVisible(int roomMobOffset, uint16 mob, byte value); 143 144 uint32 getBackAnimId(int roomBackAnimOffset, int slot); 145 void setBackAnimId(int roomBackAnimOffset, int slot, int animId); 146 147 byte getObjId(int roomObjOffset, int slot); 148 void setObjId(int roomObjOffset, int slot, byte objectId); 149 getString(uint32 offset)150 const char *getString(uint32 offset) { 151 return (const char *)(&_data[offset]); 152 } 153 154 private: 155 PrinceEngine *_vm; 156 uint8 *_data; 157 uint32 _dataSize; 158 Common::Array<Room> _roomList; 159 }; 160 161 class InterpreterFlags { 162 public: 163 InterpreterFlags(); 164 165 void setFlagValue(Flags::Id flag, int32 value); 166 int32 getFlagValue(Flags::Id flag); 167 168 void resetAllFlags(); 169 170 static const uint16 kFlagMask = 0x8000; 171 static const uint16 kMaxFlags = 2000; 172 private: 173 int32 _flags[kMaxFlags]; 174 }; 175 176 class Interpreter { 177 public: 178 Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags); 179 stopBg()180 void stopBg() { _bgOpcodePC = 0; } 181 182 void stepBg(); 183 void stepFg(); 184 void storeNewPC(int opcodePC); 185 int getLastOPCode(); 186 int getFgOpcodePC(); 187 188 void setBgOpcodePC(uint32 value); 189 void setFgOpcodePC(uint32 value); 190 191 uint32 getCurrentString(); 192 void setCurrentString(uint32 value); 193 194 byte *getString(); 195 void setString(byte *newString); 196 void increaseString(); 197 198 void setResult(byte value); 199 200 private: 201 PrinceEngine *_vm; 202 Script *_script; 203 InterpreterFlags *_flags; 204 205 uint32 _currentInstruction; 206 207 uint32 _bgOpcodePC; 208 uint32 _fgOpcodePC; 209 210 uint16 _lastOpcode; 211 uint32 _lastInstruction; 212 byte _result; 213 214 bool _opcodeNF; // break interpreter loop 215 bool _opcodeEnd; // end of a game flag 216 217 static const uint32 _STACK_SIZE = 500; 218 uint32 _stack[_STACK_SIZE]; 219 struct stringStack { 220 byte *string; 221 byte *dialogData; 222 uint32 currentString; 223 } _stringStack; 224 uint8 _stacktop; 225 uint32 _waitFlag; 226 227 byte *_string; 228 uint32 _currentString; 229 const char *_mode; 230 231 // Helper functions 232 uint32 step(uint32 opcodePC); 233 uint16 readScript16(); 234 uint32 readScript32(); 235 int32 readScriptFlagValue(); 236 Flags::Id readScriptFlagId(); 237 int checkSeq(byte *string); 238 239 void debugInterpreter(const char *s, ...); 240 241 typedef void (Interpreter::*OpcodeFunc)(); 242 static OpcodeFunc _opcodes[]; 243 244 static const uint kGiveLetterScriptFix = 79002; 245 static const uint kSecondBirdAnimationScriptFix = 45658; 246 247 // Keep opcode handlers names as they are in original code 248 // making it easier to switch back and forth 249 void O_WAITFOREVER(); 250 void O_BLACKPALETTE(); 251 void O_SETUPPALETTE(); 252 void O_INITROOM(); 253 void O_SETSAMPLE(); 254 void O_FREESAMPLE(); 255 void O_PLAYSAMPLE(); 256 void O_PUTOBJECT(); 257 void O_REMOBJECT(); 258 void O_SHOWANIM(); 259 void O_CHECKANIMEND(); 260 void O_FREEANIM(); 261 void O_CHECKANIMFRAME(); 262 void O_PUTBACKANIM(); 263 void O_REMBACKANIM(); 264 void O_CHECKBACKANIMFRAME(); 265 void O_FREEALLSAMPLES(); 266 void O_SETMUSIC(); 267 void O_STOPMUSIC(); 268 void O__WAIT(); 269 void O_UPDATEOFF(); 270 void O_UPDATEON(); 271 void O_UPDATE (); 272 void O_CLS(); 273 void O__CALL(); 274 void O_RETURN(); 275 void O_GO(); 276 void O_BACKANIMUPDATEOFF(); 277 void O_BACKANIMUPDATEON(); 278 void O_CHANGECURSOR(); 279 void O_CHANGEANIMTYPE(); 280 void O__SETFLAG(); 281 void O_COMPARE(); 282 void O_JUMPZ(); 283 void O_JUMPNZ(); 284 void O_EXIT(); 285 void O_ADDFLAG(); 286 void O_TALKANIM(); 287 void O_SUBFLAG(); 288 void O_SETSTRING(); 289 void O_ANDFLAG(); 290 void O_GETMOBDATA(); 291 void O_ORFLAG(); 292 void O_SETMOBDATA(); 293 void O_XORFLAG(); 294 void O_GETMOBTEXT(); 295 void O_MOVEHERO(); 296 void O_WALKHERO(); 297 void O_SETHERO(); 298 void O_HEROOFF(); 299 void O_HEROON(); 300 void O_CLSTEXT(); 301 void O_CALLTABLE(); 302 void O_CHANGEMOB(); 303 void O_ADDINV(); 304 void O_REMINV(); 305 void O_REPINV(); 306 void O_OBSOLETE_GETACTION(); 307 void O_ADDWALKAREA(); 308 void O_REMWALKAREA(); 309 void O_RESTOREWALKAREA(); 310 void O_WAITFRAME(); 311 void O_SETFRAME(); 312 void O_RUNACTION(); 313 void O_COMPAREHI(); 314 void O_COMPARELO(); 315 void O_PRELOADSET(); 316 void O_FREEPRELOAD(); 317 void O_CHECKINV(); 318 void O_TALKHERO(); 319 void O_WAITTEXT(); 320 void O_SETHEROANIM(); 321 void O_WAITHEROANIM(); 322 void O_GETHERODATA(); 323 void O_GETMOUSEBUTTON(); 324 void O_CHANGEFRAMES(); 325 void O_CHANGEBACKFRAMES(); 326 void O_GETBACKANIMDATA(); 327 void O_GETANIMDATA(); 328 void O_SETBGCODE(); 329 void O_SETBACKFRAME(); 330 void O_GETRND(); 331 void O_TALKBACKANIM(); 332 void O_LOADPATH(); 333 void O_GETCHAR(); 334 void O_SETDFLAG(); 335 void O_CALLDFLAG(); 336 void O_PRINTAT(); 337 void O_ZOOMIN(); 338 void O_ZOOMOUT(); 339 void O_SETSTRINGOFFSET(); 340 void O_GETOBJDATA(); 341 void O_SETOBJDATA(); 342 void O_SWAPOBJECTS(); 343 void O_CHANGEHEROSET(); 344 void O_ADDSTRING(); 345 void O_SUBSTRING(); 346 void O_INITDIALOG(); 347 void O_ENABLEDIALOGOPT(); 348 void O_DISABLEDIALOGOPT(); 349 void O_SHOWDIALOGBOX(); 350 void O_STOPSAMPLE(); 351 void O_BACKANIMRANGE(); 352 void O_CLEARPATH(); 353 void O_SETPATH(); 354 void O_GETHEROX(); 355 void O_GETHEROY(); 356 void O_GETHEROD(); 357 void O_PUSHSTRING(); 358 void O_POPSTRING(); 359 void O_SETFGCODE(); 360 void O_STOPHERO(); 361 void O_ANIMUPDATEOFF(); 362 void O_ANIMUPDATEON(); 363 void O_FREECURSOR(); 364 void O_ADDINVQUIET(); 365 void O_RUNHERO(); 366 void O_SETBACKANIMDATA(); 367 void O_VIEWFLC(); 368 void O_CHECKFLCFRAME(); 369 void O_CHECKFLCEND(); 370 void O_FREEFLC(); 371 void O_TALKHEROSTOP(); 372 void O_HEROCOLOR(); 373 void O_GRABMAPA(); 374 void O_ENABLENAK(); 375 void O_DISABLENAK(); 376 void O_GETMOBNAME(); 377 void O_SWAPINVENTORY(); 378 void O_CLEARINVENTORY(); 379 void O_SKIPTEXT(); 380 void O_SETVOICEH(); 381 void O_SETVOICEA(); 382 void O_SETVOICEB(); 383 void O_SETVOICEC(); 384 void O_VIEWFLCLOOP(); 385 void O_FLCSPEED(); 386 void O_OPENINVENTORY(); 387 void O_KRZYWA(); 388 void O_GETKRZYWA(); 389 void O_GETMOB(); 390 void O_INPUTLINE(); 391 void O_SETVOICED(); 392 void O_BREAK_POINT(); 393 394 }; 395 396 } // End of namespace Prince 397 398 #endif 399