ScummVM API documentation
eem.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  *
21  */
22 
23 #ifndef EEM_EEM_H
24 #define EEM_EEM_H
25 
26 #include "common/array.h"
27 #include "common/events.h"
28 #include "common/keyboard.h"
29 #include "common/language.h"
30 #include "common/platform.h"
31 #include "common/random.h"
32 #include "common/rect.h"
33 #include "common/scummsys.h"
34 
35 #include "common/serializer.h"
36 
37 #include "engines/advancedDetector.h"
38 #include "engines/engine.h"
39 #include "engines/savestate.h"
40 
41 #include "graphics/paletteman.h"
42 
43 #include "eem/animation.h"
44 #include "eem/font.h"
45 #include "eem/mystery.h"
46 #include "eem/resource.h"
47 
48 namespace EEM {
49 
50 class TravisScrollBar;
51 
52 class AudioPlayer;
53 class MusicPlayer;
54 
56 const uint kPalSize = 768;
57 
58 // Keep game colors uncorrected for fades and color matching. Apply the Mac
59 // monitor gamma curve only when sending a palette to the backend.
61 public:
62  void setPalette(const byte *colors, uint start, uint num) override;
63  void grabPalette(byte *colors, uint start, uint num) const override;
64 
65 private:
66  byte _colors[kPalSize] = {};
67 };
68 
69 PaletteManager *getPaletteManager();
70 
71 void fadeCurrentPaletteToBlack(uint delayMs = 8);
72 void fadePaletteFromBlack(const byte *target, uint delayMs = 8);
73 
98 enum ScreenId {
99  kScreenInvalid = 0xFFFF,
100  kScreenInitClues = 0x00,
101  kScreenMap = 0x01,
102  kScreenMapAlt = 0x02,
103  kScreenSite = 0x03,
104  kScreenNotebook = 0x04,
105  kScreenGallery = 0x05,
106  kScreenSetup = 0x06,
107  kScreenAccuse = 0x07,
108  kScreenProfile = 0x08,
109  kScreenChoosePartner = 0x09,
110  kScreenChooseMystery = 0x0A,
111  kScreenTitle = 0x0B,
112  kScreenAction = 0x0C
113 };
114 
117 enum Variant {
118  kVariantCD = 0,
119  kVariantFloppy = 1,
120  kVariantLondonCD = 2,
121  kVariantMacFloppy = 3,
122  kVariantMacCD = 4,
123 };
124 
127 enum Partner {
128  kPartnerJake = 0,
129  kPartnerJenny = 1,
130 };
131 
132 constexpr int kScreenWidth = 320;
133 constexpr int kScreenHeight = 200;
134 constexpr int kMacScreenWidth = 512;
135 constexpr int kMacScreenHeight = 384;
136 
137 constexpr Common::Rect kPdaSiteRect (Common::Point(35, 111), 21, 25);
138 constexpr Common::Rect kPdaPartnerFootMapRect (Common::Point( 7, 177), 50, 23);
139 constexpr Common::Rect kPdaPartnerHeadHintRect (Common::Point( 5, 80), 39, 30);
140 
141 class EEMEngine : public Engine {
142  friend class Debugger;
143 
144 public:
145  EEMEngine(OSystem *syst, const ADGameDescription *gameDesc);
146  ~EEMEngine() override;
147 
148  Common::Error run() override;
149  PaletteManager *getPaletteManager();
150 
151  const char *getGameId() const;
152  Common::Platform getPlatform() const;
153  Variant getVariant() const { return _variant; }
154  bool isFloppy() const { return _variant == kVariantFloppy || isDemo(); }
155  bool isLondon() const { return _variant == kVariantLondonCD; }
156  bool isMacCD() const { return _variant == kVariantMacCD; }
157  // London (game) and Macintosh (platform) are orthogonal -- the London CD
158  // shipped for both DOS and Mac -- so derive Mac-ness from the platform
159  // rather than the single-valued `_variant` (which can only hold one of
160  // them at a time). This lets EEM2 Mac be both London and Macintosh.
161  bool isMacintosh() const { return getPlatform() == Common::kPlatformMacintosh; }
162  bool isMacTalkie() const { return isMacCD() || (isMacintosh() && isLondon()); }
163  bool isDemo() const {
164  return _gameDescription && (_gameDescription->flags & ADGF_DEMO);
165  }
166  int screenWidth() const { return isMacintosh() ? kMacScreenWidth : kScreenWidth; }
167  int screenHeight() const { return isMacintosh() ? kMacScreenHeight : kScreenHeight; }
168  int scaleX(int x) const {
169  return isMacintosh() ? scaleCoord(x, kMacScreenWidth, kScreenWidth) : x;
170  }
171  int scaleY(int y) const {
172  return isMacintosh() ? scaleCoord(y, kMacScreenHeight, kScreenHeight) : y;
173  }
174  int unscaleX(int x) const {
175  return isMacintosh() ? scaleCoord(x, kScreenWidth, kMacScreenWidth) : x;
176  }
177  int unscaleY(int y) const {
178  return isMacintosh() ? scaleCoord(y, kScreenHeight, kMacScreenHeight) : y;
179  }
180  Common::Point scalePoint(int x, int y) const {
181  return Common::Point(scaleX(x), scaleY(y));
182  }
183  Common::Rect scaleRect(const Common::Rect &r) const {
184  return Common::Rect(scaleX(r.left), scaleY(r.top),
185  scaleX(r.right), scaleY(r.bottom));
186  }
187 
188  bool hasFeature(EngineFeature f) const override;
189  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
190  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
191 
192  int getAutosaveSlot() const override { return -1; }
193 
194  Common::Error saveGameStream(Common::WriteStream *stream,
195  bool isAutosave = false) override;
196  Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
197 
198  Common::Error saveProfile(const Common::String &name);
199 
200  bool loadProfile(const Common::String &name);
201 
202  SaveStateList listProfiles() const;
203 
204  const ADGameDescription *_gameDescription;
205  Variant _variant = kVariantCD;
206  Common::Language _language = Common::EN_ANY;
207 
209  bool isSpanish() const { return _language == Common::ES_ESP; }
210 
211  DBDArchive &getPics() { return _picsArchive; }
212  DBDArchive &getAni() { return _aniArchive; }
213  DBDArchive &getSites() { return _sitesArchive; }
214  DBDArchive &getBalloons() { return _balloonArchive; }
215  DBDArchive &getButtons() { return _buttonArchive; }
216  Mystery &getMystery() { return _mystery; }
217  const EEMFont &getFont() const { return _font; }
218  uint8 getPartnerIndex() const { return _partner; }
219 
221  void setInteractiveMouseCursor(bool active);
222 
224  void setHotspotMouseCursor(bool active);
225 
229  void setSiteHotspotCursorId(int cursorId);
230 
232  void displayClue(const byte *clueBlock, uint maxEntries = 32);
233 
236  bool doPuzzle(uint puzzleId);
237  bool doMacLondonPuzzle(Common::SeekableReadStream &stream);
238 
239  void displayFloppyHotspotDialog(uint siteNum, uint hotIdx);
240 
241  bool floppyHotspotSearched(uint siteNum, uint hotspotIdx) const;
242 
244  const Common::String &playerName() const { return _playerName; }
245 
247  void applyClueSideEffects(const byte *entry);
248 
249  void doNotebook();
250  void doGallery();
251  bool moreInfo(const byte *gd, uint suspectIdx,
252  const Picture &galBg, bool haveBg);
253  void doBigMap();
254 
256  void doAccuse();
257  void doAccuseFloppy();
258 
261  bool doAccuseNotes();
262 
263  void drawKDBalloonOverCurrentScreen(Common::String text);
264 
266  void doHelp();
267 
269  void doInterfaceHelp(uint num = 0);
270 
272  uint16 getKDTextBalloon(byte firstChar) const;
273 
275  uint16 fitBalloonToText(uint16 bubNum, const Common::String &text);
276 
279  uint getBalloonLineCapacity(uint16 balloonId, int lineH) const;
280 
282  Common::String parseString(const Common::String &raw,
283  const Common::String &playerName,
284  uint partner) const;
285 
288  bool loadKdAnim(uint16 num, Animation &anim, int &px, int &py,
289  uint16 &animId);
290 
291  void setPartnerEraseBg(const Graphics::ManagedSurface *bg);
292 
295  void setPartnerIdleAnim(bool has, uint16 animId, int x, int y) {
296  _hasPartnerIdle = has;
297  _partnerIdleAnimId = animId;
298  _partnerIdleX = x;
299  _partnerIdleY = y;
300  }
301 
308  bool getBalloonInsets(uint16 bubNum, uint16 &xInset, uint16 &yInset,
309  uint16 &textW) const;
310  bool getBalloonIndicatorPos(uint16 bubNum, uint16 &dx,
311  uint16 &dy) const;
312 
313  void drawFloppyBubbleIndicator(Graphics::ManagedSurface &dst,
314  uint16 bubNum, int ballX, int ballY,
315  bool endIndicator);
316 
317  bool areYouSure();
318 
319 private:
320  void applyStartupTestOverrides();
321  bool areYouSureMac();
322  bool areMysteriesSolved(uint lo, uint hi) const;
323 
326  bool anyMysterySolved(uint lo, uint hi) const;
327 
331  uint mysteryTierCount() const { return isLondon() ? 2 : 3; }
332 
335  bool mysteryTierRange(uint stage, uint &lo, uint &hi) const;
336 
337  void advanceChainStageAfterSolve(uint mysteryNum);
338  void applySkipRepeatedCasesOption();
339 
340  void screenDriver();
341 
343  void drawNotebookFrame(int &page, TravisScrollBar *scrollBar = nullptr);
344 
347  Common::String notebookNoteText(uint clueId, const byte *ni,
348  uint16 niCount, bool floppyNb,
349  const byte *bufBase,
350  uint32 mysSz) const;
351 
354  struct AccuseNotesCtx {
355  const byte *ni;
356  uint16 niCount;
357  bool floppyNote;
358  const byte *bufBaseNotes;
359  const Common::Array<uint> *found;
360  int rectX, rectY, rectW, rectH;
361  uint expected;
362  bool haveBg;
363  const Picture *accuseBg;
364  Common::Array<Common::Rect> *slotRects;
365  Common::Array<uint> *slotClues;
366  int *pageBreaks;
367  int pageBreaksCap;
368  int *numPages;
369  int *page;
370  TravisScrollBar *scrollBar = nullptr;
371  };
372 
374  Common::String accuseNoteText(uint clueId, const AccuseNotesCtx &ctx) const;
375 
377  void accuseRebuildPagination(const AccuseNotesCtx &ctx);
378 
380  void accuseDrawScreen(const AccuseNotesCtx &ctx);
381 
385  void floppyKDHint(uint kdSlot, const byte *kdIdx,
386  const byte *bufBase, uint32 mysSize);
387  void displayScrapbookExtra(uint mysteryNum);
388  void displayMacPracticeScrapbook();
389  void accuseDrawGallery(int highlighted,
391  Common::Array<int> &suspects, uint8 num,
392  bool haveAccuseBg, const Picture &accuseBg);
393  void drawGalleryFrame(const byte *gd, uint8 numSuspects,
394  Common::Array<Common::Rect> &slotRects,
395  Common::Array<int> &slotSuspect);
396 
397  struct BigMapOverviewState {
398  Common::Rect window;
399  int zoomX = 0;
400  int zoomY = 0;
401  };
402 
403  struct BigMapDetailState {
404  const Common::Array<byte> *mapPixels = nullptr;
405  uint16 mapW = 0;
406  uint16 mapH = 0;
407 
408  int scrollX = 0;
409  int scrollY = 0;
410  int maxScrollX = 0;
411  int maxScrollY = 0;
412 
413  int mapWinX = 0;
414  int mapWinY = 0;
415  int mapWinW = 0;
416  int mapWinH = 0;
417 
418  Common::Rect returnRect;
419  Common::Rect setupRect;
420  Common::Rect arrowYUp;
421  Common::Rect arrowYDown;
422  Common::Rect arrowXLeft;
423  Common::Rect arrowXRight;
424  Common::Rect xSlider;
425  Common::Rect ySlider;
426 
427  int arrowStepX = 0;
428  int arrowStepY = 0;
429 
430  uint32 startTick = 0;
431  uint32 lastDrawTick = 0;
432  uint32 lastCycleTick = 0;
433  };
434 
435  bool bigMapRunOverview(BigMapOverviewState &state);
436  bool bigMapLoadDetailPixels(Common::Array<byte> &mapPixels,
437  uint16 &mapW, uint16 &mapH);
438  void bigMapInitDetailState(BigMapDetailState &state,
439  const Common::Array<byte> &mapPixels,
440  uint16 mapW, uint16 mapH,
441  const BigMapOverviewState &overview);
442  bool bigMapRunDetail(BigMapDetailState &state);
443  bool bigMapHandleDetailEvent(const Common::Event &ev,
444  BigMapDetailState &state,
445  bool &returnToOverview, bool &dirty);
446  void bigMapHandleDetailKey(const Common::Event &ev,
447  BigMapDetailState &state, bool &dirty);
448  bool bigMapHandleDetailMouseDown(const Common::Event &ev,
449  BigMapDetailState &state,
450  bool &returnToOverview, bool &dirty);
451  bool bigMapTrySelectDetailSite(int mouseX, int mouseY,
452  const BigMapDetailState &state);
453  void bigMapCycleOverviewPalette(bool mac);
454  void bigMapCycleDetailPalette(bool mac);
455  void drawBigMapOverview(uint32 elapsedMs);
456  void drawBigMapDetail(int scrollX, int scrollY,
457  const Common::Array<byte> &mapPixels,
458  uint16 mapW, uint16 mapH,
459  uint32 elapsedMs);
460  void drawAccuseGallery(uint8 numSuspects, const byte *gd,
461  int highlighted,
462  Common::Array<Common::Rect> &slotRects,
463  Common::Array<int> &slotSuspect);
464 
466  bool openArchives();
467 
469  bool loadSitePalettes();
470 
473  void setSitePalette(uint num);
474 
477  bool getSitePalette(uint num, byte *out) const;
478 
481  bool setAnmPalette(const Common::Path &anmPath);
482 
483 public:
485  void setSitePaletteForSite(uint siteNum) { setSitePalette(siteNum + 1); }
486 private:
487 
488  void blitAt(const Picture &pic, int x, int y);
489 
494  void blitAtScaled(const Picture &pic, int x, int y, int scale);
495 
496 public:
497  void waitForInput(uint32 maxMs);
498 
507  bool playAnm(const Common::Path &path, uint frameDelayMs = 120,
508  bool holdLastFrame = false, bool fadeIn = false,
509  bool setSkipIntroOnEsc = true, bool showLastFrameOnSkip = false);
510 
514  void playFlc(const Common::Path &path, bool fadeIn = false,
515  bool holdLastFrame = false, uint16 backgroundPict = 0);
516 
517 private:
518  void interruptAudio(bool stopMusicToo = true);
519 
520  void showEAKidsLogo();
521  void showHighScoreLogo();
522  void showFloppyStormLogo();
523 
524  bool waitIntroDelay(uint32 maxMs);
525  void runMacStartup();
526  void playMacCDIntro();
527  void showMacEAKidsLogo();
528  void showMacStillLogo(uint picId, uint palId, uint holdMs,
529  bool playThunder);
530  void showMacTitleIntro();
531 
532  void runLondonStartup();
533  void showMacLondonTitle();
535  bool startLondonTrainingMystery();
536  void showLondonEAKidsLogo();
537  void showStillPicture(uint picId, uint palId, uint holdMs,
538  bool playThunder = false, bool holdLastFrame = false);
539  void showLondonCharSelect();
540  void playLondonInitCluesAnim(uint16 caseType, const Picture &bg,
541  bool haveBriefingBg);
542  void playMacLondonInitCluesAnim(uint16 caseType, const Picture &bg,
543  bool haveBriefingBg);
544  void playCdFloppyInitCluesAnim(uint16 caseType, bool floppy,
545  const Picture &bg, bool haveBriefingBg);
546 
547  void doProfilePicker();
548  void doNewPlayer();
549  void doChoosePartner();
550 
560  int doShowEnding(uint num, bool firstPage = true);
561 
565  void doShowScrapbook(uint stage);
566 
567  void doActionScreen();
568  void doCaseSelection();
569  void doSiteLoop();
570 
571  void doSetup();
572 
573  void setupDrawScreen();
574  Common::KeyCode setupShowFullscreenPic(uint16 picId, bool transparent);
575  void setupLeave();
576 
577  void doSetupLondon();
578  void setupDrawScreenLondon();
581  void setupShowSavedConfirm();
582 
584  void doInitClues();
585 
592  void displayFloppyBriefing(const byte *initBlock);
593 
597  void displayFloppyDialogRecords(const byte *rec, uint count,
598  uint lastIndicator = 0);
599 
603  bool floppyDialogWaitForClick();
604 
605 public:
608  void startTravelMusic();
609  void finishTravelMusic(bool skipped);
610 
612  void waitForMusicDone(uint32 maxMs = 60000);
613 
615  void stopMusic();
616 
619  bool doLondonApproach(uint16 approachId);
620 
623  void syncSoundSettings() override;
624 
627  void startLondonTravelMusic(uint8 travelKind);
628  bool playMacLondonTravelAnimation(uint8 travelKind);
629 private:
630  static int scaleCoord(int value, int target, int source) {
631  const bool negative = value < 0;
632  const int magnitude = negative ? -value : value;
633  const int scaled = (magnitude * target + source / 2) / source;
634  return negative ? -scaled : scaled;
635  }
636 
637  Common::String _playerName;
638 
643  bool _playerFemale = false;
644 
646  uint8 _mysteriesSolved[55] = {};
647  uint8 _chainStage = 1;
648  // Applied on case selection to preserve the current case's difficulty.
649  uint8 _pendingBookUnlock = 0;
650 
651  bool _voiceOn = true;
652  bool _musicOn = true;
653 
656  bool _profileCreatedThisSession = false;
657 
659 
660  DBDArchive _picsArchive;
661  DBDArchive _aniArchive;
662  DBDArchive _sitesArchive;
663  DBDArchive _balloonArchive;
664  DBDArchive _buttonArchive;
665  Mystery _mystery;
666  EEMFont _font;
667  EEMFont _dialogFont;
668  EEMFont _newspaperFont;
669 
670  Common::Array<byte> _sitePals;
671  MacPaletteManager _macPaletteManager;
672 
673  uint16 _lastScreen;
674  uint16 _nextScreen;
675  uint8 _partner;
676 
678  bool _skipIntro = false;
679 
681  Graphics::ManagedSurface _partnerEraseBg;
682 
684  bool _hasPartnerIdle = false;
685  uint16 _partnerIdleAnimId = 0;
686  int _partnerIdleX = 0;
687  int _partnerIdleY = 0;
688 
689  bool _interactiveMouseCursor = false;
692  int _siteCursorId = 0;
693 
696  int _lastSiteArrivalAnim = -1;
697 
698  bool _restoredContentDataLoaded = false;
699 
702  MusicPlayer *_music = nullptr;
703 
704 public:
705  AudioPlayer *_audio = nullptr;
706 
708  void setNextScreen(ScreenId s) { _nextScreen = s; }
709  bool shouldPlaySiteArrival(uint siteNum) const {
710  return _lastSiteArrivalAnim != (int)siteNum;
711  }
712  void markSiteArrivalPlayed(uint siteNum) {
713  _lastSiteArrivalAnim = (int)siteNum;
714  }
715  void resetSiteArrivalState() {
716  _lastSiteArrivalAnim = -1;
717  }
718  void setSiteArrivalState(uint siteNum) {
719  _lastSiteArrivalAnim = (int)siteNum;
720  }
721 };
722 
723 Common::Rect pdaControlRect(const EEMEngine *vm, const Common::Rect &rect);
724 
725 } // End of namespace EEM
726 
727 #endif
Definition: managed_surface.h:51
Definition: str.h:59
void grabPalette(byte *colors, uint start, uint num) const override
void setNextScreen(ScreenId s)
_NextScreen @ 2d5d:3f26 writer for site loop / inline screens.
Definition: eem.h:708
EngineFeature
Definition: engine.h:282
Definition: stream.h:77
Definition: error.h:81
T left
Definition: rect.h:170
int getAutosaveSlot() const override
Definition: eem.h:192
Definition: mystery.h:50
Definition: advancedDetector.h:164
Definition: console.h:31
Definition: random.h:44
Definition: rect.h:536
Definition: path.h:52
Definition: resource.h:48
Definition: audio.h:56
Definition: stream.h:745
bool isSpanish() const
Spanish floppy release.
Definition: eem.h:209
void setPalette(const byte *colors, uint start, uint num) override
T right
Definition: rect.h:171
Definition: font.h:55
.DBD + .DBX archive pair (PICS, SITES, ANI, BALLOON, BUTTON).
Definition: resource.h:60
Definition: animation.h:30
Definition: ustr.h:57
void setSitePaletteForSite(uint siteNum)
Public so SiteScreen can switch palettes per site.
Definition: eem.h:485
const Common::String & playerName() const
Active player name (= profile-save description).
Definition: eem.h:244
Definition: events.h:218
Definition: eem.h:141
void setPartnerIdleAnim(bool has, uint16 animId, int x, int y)
Definition: eem.h:295
Definition: rect.h:144
Definition: eem.h:60
Definition: system.h:166
Definition: music.h:57
Add "-demo" to gameid.
Definition: advancedDetector.h:157
Definition: paletteman.h:47
Definition: engine.h:149
Platform
Definition: platform.h:93
Language
Definition: language.h:45