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_PRINCE_H 24 #define PRINCE_PRINCE_H 25 26 #include "common/random.h" 27 #include "common/system.h" 28 #include "common/debug.h" 29 #include "common/debug-channels.h" 30 #include "common/textconsole.h" 31 #include "common/rect.h" 32 #include "common/events.h" 33 #include "common/endian.h" 34 #include "common/savefile.h" 35 #include "common/serializer.h" 36 37 #include "image/bmp.h" 38 39 #include "gui/debugger.h" 40 41 #include "engines/engine.h" 42 #include "engines/util.h" 43 44 #include "audio/mixer.h" 45 46 #include "video/flic_decoder.h" 47 48 #include "prince/mob.h" 49 #include "prince/object.h" 50 #include "prince/pscr.h" 51 #include "prince/detection.h" 52 53 namespace Prince { 54 55 struct SavegameHeader; 56 57 class PrinceEngine; 58 class GraphicsMan; 59 class Script; 60 class Interpreter; 61 class InterpreterFlags; 62 class Debugger; 63 class MusicPlayer; 64 class VariaTxt; 65 class Cursor; 66 class MhwanhDecoder; 67 class Font; 68 class Hero; 69 class Animation; 70 class Room; 71 class Pscr; 72 73 struct SavegameHeader { 74 uint8 version; 75 Common::String saveName; 76 Graphics::Surface *thumbnail; 77 int16 saveYear, saveMonth, saveDay; 78 int16 saveHour, saveMinutes; 79 uint32 playTime; 80 }; 81 82 #define kSavegameStrSize 14 83 #define kSavegameStr "SCUMMVM_PRINCE" 84 85 struct Text { 86 const char *_str; 87 uint16 _x, _y; 88 uint16 _time; 89 uint32 _color; 90 TextText91 Text() { 92 clear(); 93 } 94 clearText95 void clear() { 96 _str = nullptr; 97 _x = 0; 98 _y = 0; 99 _time = 0; 100 _color = 255; 101 } 102 }; 103 104 struct AnimListItem { 105 uint16 _type; // type of animation - for background anims RND of frame 106 uint16 _fileNumber; 107 uint16 _startPhase; // first phase number 108 uint16 _endPhase; 109 uint16 _loopPhase; 110 int16 _x; 111 int16 _y; 112 uint16 _loopType; 113 uint16 _nextAnim; // number of animation to do for loop = 3 114 uint16 _flags; // byte 0 - draw masks, byte 1 - draw in front of mask, byte 2 - load but turn off drawing 115 bool loadFromStream(Common::SeekableReadStream &stream); 116 }; 117 118 struct BAS { 119 int32 _type; // type of sequence 120 int32 _data; // additional data 121 int32 _anims; // number of animations 122 int32 _current; // actual number of animation 123 int32 _counter; // time counter for animation 124 int32 _currRelative; //actual relative number for animation 125 int32 _data2; // additional data for measurements 126 }; 127 128 const int kStructSizeBAS = 28; 129 130 struct BASA { 131 int16 _num; // animation number 132 int16 _start; // initial frame 133 int16 _end; // final frame 134 //int16 _pad; // fulfilment to 8 bytes 135 }; 136 137 const int kStructSizeBASA = 8; 138 139 // background and normal animation 140 struct Anim { 141 BASA _basaData; 142 int32 _addr; //animation adress 143 int16 _usage; 144 int16 _state; // state of animation: 0 - turning on, 1 - turning off 145 int16 _flags; 146 int16 _frame; // number of phase to show 147 int16 _lastFrame; // last phase 148 int16 _loopFrame; // first frame of loop 149 int16 _showFrame; // actual visible frame of animation 150 int16 _loopType; // type of loop (0 - last frame; 1 - normal loop (begin from _loopFrame); 2 - no loop; 3 - load new animation) 151 int16 _nextAnim; // number of next animation to load after actual 152 int16 _x; 153 int16 _y; 154 int32 _currFrame; 155 int16 _currX; 156 int16 _currY; 157 int16 _currW; 158 int16 _currH; 159 int16 _packFlag; 160 int32 _currShadowFrame; 161 int16 _packShadowFlag; 162 int32 _shadowBack; 163 int16 _relX; 164 int16 _relY; 165 Animation *_animData; 166 Animation *_shadowData; 167 168 enum AnimOffsets { 169 kAnimState = 10, 170 kAnimFrame = 14, 171 kAnimLastFrame = 16, 172 kAnimX = 26 173 }; 174 getAnimDataAnim175 int16 getAnimData(Anim::AnimOffsets offset) { 176 switch (offset) { 177 case kAnimState: 178 return _state; 179 case kAnimFrame: 180 return _frame + 1; // fix for location 30 - man with a dog animation 181 case kAnimX: 182 return _x; 183 default: 184 error("getAnimData() - Wrong offset type: %d", (int)offset); 185 } 186 } 187 setAnimDataAnim188 void setAnimData(Anim::AnimOffsets offset, int16 value) { 189 if (offset == kAnimX) { 190 _x = value; 191 } else { 192 error("setAnimData() - Wrong offset: %d, value: %d", (int)offset, value); 193 } 194 } 195 }; 196 197 struct BackgroundAnim { 198 BAS _seq; 199 Common::Array<Anim> backAnims; 200 }; 201 202 enum AnimType { 203 kBackgroundAnimation, 204 kNormalAnimation 205 }; 206 207 // Nak (PL - Nakladka) 208 struct Mask { 209 uint16 _state; // visible / invisible 210 int16 _flags; // turning on / turning off of an mask 211 int16 _x1; 212 int16 _y1; 213 int16 _x2; 214 int16 _y2; 215 int16 _z; 216 int16 _number; // number of mask for background recreating 217 int16 _width; 218 int16 _height; 219 byte *_data; 220 getXMask221 int16 getX() const { 222 return READ_LE_UINT16(_data); 223 } 224 getYMask225 int16 getY() const { 226 return READ_LE_UINT16(_data + 2); 227 } 228 getWidthMask229 int16 getWidth() const { 230 return READ_LE_UINT16(_data + 4); 231 } 232 getHeightMask233 int16 getHeight() const { 234 return READ_LE_UINT16(_data + 6); 235 } 236 getMaskMask237 byte *getMask() const { 238 return (byte *)(_data + 8); 239 } 240 }; 241 242 struct InvItem { 243 int _x; 244 int _y; 245 Graphics::Surface *_surface; getSurfaceInvItem246 Graphics::Surface *getSurface() const { return _surface; } 247 }; 248 249 struct DrawNode { 250 int posX; 251 int posY; 252 int posZ; 253 int32 width; 254 int32 height; 255 int32 scaleValue; 256 Graphics::Surface *s; 257 Graphics::Surface *originalRoomSurface; 258 void *data; 259 void (*drawFunction)(Graphics::Surface *, DrawNode *); 260 }; 261 262 struct DebugChannel { 263 264 enum Type { 265 kScript, 266 kEngine 267 }; 268 269 }; 270 271 class PrinceEngine : public Engine { 272 protected: 273 Common::Error run() override; 274 275 public: 276 PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc); 277 ~PrinceEngine() override; 278 279 bool scummVMSaveLoadDialog(bool isSave); 280 281 bool hasFeature(EngineFeature f) const override; 282 void pauseEngineIntern(bool pause) override; 283 bool canSaveGameStateCurrently() override; 284 bool canLoadGameStateCurrently() override; 285 Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override; 286 Common::Error loadGameState(int slot) override; 287 288 void playVideo(Common::String videoFilename); 289 290 WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true); 291 void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header); 292 void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream); 293 bool loadGame(int slotNumber); 294 void resetGame(); 295 296 int32 _creditsDataSize; 297 byte *_creditsData; 298 void scrollCredits(); 299 300 int getGameType() const; 301 const char *getGameId() const; 302 uint32 getFeatures() const; 303 Common::Language getLanguage() const; 304 305 const PrinceGameDescription *_gameDescription; 306 Video::FlicDecoder _flicPlayer; 307 const Graphics::Surface *_flcFrameSurface; 308 VariaTxt *_variaTxt; 309 310 uint32 _talkTxtSize; 311 byte *_talkTxt; 312 313 uint32 _mobTranslationSize; 314 byte *_mobTranslationData; 315 316 bool _missingVoice; 317 318 bool loadLocation(uint16 locationNr); 319 bool loadAnim(uint16 animNr, bool loop); 320 bool loadVoice(uint32 textSlot, uint32 sampleSlot, const Common::String &name); 321 bool loadSample(uint32 sampleSlot, const Common::String &name); 322 bool loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName); 323 bool loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2); 324 bool loadTrans(byte *transTable, const char *resourceName); 325 bool loadMobPriority(const char *resourceName); 326 327 void loadMobTranslationTexts(); 328 void setMobTranslationTexts(); 329 330 bool loadMusic(int musNumber); 331 void stopMusic(); 332 333 void playSample(uint16 sampleId, uint16 loopType); 334 void stopSample(uint16 sampleId); 335 void stopAllSamples(); 336 void freeSample(uint16 sampleId); 337 void freeAllSamples(); 338 339 void setVoice(uint16 slot, uint32 sampleSlot, uint16 flag); 340 341 void changeCursor(uint16 curId); 342 void printAt(uint32 slot, uint8 color, char *s, uint16 x, uint16 y); 343 int calcTextLines(const char *s); 344 int calcTextTime(int numberOfLines); 345 void correctStringDEU(char *s); 346 347 static const uint8 kMaxTexts = 32; 348 Text _textSlots[kMaxTexts]; 349 350 Hero *_mainHero; 351 Hero *_secondHero; 352 353 enum HeroId { 354 kMainHero, 355 kSecondHero 356 }; 357 358 int _mouseFlag; 359 uint32 _currentTime; 360 uint16 _locationNr; 361 uint16 _sceneWidth; 362 int32 _picWindowX; 363 int32 _picWindowY; 364 365 Image::BitmapDecoder *_roomBmp; 366 MhwanhDecoder *_suitcaseBmp; 367 Room *_room; 368 Script *_script; 369 InterpreterFlags *_flags; 370 Interpreter *_interpreter; 371 GraphicsMan *_graph; 372 uint8 _currentMidi; 373 byte *_zoomBitmap; 374 byte *_shadowBitmap; 375 byte *_transTable; 376 377 int16 _scaleValue; // scale for hero or special shadow animation 378 int16 _lightX; // for hero shadow 379 int16 _lightY; 380 int32 _shadScaleValue; 381 int32 _shadLineLen; 382 byte *_shadowLine; 383 void setShadowScale(int32 shadowScale); 384 static void plotShadowLinePoint(int x, int y, int color, void *data); 385 386 static const int16 kFPS = 15; 387 static const int32 kIntMax = 2147483647; 388 389 static const int16 kMaxPicWidth = 1280; 390 static const int16 kMaxPicHeight = 480; 391 static const int16 kZoomStep = 4; 392 static const int32 kZoomBitmapLen = kMaxPicHeight / kZoomStep * kMaxPicWidth / kZoomStep; 393 static const int32 kShadowBitmapSize = kMaxPicWidth * kMaxPicHeight / 8; 394 static const int16 kShadowLineArraySize = 2 * 1280 * 4; 395 static const int16 kZoomBitmapWidth = kMaxPicWidth / kZoomStep; 396 static const int16 kZoomBitmapHeight = kMaxPicHeight / kZoomStep; 397 static const int16 kNormalWidth = 640; 398 static const int16 kNormalHeight = 480; 399 static const uint32 kTransTableSize = 256 * 256; 400 401 static const int kMaxNormAnims = 64; 402 static const int kMaxBackAnims = 64; 403 static const int kMaxObjects = 64; 404 static const int kMaxMobs = 64; 405 406 Common::Array<DrawNode> _drawNodeList; 407 Common::Array<AnimListItem> _animList; 408 Common::Array<BackgroundAnim> _backAnimList; 409 Common::Array<Anim> _normAnimList; 410 Common::Array<Mob> _mobList; 411 Common::Array<uint32> _mobPriorityList; 412 Common::Array<Mask> _maskList; 413 Common::Array<Object *> _objList; 414 uint16 *_objSlot; 415 416 void freeNormAnim(int slot); 417 void freeAllNormAnims(); 418 void removeSingleBackAnim(int slot); 419 420 Common::RandomSource _randomSource; 421 422 void checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z); 423 void insertMasks(Graphics::Surface *originalRoomSurface); 424 void showMask(int maskNr, Graphics::Surface *originalRoomSurface); 425 void clsMasks(); 426 427 void grabMap(); 428 429 int _selectedMob; // number of selected Mob / inventory item 430 int _selectedItem; // number of item on mouse cursor 431 int _selectedMode; 432 int _currentPointerNumber; 433 434 static const int16 kMaxInv = 90; // max amount of inventory items in whole game 435 static const uint16 kMaxItems = 30; // size of inventory 436 437 uint32 _invTxtSize; 438 byte *_invTxt; 439 440 Graphics::Surface *_optionsPic; 441 Graphics::Surface *_optionsPicInInventory; 442 443 bool _optionsFlag; 444 int _optionEnabled; 445 int _optionsMob; 446 int _optionsX; 447 int _optionsY; 448 int _optionsWidth; 449 int _optionsHeight; 450 int _invOptionsWidth; 451 int _invOptionsHeight; 452 int _optionsStep; 453 int _invOptionsStep; 454 int _optionsNumber; 455 int _invOptionsNumber; 456 int _optionsColor1; // color for non-selected options 457 int _optionsColor2; // color for selected option 458 459 bool _showInventoryFlag; 460 int _invExamY; 461 bool _inventoryBackgroundRemember; 462 int _invLineX; 463 int _invLineY; 464 int _invLine; // number of items in one line 465 int _invLines; // number of lines with inventory items 466 int _invLineW; 467 int _invLineH; 468 int _maxInvW; 469 int _maxInvH; 470 int _invLineSkipX; 471 int _invLineSkipY; 472 int _invX1; 473 int _invY1; 474 int _invWidth; 475 int _invHeight; 476 bool _invCurInside; 477 int _mst_shadow; 478 int _mst_shadow2; // blinking after adding new item 479 int _candleCounter; // special counter for candle inventory item 480 int _invMaxCount; // time to turn inventory on 481 int _invCounter; // turning on counter 482 483 void inventoryFlagChange(bool inventoryState); 484 bool loadAllInv(); 485 void rememberScreenInv(); 486 void prepareInventoryToView(); 487 void drawInvItems(); 488 void displayInventory(); 489 void addInv(int heroId, int item, bool addItemQuiet); 490 void remInv(int heroId, int item); 491 void clearInv(int heroId); 492 void swapInv(int heroId); 493 void addInvObj(); 494 void makeInvCursor(int itemNr); 495 void enableOptions(bool checkType); 496 void checkOptions(); 497 void checkInvOptions(); 498 void openInventoryCheck(); 499 500 void leftMouseButton(); 501 void rightMouseButton(); 502 void inventoryLeftMouseButton(); 503 void inventoryRightMouseButton(); 504 void dialogLeftMouseButton(byte *string, int dialogSelected); 505 506 uint32 _dialogDatSize; 507 byte *_dialogDat; 508 byte *_dialogData; // on, off flags for lines of dialog text 509 510 byte *_dialogBoxAddr[32]; // adresses of dialog windows 511 byte *_dialogOptAddr[32]; // adresses of dialog options 512 int _dialogOptLines[4 * 32]; // numbers of initial dialog lines 513 514 byte *_dialogText; 515 int _dialogLines; 516 bool _dialogFlag; 517 int _dialogWidth; 518 int _dialogHeight; 519 int _dialogLineSpace; 520 int _dialogColor1; // color for non-selected options 521 int _dialogColor2; // color for selected option 522 Graphics::Surface *_dialogImage; 523 524 void createDialogBox(int dialogBoxNr); 525 void dialogRun(); 526 void talkHero(int slot); 527 void doTalkAnim(int animNumber, int slot, AnimType animType); 528 529 static const uint8 zoomInStep = 8; 530 void initZoomIn(int slot); 531 void initZoomOut(int slot); 532 void doZoomIn(int slot); 533 void doZoomOut(int slot); 534 void freeZoomObject(int slot); 535 536 static const uint8 kFadeStep = 4; 537 void blackPalette(); 538 void setPalette(const byte *palette); 539 540 int getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY); 541 542 // 'Throw a rock' mini-game: 543 static const int16 kCurveLen = 17; 544 static const int kCelStep = 4; 545 int16 *_curveData; 546 int _curvPos; 547 void makeCurve(); 548 void getCurve(); 549 void mouseWeirdo(); 550 551 static const uint16 kPowerBarPosX = 288; 552 static const uint16 kPowerBarPosY = 430; 553 static const uint8 kPowerBarWidth = 64; 554 static const uint8 kPowerBarHeight = 16; 555 static const uint8 kPowerBarBackgroundColor = 0; 556 static const uint16 kPowerBarGreenPosY = 434; 557 static const uint8 kPowerBarGreenColor1 = 202; 558 static const uint8 kPowerBarGreenColor2 = 235; 559 static const uint8 kPowerBarGreenHeight = 8; 560 void showPower(); 561 562 // Pathfinding 563 static const int16 kPathGridStep = 2; 564 static const uint32 kPathBitmapLen = (kMaxPicHeight / kPathGridStep * kMaxPicWidth / kPathGridStep) / 8; 565 static const int32 kTracePts = 8000; 566 static const int32 kPBW = kMaxPicWidth / 16; // PathBitmapWidth 567 static const int kMinDistance = 2500; 568 569 byte *_roomPathBitmap; // PL - Sala 570 byte *_roomPathBitmapTemp; // PL - SSala 571 byte *_coordsBufEnd; 572 byte *_coordsBuf; // optimal path 573 byte *_coords; // last path point adress from coordsBuf 574 byte *_coordsBuf2; 575 byte *_coords2; 576 byte *_coordsBuf3; 577 byte *_coords3; 578 int _traceLineLen; 579 bool _traceLineFirstPointFlag; // if plotTraceLine after first point 580 bool _tracePointFirstPointFlag; // if plotTracePoint after first point 581 byte *_directionTable; 582 int _shanLen; 583 584 byte *_checkBitmapTemp; 585 byte *_checkBitmap; 586 int _checkMask; 587 int _checkX; 588 int _checkY; 589 590 byte *_rembBitmapTemp; 591 byte *_rembBitmap; 592 int _rembMask; 593 int _rembX; 594 int _rembY; 595 596 int _fpX; 597 int _fpY; 598 599 int drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data); 600 bool loadPath(const char *resourceName); 601 byte *makePath(int heroId, int currX, int currY, int destX, int destY); 602 void findPoint(int x, int y); 603 int getPixelAddr(byte *pathBitmap, int x, int y); 604 static int plotTraceLine(int x, int y, void *data); 605 void specialPlotInside(int x, int y); 606 bool tracePath(int x1, int y1, int x2, int y2); 607 Direction makeDirection(int x1, int y1, int x2, int y2); 608 void specialPlot(int x, int y); 609 void specialPlot2(int x, int y); 610 void allocCoords2(); 611 void freeCoords2(); 612 void freeCoords3(); 613 static int plotTracePoint(int x, int y, void *data); 614 void specialPlotInside2(int x, int y); 615 void approxPath(); 616 void freeDirectionTable(); 617 void scanDirections(); 618 int scanDirectionsFindNext(byte *coords, int xDiff, int yDiff); 619 void moveShandria(); 620 void walkTo(); 621 void moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag); 622 623 int leftDownDir(); 624 int leftDir(); 625 int leftUpDir(); 626 int rightDownDir(); 627 int rightDir(); 628 int rightUpDir(); 629 int upLeftDir(); 630 int upDir(); 631 int upRightDir(); 632 int downLeftDir(); 633 int downDir(); 634 int downRightDir(); 635 636 int cpe(); 637 int checkLeftDownDir(); 638 int checkLeftDir(); 639 int checkDownDir(); 640 int checkUpDir(); 641 int checkRightDir(); 642 int checkLeftUpDir(); 643 int checkRightDownDir(); 644 int checkRightUpDir(); 645 646 private: 647 bool playNextFLCFrame(); 648 void keyHandler(Common::Event event); 649 int checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList); 650 void drawScreen(); 651 void showTexts(Graphics::Surface *screen); 652 void init(); 653 void showLogo(); 654 void showAnim(Anim &anim); 655 void showNormAnims(); 656 void setBackAnim(Anim &backAnim); 657 void showBackAnims(); 658 void clearBackAnimList(); 659 bool spriteCheck(int sprWidth, int sprHeight, int destX, int destY); 660 void showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ); 661 void showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ); 662 void showObjects(); 663 void showParallax(); 664 static bool compareDrawNodes(DrawNode d1, DrawNode d2); 665 void runDrawNodes(); 666 void makeShadowTable(int brightness); 667 void pausePrinceEngine(int fps = kFPS); 668 669 uint32 getTextWidth(const char *s); 670 void debugEngine(const char *s, ...); 671 672 uint8 _cursorNr; 673 674 Common::RandomSource *_rnd; 675 Cursor *_cursor1; 676 Graphics::Surface *_cursor2; 677 Cursor *_cursor3; 678 Debugger *_debugger; 679 Font *_font; 680 MusicPlayer *_midiPlayer; 681 682 static const int kMaxSamples = 60; 683 Audio::RewindableAudioStream *_audioStream[kMaxSamples]; 684 Audio::SoundHandle _soundHandle[kMaxSamples]; 685 686 Common::Array<PScr *> _pscrList; 687 Common::Array<InvItem> _allInvList; 688 Common::Array<Mob> _invMobList; 689 690 bool _flicLooped; 691 692 void mainLoop(); 693 694 }; 695 696 } // End of namespace Prince 697 698 #endif 699