ScummVM API documentation
bolt.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 #ifndef BOLT_H
23 #define BOLT_H
24 
25 #include "common/scummsys.h"
26 #include "common/system.h"
27 #include "common/error.h"
28 #include "common/fs.h"
29 #include "common/hash-str.h"
30 #include "common/random.h"
31 #include "common/serializer.h"
32 #include "common/util.h"
33 #include "engines/engine.h"
34 #include "engines/savestate.h"
35 #include "graphics/screen.h"
36 
37 #include "bolt/detection.h"
38 #include "bolt/xplib/xplib.h"
39 
40 namespace Bolt {
41 
42 #define SCREEN_WIDTH 320
43 #define SCREEN_HEIGHT 200
44 #define EXTENDED_SCREEN_WIDTH 384
45 #define EXTENDED_SCREEN_HEIGHT 240
46 
47 struct BoltGameDescription;
48 class XpLib;
49 
50 typedef struct DisplaySpecs {
51  int16 id;
52  int16 width;
53  int16 height;
54 } DisplaySpecs;
55 
56 typedef int16 (BoltEngine::*SideShowHandler)(int16 prevBooth);
57 
58 struct BarkerTable {
59  SideShowHandler *handlers;
60  int16 count;
61  int16 minIndex;
62  int16 maxIndex;
63 };
64 
65 typedef struct BOLTHeader {
66  byte header[11];
67  byte groupCount;
68  uint32 groupDirOffset;
69 
70  BOLTHeader() {
71  memset(header, 0, sizeof(header));
72  groupCount = 0;
73  groupDirOffset = 0;
74  }
75 } BOLTHeader;
76 
77 typedef void (*BOLTCallback)(void);
78 
79 typedef struct BOLTCallbacks {
80  BOLTCallback *typeLoadCallbacks;
81  BOLTCallback *typeFreeCallbacks;
82  BOLTCallback *memberLoadCallbacks;
83  BOLTCallback *memberFreeCallbacks;
84  BOLTCallback *groupLoadCallbacks;
85  BOLTCallback *groupFreeCallbacks;
86 
87  BOLTCallbacks() {
88  typeLoadCallbacks = nullptr;
89  typeFreeCallbacks = nullptr;
90  memberLoadCallbacks = nullptr;
91  memberFreeCallbacks = nullptr;
92  groupLoadCallbacks = nullptr;
93  groupFreeCallbacks = nullptr;
94  }
96 
97 typedef struct BOLTMemberEntry {
98  byte flags;
99  byte preLoadCbIndex;
100  byte preFreeCbIndex;
101  byte typeCbIndex;
102  uint32 decompSize;
103  uint32 fileOffset;
104  uint32 dataPtrPlaceholder;
105  byte *dataPtr;
106 
107  BOLTMemberEntry() {
108  flags = 0;
109  preLoadCbIndex = 0;
110  preFreeCbIndex = 0;
111  typeCbIndex = 0;
112  decompSize = 0;
113  fileOffset = 0;
114  dataPtrPlaceholder = 0;
115  dataPtr = nullptr;
116  }
118 
119 typedef struct BOLTGroupEntry {
120  byte flags;
121  byte loadCbIndex;
122  byte freeCbIndex;
123  byte memberCount;
124  uint32 memberDirOffset;
125  uint32 memberDataOffset;
126  uint32 groupDataPtrPlaceholder;
127  byte *memberData;
128  BOLTMemberEntry *members;
129 
130  BOLTGroupEntry() {
131  flags = 0;
132  loadCbIndex = 0;
133  freeCbIndex = 0;
134  memberCount = 0;
135  memberDirOffset = 0;
136  memberDataOffset = 0;
137  groupDataPtrPlaceholder = 0;
138  memberData = nullptr;
139  members = nullptr;
140  }
141 
142  ~BOLTGroupEntry() {
143  free(memberData);
144  memberData = nullptr;
145 
146  delete[] members;
147  members = nullptr;
148  }
149 
150  void initMembers(int numMembers) {
151  int actualNumber = numMembers == 0 ? 256 : numMembers;
152  members = new BOLTMemberEntry[actualNumber];
153  }
154 
156 
157 typedef struct BOLTLib {
158  int16 refCount;
159  int16 groupCount;
160  Common::File *fileHandle;
161  BOLTCallbacks callbacks;
162  BOLTGroupEntry *groups;
163 
164  BOLTLib(int inGroupCount) {
165  refCount = 0;
166  groupCount = 0;
167  fileHandle = nullptr;
168  groups = new BOLTGroupEntry[inGroupCount];
169  }
170 
171  ~BOLTLib() {
172  delete[] groups;
173  }
174 } BOLTLib;
175 
176 typedef struct RTFResource {
177  Common::File *fileHandle;
178  uint32 *indexTablePtr;
179  int16 entryCount;
180  byte *indexTableRawData;
181  uint32 *indexTable;
182 
183  RTFResource() {
184  fileHandle = nullptr;
185  indexTablePtr = nullptr;
186  entryCount = 0;
187  indexTableRawData = nullptr;
188  indexTable = nullptr;
189  }
190 
191  ~RTFResource() {
192  if (indexTable)
193  delete[] indexTable;
194  }
195 
196  void reserveTableSize(int numElements) {
197  indexTable = new uint32[numElements];
198  }
199 } RTFResource;
200 
201 struct RTFPacket;
202 typedef struct RTFPacket {
203  uint32 tag;
204  uint32 allocSize;
205  uint32 dataSize;
206  byte *dataPtr;
207  int16 skipCount;
208  int16 frameRate;
209  int16 duration;
210  int16 timestamp;
211  RTFPacket *next;
212  byte *ringBufPtr;
213 
214  RTFPacket() {
215  tag = 0;
216  allocSize = 0;
217  dataSize = 0;
218  dataPtr = nullptr;
219  skipCount = 0;
220  frameRate = 0;
221  duration = 0;
222  timestamp = 0;
223  next = nullptr;
224  ringBufPtr = nullptr;
225  }
226 } RTFPacket;
227 
228 struct SSprite;
229 
230 typedef void (*SSpriteUpdateFunc)(void);
231 typedef void (*SSpritePathCallback)(SSprite *);
232 
233 typedef struct SSprite {
234  int16 flags;
235  int16 x;
236  int16 y;
237  int16 frameCount;
238  int16 currentFrame;
239  byte **frameData;
240  SSpriteUpdateFunc updateFunc;
241  SSpritePathCallback pathCallback;
242  int16 frameTimer;
243  int16 frameRate;
244  int16 startFrame;
245  int16 stopFrame;
246  int16 velocityX;
247  int16 velocityY;
248  int16 xLimitLow;
249  int16 xLimitHigh;
250  int16 yLimitLow;
251  int16 yLimitHigh;
252  int16 accelX;
253  int16 accelY;
254  int16 dragX;
255  int16 dragY;
256  byte *pathData;
257  int16 pathOffset;
258  int16 pathLength;
259  int16 collX;
260  int16 collY;
261  int16 collW;
262  int16 collH;
263  int16 userInfo;
264 
265  SSprite() {
266  flags = 0;
267  x = 0;
268  y = 0;
269  frameCount = 0;
270  currentFrame = 0;
271  frameData = nullptr;
272  updateFunc = nullptr;
273  pathCallback = nullptr;
274  frameTimer = 0;
275  frameRate = 0;
276  startFrame = 0;
277  stopFrame = 0;
278  velocityX = 0;
279  velocityY = 0;
280  xLimitLow = 0;
281  xLimitHigh = 0;
282  yLimitLow = 0;
283  yLimitHigh = 0;
284  accelX = 0;
285  accelY = 0;
286  dragX = 0;
287  dragY = 0;
288  pathData = nullptr;
289  pathOffset = 0;
290  pathLength = 0;
291  collX = 0;
292  collY = 0;
293  collW = 0;
294  collH = 0;
295  userInfo = 0;
296  }
297 } SSprite;
298 
299 // FRED GAME
300 
301 typedef struct SoundInfo {
302  byte *data;
303  uint32 size;
304  byte priority;
305  byte channel;
306 
307  SoundInfo() {
308  data = nullptr;
309  size = 0;
310  priority = 0;
311  channel = 0;
312  }
313 } SoundInfo;
314 
315 
316 typedef struct FredEntityState {
317  uint16 flags;
318  int16 frameCountdown;
319  int16 animMode;
320  int16 frameIndex;
321  byte *animTable;
322  int16 direction;
323  int32 xPos;
324  int32 yPos;
325  int32 prevXPos;
326  int32 prevYPos;
327  int16 speed;
328  byte *pathTable;
329  int16 pathIndex;
330 
331  FredEntityState() {
332  flags = 0;
333  frameCountdown = 0;
334  animMode = 0;
335  frameIndex = 0;
336  animTable = nullptr;
337  direction = 0;
338  xPos = 0;
339  yPos = 0;
340  prevXPos = 0;
341  prevYPos = 0;
342  speed = 0;
343  pathTable = nullptr;
344  pathIndex = 0;
345  }
347 
348 // HUCK GAME
349 
350 typedef struct HuckState {
351  int16 levelNumber;
352  int16 slotIndex[10];
353  int16 levelComplete;
354  int16 drawTable1[24];
355  int16 drawTable2[24];
356  int16 giftCount;
357  int16 hasCycle;
358  int16 selectionPending;
359  int16 selected1Slot;
360  int16 selected2Slot;
361  int16 selected1SpriteId;
362  int16 selected2SpriteId;
363 
364  HuckState() {
365  levelNumber = 0;
366  memset(slotIndex, 0, sizeof(slotIndex));
367  levelComplete = 0;
368  memset(drawTable1, 0, sizeof(drawTable1));
369  memset(drawTable2, 0, sizeof(drawTable2));
370  giftCount = 0;
371  hasCycle = 0;
372  selectionPending = 0;
373  selected1Slot = 0;
374  selected2Slot = 0;
375  selected1SpriteId = 0;
376  selected2SpriteId = 0;
377  }
378 } HuckState;
379 
380 // GEORGE GAME
381 
382 typedef struct GeorgeEntityState {
383  uint16 flags;
384  int16 frameCountdown;
385  int16 animMode;
386  int16 variant;
387  int16 frameIndex;
388  byte *animTable;
389  int32 joyInput;
390  int32 x;
391  int32 y;
392  int32 prevX;
393  int32 prevY;
394  int32 velX;
395  int32 velY;
396  int32 accelX;
397  int32 accelY;
398  byte *pathTable;
399  int16 pathIndex;
400 
402  flags = 0;
403  frameCountdown = 0;
404  animMode = 0;
405  variant = 0;
406  frameIndex = 0;
407  animTable = nullptr;
408  joyInput = 0;
409  x = 0;
410  y = 0;
411  prevX = 0;
412  prevY = 0;
413  velX = 0;
414  velY = 0;
415  accelX = 0;
416  accelY = 0;
417  pathTable = nullptr;
418  pathIndex = 0;
419  }
421 
422 // SCOOBY GAME
423 
424 typedef struct ScoobyState {
425  int16 levelNumber;
426  int16 slotIndex[10];
427  int16 levelComplete;
428  int16 wallStates[25][4];
429  int16 scoobyCell;
430  int16 scoobySavedCell;
431  int16 leftNeighbor;
432  int16 rightNeighbor;
433  int16 upNeighbor;
434  int16 downNeighbor;
435  int16 activeLevel;
436  int16 scoobyX;
437  int16 scoobyY;
438  int16 velocityX;
439  int16 velocityY;
440  int16 targetVelocityX;
441  int16 targetVelocityY;
442  int16 transitionTarget;
443  int16 currentAnim;
444  int16 direction;
445  int16 spriteFrameCount;
446  byte *frameData[6];
447 
448  ScoobyState() {
449  levelNumber = 0;
450 
451  for (int i = 0; i < 10; i++)
452  slotIndex[i] = 0;
453 
454  levelComplete = 0;
455 
456  for (int i = 0; i < 25; i++)
457  for (int j = 0; j < 4; j++)
458  wallStates[i][j] = 0;
459 
460  scoobyCell = 0;
461  scoobySavedCell = 0;
462  leftNeighbor = 0;
463  rightNeighbor = 0;
464  upNeighbor = 0;
465  downNeighbor = 0;
466  activeLevel = 0;
467  scoobyX = 0;
468  scoobyY = 0;
469  velocityX = 0;
470  velocityY = 0;
471  targetVelocityX = 0;
472  targetVelocityY = 0;
473  transitionTarget = 0;
474  currentAnim = 0;
475  direction = 0;
476  spriteFrameCount = 0;
477 
478  for (int i = 0; i < 6; i++)
479  frameData[i] = nullptr;
480  }
481 } ScoobyState;
482 
483 typedef struct ScoobyRect {
484  int16 left;
485  int16 right;
486  int16 top;
487  int16 bottom;
488 
489  ScoobyRect() {
490  left = 0;
491  right = 0;
492  top = 0;
493  bottom = 0;
494  }
495 } ScoobyRect;
496 
497 // TOPCAT GAME
498 
499 typedef struct TopCatAnim {
500  int16 animType;
501  int16 animIndex;
502  int16 transitionToNextQuestionFlag;
503  int16 *seqPtr;
504 
505  TopCatAnim() {
506  animType = 0;
507  animIndex = 0;
508  transitionToNextQuestionFlag = 0;
509  seqPtr = nullptr;
510  }
511 } TopCatAnim;
512 
513 // YOGI GAME
514 
515 typedef struct YogiState {
516  int16 levelNumber;
517  int16 currentSlot;
518  int16 levelIndex[10];
519  int16 slotIndex[10];
520  int16 levelComplete;
521  int16 basketSound[24];
522  int16 basketState[24];
523  int16 basketCount;
524  int16 matchCount;
525  int16 selectionPending;
526  int16 selected1Slot;
527  int16 selected2Slot;
528  int16 sound1;
529  int16 sound2;
530 
531  YogiState() {
532  levelNumber = 0;
533  currentSlot = 0;
534  memset(levelIndex, 0, sizeof(levelIndex));
535  memset(slotIndex, 0, sizeof(slotIndex));
536  levelComplete = 0;
537  memset(basketSound, 0, sizeof(basketSound));
538  memset(basketState, 0, sizeof(basketState));
539  basketCount = 0;
540  matchCount = 0;
541  selectionPending = 0;
542  selected1Slot = 0;
543  selected2Slot = 0;
544  sound1 = 0;
545  sound2 = 0;
546  }
547 } YogiState;
548 
549 class BoltEngine : public Engine {
550 friend class XpLib;
551 
552 private:
553  const ADGameDescription *_gameDescription;
554  Common::RandomSource _randomSource;
555 protected:
556  // Engine APIs
557  Common::Error run() override;
558 
559 public:
560  BoltEngine(OSystem *syst, const ADGameDescription *gameDesc);
561  ~BoltEngine() override;
562 
563  uint32 getFeatures() const;
564 
568  Common::String getGameId() const;
569 
570  bool hasFeature(EngineFeature f) const override {
571  return (f == kSupportsReturnToLauncher);
572  };
573 
574  // This engine doesn't save anything!
575  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
576  return false;
577  }
578  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
579  return false;
580  }
581 
582 protected:
583  DisplaySpecs _displaySpecs[2] = {
584  {0, 384, 240},
585  {1, 320, 200}
586  };
587 
588  XpLib *_xp = nullptr;
589  bool _extendedViewport = false;
590  bool _isDemo = false;
591 
592  // xpMain
593  void boltMain();
594  void setCursorPict(byte *sprite);
595  int16 displayDemoPict(int16 prevBooth);
596 
597  // Booth
598  void startCycle(byte *cycleResource);
599  void displayBooth(int16 page);
600  void playAVOverBooth(int16 animIndex);
601  int16 hucksBooth(int16 prevBooth);
602  int16 fredsBooth(int16 prevBooth);
603  int16 scoobysBooth(int16 prevBooth);
604  int16 yogisBooth(int16 prevBooth);
605  int16 georgesBooth(int16 prevBooth);
606  int16 topCatsBooth(int16 prevBooth);
607  int16 mainEntrance(int16 prevBooth);
608  bool loadBooth(int16 boothId);
609  void unloadBooth();
610  int16 openBooth(int16 boothId);
611  void closeBooth();
612  void playTour();
613  void finishPlayingHelp(int16 activeHotspot);
614  int16 hotSpotActive(int16 hotspot);
615  void hoverHotSpot();
616  int16 boothEventLoop();
617  void resetInactivityState();
618  bool handleButtonPress(int16 hotspot);
619  void blastColors(byte **paletteTable, int16 index, int16 mode);
620  void setColors(int16 index);
621  void restoreColors(int16 index);
622  void loadColors();
623  void shiftColorMap(byte *colorMap, int16 delta);
624  void playBoothAV();
625  void mainEntranceHelpBlink();
626  void boothHelpBlink();
627  void tourPaletteCycleStep();
628  void fadeToBlack(int16 steps);
629  void flushInput();
630  int16 winALetter(int16 prevBooth);
631  int16 endDemo(int16 prevBooth);
632 
633  int16 _lettersWon = 0;
634  bool _allLettersWonFlag = false;
635  int _displayMode = 0;
636  int32 _displayX = 0;
637  int32 _displayY = 0;
638  int32 _displayWidth = 0;
639  int32 _displayHeight = 0;
640 
641  int16 _boothLoadedMask = 0;
642  int16 _currentBoothScene = 0;
643  int16 _boothNumHotspots = 0;
644  int16 _boothNumAnimations = 0;
645  byte *_boothSceneDesc = nullptr;
646  byte *_boothHotPalDescs[4];
647  Common::Rect _boothHotspotDescs[8];
648  byte *_boothAnimDescs[7];
649  byte *_boothAnimPalDescs[4];
650  byte _savedPalettes[7][30];
651  byte _savedHotPalettes[4][9];
652  byte *_boothPalCycleData = nullptr;
653  XPPicDesc _boothLetterSprite;
654  bool _needInitCursorPos = true;
655  byte *_boothVisitSignOn = nullptr;
656  byte *_boothVisitSignOff = nullptr;
657  byte _leftDoorNavTable[3] = { 3, 2, 4 };
658  byte _rightDoorNavTable[3] = { 1, 0, 5 };
659 
660  int16 _cursorX = 0;
661  int16 _cursorY = 0;
662  int16 _hoveredHotspot = 0;
663  uint32 _helpTimer = 0;
664  int16 _keyReleased = 0;
665  int16 _keyLeft = 0;
666  int16 _keyRight = 0;
667  int16 _keyUp = 0;
668  int16 _keyDown = 0;
669  int16 _helpFlag = 0;
670  int16 _keyEnter = 0;
671 
672  int16 _tourStep = 0;
673  int16 _helpPlaying = 0;
674  int16 _helpIsIdle = 0;
675  int16 _idleHelpAudioAvailable = 1;
676 
677  int16 _huckWins = 0;
678  int16 _fredWins = 0;
679  int16 _scoobyWins = 0;
680  int16 _yogiWins = 0;
681  int16 _georgeWins = 0;
682  int16 _topCatWins = 0;
683 
684  // Barker
685  BarkerTable *createBarker(int16 minIndex, int16 maxIndex);
686  void freeBarker(BarkerTable *table);
687  bool registerSideShow(BarkerTable *table, SideShowHandler handler, int16 boothId);
688  int16 barker(BarkerTable *table, int16 startBooth);
689  bool checkError();
690 
691  int32 _curErrorCode = 0;
692  int16 _currentBoothId = 0;
693 
694  // Utils
695  void displayColors(byte *palette, int16 page, int16 flags);
696  byte getPixel(byte *sprite, int16 localX, int16 localY);
697  void boltPict2Pict(XPPicDesc *dest, byte *boltSprite);
698  void displayPic(byte *boltSprite, int16 xOff, int16 yOff, int16 page);
699  bool pointInRect(Common::Rect *rect, int16 x, int16 y);
700  const char *assetPath(const char *fileName);
701  void boltCycleToXPCycle(byte *srcData, XPCycleState *cycleDesc);
702  void unpackColors(int16 count, byte *packedColors);
703  bool intersectRect(const Common::Rect *a, const Common::Rect *b, Common::Rect *out);
704 
705  // Swap
706  void swapPicHeader();
707  void swapAndResolvePicDesc();
708  void swapFirstWord();
709  void swapFirstTwoWords();
710  void swapFirstFourWords();
711  void swapSpriteHeader();
712  void freeSpriteCleanUp();
713 
714  // Resource
715  bool libRead(Common::File *fileHandle, uint32 offset, byte *dest, uint32 size);
716  void decompress(byte *dest, uint32 decompSize, byte *src);
717  void resolveIt(uint32 *ref);
718  void resolvePendingFixups();
719  void resolveFunction(uint32 *ref);
720  void resolveAllRefs();
721  byte *getResolvedPtr(byte *data, int offset);
722  bool openBOLTLib(BOLTLib **outLib, BOLTCallbacks *outIdx, const char *fileName);
723  bool closeBOLTLib(BOLTLib **lib);
724  bool attemptFreeIndex(BOLTLib *lib, int16 groupId);
725  bool loadGroupDirectory();
726  bool getBOLTGroup(BOLTLib *lib, int16 groupId, int16 flags);
727  void freeBOLTGroup(BOLTLib *lib, int16 groupId, int16 flags);
728  byte *getBOLTMember(BOLTLib *lib, int16 resId);
729  bool freeBOLTMember(BOLTLib *lib, int16 resId);
730  Common::Rect memberToRect(byte *data);
731  byte *memberAddr(BOLTLib *lib, int16 resId);
732  byte *memberAddrOffset(BOLTLib *lib, uint32 resIdAndOffset);
733  uint32 memberSize(BOLTLib *lib, int16 resId);
734  byte *groupAddr(BOLTLib *lib, int16 groupId);
735  bool allocResourceIndex();
736  void freeResourceIndex();
737  void swapAllWords();
738  void swapAllLongs();
739 
740  BOLTLib *_boothsBoltLib = nullptr;
741  BOLTCallbacks _boothsBoltCallbacks;
742 
743  static BOLTCallback _defaultTypeLoadCallbacks[25];
744  static BOLTCallback _defaultTypeFreeCallbacks[25];
745  static BOLTCallback _defaultMemberLoadCallbacks[25];
746  static BOLTCallback _defaultMemberFreeCallbacks[25];
747  static BOLTCallback _defaultGroupLoadCallbacks[25];
748  static BOLTCallback _defaultGroupFreeCallbacks[25];
749 
750  static void noOpCb();
751 
752  static void swapAllWordsCb();
753  static void swapAllLongsCb();
754  static void swapPicHeaderCb();
755  static void swapAndResolvePicDescCb();
756  static void swapFirstWordCb();
757  static void swapFirstTwoWordsCb();
758  static void swapFirstFourWordsCb();
759  static void swapSpriteHeaderCb();
760  static void freeSpriteCleanUpCb();
761 
762  void initCallbacks();
763 
764  int16 _resourceIndexCount = 1000;
765  uint32 **_resourceIndex = nullptr;
766  Common::Array<byte *> _resolvedPtrs;
767  Common::File *_cachedFileHandle = nullptr;
768  uint32 _cachedFilePos = 0xFFFFFFFF;
769  BOLTLib *_boltCurrentLib = nullptr;
770  BOLTHeader _boltFileHeader;
771  BOLTGroupEntry *_boltCurrentGroupEntry = nullptr;
772  int16 _boltLoadDepth = 0;
773  byte *_boltRawMemberData = nullptr;
774  BOLTMemberEntry *_boltCurrentMemberEntry = nullptr;
775  int16 _pendingFixupCount = 0;
776 
777  // Game state
778  bool initVRam(int16 poolSize);
779  void freeVRam();
780  bool vLoad(void *dest, const char *name);
781  bool vSave(void *src, uint16 srcSize, const char *name);
782  bool vDelete(const char *name);
783  byte *dataAddress(int16 recordOffset);
784  uint16 dataSize(int16 recordOffset);
785  bool findRecord(const char *name, int16 *outOffset);
786 
787  int32 _vramRecordCount = 0;
788  int32 _vramUsedBytes = 0;
789  byte *_allocatedMemPool = nullptr;
790  uint32 _allocatedMemPoolSize = 0;
791 
792  // RTF
793  RTFResource *openRTF(const char *fileName);
794  void closeRTF(RTFResource *rtf);
795  bool playRTF(RTFResource *rtfFile, int16 animIndex, byte *ringBuffer, int32 bufferSize);
796  bool fillRTFBuffer();
797  void flushRTFSoundQueue();
798  bool maintainRTF(int16 mode, RTFPacket **outFrameData);
799  bool isRTFPlaying();
800  bool killRTF(uint32 *outFilePos);
801  bool readPacket();
802  void preProcessPacket(RTFPacket *packet);
803  void queuePacket(RTFPacket *packet);
804  RTFPacket *deQueuePacket();
805  RTFPacket *allocPacket(uint32 dataSize);
806  void freePacket(RTFPacket *packet);
807  void resetPlaybackState();
808  void setAVBufferSize(uint32 bufSize);
809 
810  RTFResource *_rtfHandle = nullptr;
811  Common::File *_rtfFileHandle = nullptr;
812  uint32 _rtfChunkRemaining = 0;
813  bool _rtfMidChunk = false;
814  RTFPacket *_rtfCurrentPacket = nullptr;
815  byte *_ringBufBase = nullptr;
816  byte *_ringBufWritePtr = nullptr;
817  uint32 _ringBufSize = 0;
818  uint32 _ringBufFreeSpace = 0;
819  uint32 _ringBufLowWater = 0;
820  uint32 _ringBufHighWater = 0;
821  uint32 _ringBufUsed = 0;
822  bool _rtfSoundActive = false;
823  int16 _rtfPlaybackTime = 0;
824  int16 _rtfCumulativeTime = 0;
825  RTFPacket *_rtfPendingFrame = nullptr;
826  RTFPacket *_rtfSoundQueueHead = nullptr;
827  RTFPacket *_rtfSoundPlayHead = nullptr;
828  RTFPacket *_rtfChunkListTail = nullptr;
829  RTFPacket *_rtfChunkListHead = nullptr;
830  int16 _rtfChunkCount = 0;
831  int16 _rtfQueuedSoundCount = 0;
832  int16 _rtfSoundTiming = 0;
833  uint32 _rtfAnimStartOffset = 0;
834  bool _rtfNeedInitialFill = false;
835  uint32 _rtfChunkTag = 0;
836  uint32 _rtfChunkSize = 0;
837 
838  // AV
839  bool prepareAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
840  bool maintainAV(int16 mode);
841  void stopAV();
842  bool playAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
843  void processPacket(RTFPacket *packet);
844  void processRL7(RTFPacket *packet);
845  void processPLTE(RTFPacket *packet);
846  bool initAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
847  void cleanUpAV();
848 
849  byte *_avRingBuffer = nullptr;
850  uint32 _avTargetBufSize = 0x0FA000;
851  int16 _avSkipLevel = 0;
852  byte *_avFrontPalette = nullptr;
853  byte *_avBackPalette = nullptr;
854  uint32 _avSavedInactivityTimer = 0;
855  uint32 _avSavedScreenSaverTimer = 0;
856  int16 _avFrameAccum = 0;
857  int16 _avDisplayX = 0;
858  int16 _avDisplayY = 0;
859 
860  XPPicDesc _avFrontBufDesc;
861  XPPicDesc _avBackBufDesc;
862 
863  // Anim
864  bool startAnimation(RTFResource *rtf, int16 animIndex);
865  void stopAnimation();
866  bool maintainAudioPlay(int16 mode);
867  bool initAnim(RTFResource *rtf, int16 animIndex);
868  void cleanUpAnim();
869 
870  int16 _animPrevInactivityTimer = 0;
871  byte *_animRingBuffer = nullptr;
872  Common::File *_animFileHandle = nullptr;
873 
874  // SSprite
875  void setUpSSprite(SSprite *sprite, int16 frameCount, byte **frameData, int16 frameRate, int16 velocityX, int16 velocityY);
876  void animateSSprite(SSprite *sprite, int16 page);
877  void displaySSprite(SSprite *sprite, int16 x, int16 y);
878  void eraseSSprite(SSprite *sprite);
879  void setSSpriteFrames(SSprite *sprite, int16 frameCount, byte **frameData, int16 frameRate);
880  void setSSpriteDrag(SSprite *sprite, int16 dragX, int16 dragY);
881  void setSSpriteAccel(SSprite *sprite, int16 accelX, int16 accelY);
882  void reverseSSpriteAccel(SSprite *sprite);
883  void addSSpriteAccel(SSprite *sprite, int16 dx, int16 dy);
884  void setSSpriteVelocity(SSprite *sprite, int16 vx, int16 vy);
885  void reverseSSpriteVelocity(SSprite *sprite);
886  void setSSpriteStart(SSprite *sprite, int16 startFrame, int16 x, int16 y);
887  void setSSpriteStop(SSprite *sprite, int16 stopFrame);
888  void setSSpritePath(SSprite *sprite, byte *pathData, int16 pathCount, SSpritePathCallback callback);
889  bool inSSprite(SSprite *sprite, int16 x, int16 y);
890  bool sSpriteCollide(SSprite *spriteA, SSprite *spriteB);
891  void setSSpriteCollision(SSprite *sprite, int16 *bounds);
892  bool sSpriteAlive(SSprite *sprite);
893  void getSSpriteLoc(SSprite *sprite, Common::Point *out);
894  void getSSpriteAccel(SSprite *sprite, int16 *out);
895  void getSSpriteVelocity(SSprite *sprite, int16 *out);
896  void getSSpriteDrag(SSprite *sprite, int16 *out);
897  void setSSpriteXLimit(SSprite *sprite, int16 high, int16 low);
898  void setSSpriteYLimit(SSprite *sprite, int16 high, int16 low);
899  void setSSpriteInfo(SSprite *sprite, int16 info);
900  int16 getSSpriteInfo(SSprite *sprite);
901  void freezeSSprite(SSprite *sprite);
902  void unfreezeSSprite(SSprite *sprite);
903 
904  int16 _spriteCollTempX = 0;
905  int16 _spriteCollTempY = 0;
906  int16 _spriteCollTempW = 0;
907  int16 _spriteCollTempH = 0;
908  int16 _spriteScreenX = 0;
909  int16 _spriteScreenY = 0;
910  int16 _spriteCollTempA[4] = { 0 };
911  int16 _spriteCollTempB[4] = { 0 };
912  int16 _spriteScreenAX = 0;
913  int16 _spriteScreenAY = 0;
914  int16 _spriteScreenBX = 0;
915  int16 _spriteScreenBY = 0;
916 
917  // --- MINIGAMES ---
918 
919  // --- FRED ---
920  int16 fredGame(int16 prevBooth);
921  bool initFred();
922  void cleanUpFred();
923  bool initFredLevel(int16 levelGroup, int16 palGroup);
924  void termFredLevel(int16 levelGroup, int16 palGroup);
925  void swapFredAnimEntry();
926  void swapFredAnimDesc();
927  void swapFredLevelDesc();
928  int16 playFred();
929  int16 helpFred();
930  void hiliteFredHelpObject(byte *entry, int16 highlight);
931  void helpAnimStep();
932  bool spawnBalloon();
933  int16 calcBalloonSpawnDelay();
934  int16 selectBalloonRow();
935  void setFredAnimMode(FredEntityState *state, int16 mode);
936  void renderFredScene();
937  void getFredSoundInfo(BOLTLib *lib, int16 memberId, SoundInfo *soundInfo);
938  void playFredSound(SoundInfo *oneShot, SoundInfo *loop);
939  void updateFredSound();
940 
941  static void resolveAllRefsCb();
942  static void swapFredAnimEntryCb();
943  static void swapFredAnimDescCb();
944  static void swapFredLevelDescCb();
945 
946  BOLTLib *_fredBoltLib = nullptr;
947  BOLTCallbacks _fredBoltCallbacks;
948 
949  static BOLTCallback _fredTypeLoadCallbacks[28];
950  static BOLTCallback _fredTypeFreeCallbacks[28];
951 
952  byte *_fredLevelPtr = nullptr;
953  byte *_fredBackground = nullptr;
954  byte *_fredBalloonString = nullptr;
955  byte *_fredPalette = nullptr;
956  byte *_fredFacingLeftRect = nullptr;
957  byte *_fredFacingRightRect = nullptr;
958  byte *_fredTurningRect = nullptr;
959  byte *_fredBalloonRect = nullptr;
960  byte *_fredHelpEntries = nullptr;
961  byte *_fredPlayButton = nullptr;
962  byte *_fredSprites[10] = { nullptr };
963  FredEntityState **_fredEntitiesTable = nullptr;
964 
965  byte *_fredRowBounds = nullptr;
966  byte *_fredShuffleTable = nullptr;
967  byte *_fredCycleRaw = nullptr;
968  byte *_fredBalloonSprite = nullptr;
969  byte *_fredPathMatrix = nullptr;
970  byte *_fredCurrentHelpObject = nullptr;
971  byte *_fredHoveredEntry = nullptr;
972 
973  SoundInfo _fredSounds[4];
974 
975  SoundInfo *_fredCurrentSound = nullptr;
976  SoundInfo *_fredLoopSound = nullptr;
977  SoundInfo *_fredPendingOneShot = nullptr;
978  SoundInfo *_fredPendingLoop = nullptr;
979 
980  FredEntityState _fredSprite;
981 
982  int16 _fredSaveData[3] = { 0, 0, 0 };
983  int16 _fredLevelIndex = 0;
984 
985  int16 _fredBalloonSpawnDelay = 0;
986  int16 _fredBalloonSearchIdx = 0;
987  uint32 _fredTimer = 0;
988  int16 _fredHelpStep = -1;
989  int16 _fredShowHelp = 1;
990 
991  XPCycleState _fredCycleSpecs[4];
992 
993  // --- GEORGE ---
994  int16 georgeGame(int16 prevBooth);
995  bool initGeorge();
996  void cleanUpGeorge();
997  bool initGeorgeLevel(int16 level, int16 variant);
998  void termGeorgeLevel(int16 level, int16 variant);
999  void swapGeorgeFrameArray();
1000  void swapGeorgeHelpEntry();
1001  void swapGeorgeThresholds();
1002  int16 playGeorge();
1003  int16 helpGeorge();
1004  void hiliteGeorgeHelpObject(byte *entry, int16 highlight);
1005  void advanceHelpAnimation();
1006  bool spawnSatellite();
1007  int16 getRandomSatelliteWait();
1008  int16 getRandomAsteroidRow();
1009  bool confirmAsteroidHitTest();
1010  bool spawnAsteroid();
1011  int16 getRandomAsteroidWait();
1012  int16 getAsteroidRow();
1013  void setGeorgeAnimMode(GeorgeEntityState *sat, int16 mode);
1014  void setSatelliteAnimMode(GeorgeEntityState *sat, int16 mode, int16 variant);
1015  void setAsteroidAnimMode(GeorgeEntityState *sat, int16 mode, int16 variant);
1016  void drawFlyingObjects();
1017  void getGeorgeSoundInfo(BOLTLib *boltLib, int16 member, SoundInfo *outInfo, byte priority);
1018  void playGeorgeSound(SoundInfo *newSound, SoundInfo *nextSound);
1019  void updateGeorgeSound();
1020 
1021  static void swapGeorgeFrameArrayCb();
1022  static void swapGeorgeHelpEntryCb();
1023  static void swapGeorgeThresholdsCb();
1024 
1025  BOLTLib *_georgeBoltLib = nullptr;
1026  BOLTCallbacks _georgeBoltCallbacks;
1027 
1028  static BOLTCallback _georgeTypeLoadCallbacks[28];
1029  static BOLTCallback _georgeTypeFreeCallbacks[28];
1030 
1031  byte *_georgePrevActiveHelpObject = nullptr;
1032  byte *_georgeActiveHelpObject = nullptr;
1033  int16 _georgeHelpStep = -1;
1034  int16 _georgeHelpActive = 1;
1035 
1036  GeorgeEntityState **_georgeEntityList = nullptr;
1037  int16 _georgeCarIdx = 0;
1038  int16 _georgeNumSatellites = 0;
1039  int16 _georgeFirstAsteroidIdx = 0;
1040  int16 _georgeTotalSatellites = 0;
1041  byte *_georgeCarPics[3] = { nullptr };
1042  byte *_georgeHelpObjects = nullptr;
1043  byte *_georgeHelpSequence = nullptr;
1044  uint32 _georgeHelpTimer = 0;
1045  byte *_georgeSatelliteShuffleTable = nullptr;
1046  byte *_georgeAsteroidShuffleTable = nullptr;
1047  int16 *_georgeSatelliteThresholds = nullptr;
1048  int16 *_georgeAsteroidThresholds = nullptr;
1049  byte *_georgeSatellitePaths = nullptr;
1050  byte *_georgeAsteroidPaths = nullptr;
1051  byte *_georgeCollisionRect = nullptr;
1052  byte *_georgeSatelliteCollisionRects = nullptr;
1053  byte *_georgeAsteroidCollisionRects = nullptr;
1054  byte *_georgeSatelliteGfx = nullptr;
1055  byte *_georgeAsteroidGfx = nullptr;
1056  int16 _georgeSatelliteWait = 0;
1057  int16 _georgeAsteroidWait = 0;
1058  int16 _georgeSatelliteSearchIdx = 0;
1059  int16 _georgeAsteroidSearchIdx = 0;
1060  int16 _georgeHitSearchIdx = 0;
1061  byte *_georgeBgPic = nullptr;
1062  byte *_georgePalette = nullptr;
1063  byte *_georgePalCycleRawData = nullptr;
1064  XPCycleState _georgePalCycleSpecs[4];
1065  int16 _georgeCollectedSatellitesNum = 0;
1066  SoundInfo _georgeSoundCarStartUp;
1067  SoundInfo _georgeSoundCarGoesAway;
1068  SoundInfo _georgeSoundCarLoopHi;
1069  SoundInfo _georgeSoundCarLoopLo;
1070  SoundInfo _georgeSoundCarTumble;
1071  SoundInfo **_georgeSatelliteSoundList = nullptr;
1072  byte _georgeSoundChannelCounter = 0;
1073  SoundInfo *_georgeSoundToPlay = nullptr;
1074  SoundInfo *_georgeSoundCurrent = nullptr;
1075  SoundInfo *_georgeSoundQueued = nullptr;
1076  SoundInfo *_georgeSoundNext = nullptr;
1077  int16 _georgeSaveData[3] = { 0 };
1078  int16 *_georgeThresholds = nullptr;
1079 
1080  // --- HUCK ---
1081  void playSoundMapHuck(int16 memberId);
1082  void waitSoundMapHuck();
1083  void setHuckColors(int16 which);
1084  void restoreHuckColors(int16 which);
1085  void startHuckShuffleTimer();
1086  void drawGift(int16 slot);
1087  void drawHuckGifts();
1088  void checkHuckLevelComplete();
1089  bool initHuckDisplay();
1090  bool loadHuckResources();
1091  void unloadHuckResources();
1092  bool initHuckLevel();
1093  bool resumeHuckLevel();
1094  bool initHuck();
1095  void huckToggleBlinking(int16 *state, int16 which);
1096  void huckUpdateHotSpots(int16 x, int16 y);
1097  int16 findGift(int16 x, int16 y);
1098  bool handleGiftSelect(int16 x, int16 y);
1099  void huckHandleActionButton(int16 x, int16 y);
1100  void giftSwap();
1101  void resolveHuckSelection();
1102  void handleEvent(int16 eventType, uint32 eventData);
1103  void playHuck();
1104  void cleanUpHuck();
1105  int16 huckGame(int16 prevBooth);
1106  void swapHuckWordArray();
1107  void swapHuckWords();
1108 
1109  static void swapHuckWordArrayCb();
1110  static void swapHuckWordsCb();
1111 
1112  BOLTLib *_huckBoltLib = nullptr;
1113  BOLTCallbacks _huckBoltCallbacks;
1114 
1115  static BOLTCallback _huckTypeLoadCallbacks[27];
1116  static BOLTCallback _huckTypeFreeCallbacks[27];
1117 
1118  int16 _huckSoundPlaying = 0;
1119  int16 _huckHotSpotCount = 0;
1120  int16 _huckActionState = 0;
1121  uint32 _huckScreensaverTimer = 0;
1122  uint32 _huckBlinkTimer = 0;
1123  int16 _huckScreensaverFlag = 0;
1124  int16 _huckBlinkFlag = 0;
1125  uint32 _huckShuffleTimer = 0;
1126  int16 _huckGlobal[30] = { 0 };
1127  HuckState _huckState;
1128  byte *_huckGiftPic = nullptr;
1129  byte *_huckBgPic = nullptr;
1130  int16 _huckGiftGroupId = 0;
1131  int16 _huckVariantGroupId = 0;
1132  byte *_huckBgDisplayPic = nullptr;
1133  int16 _huckScrollOffset = 0;
1134  int16 _huckPalRange[8] = { 0 };
1135  int16 _huckReturnBooth = 0;
1136  int16 _huckExitFlag = 0;
1137  int16 _huckCursorX = 0;
1138  int16 _huckCursorY = 0;
1139  byte _huckPalSave0[15] = { 0 };
1140  byte _huckPalHighlight0[15] = { 0 };
1141  byte _huckPalSave1[15] = { 0 };
1142  byte _huckPalHighlight1[15] = { 0 };
1143  XPPicDesc _huckScratchPic;
1144 
1145  // --- SCOOBY ---
1146  bool loadScoobyBaseAssets();
1147  void cleanUpScoobyBaseAssets();
1148  void displayPicClipHack(byte *pic, int16 offsetX, int16 offsetY, int16 *clipRect, int16 displayMode);
1149  void drawMovingWalls(int16 cellIdx, int16 direction, int16 picFrame, int16 bgFrame);
1150  void drawAllMovingWalls();
1151  void animateTransition(int16 memberIdx);
1152  void clearPictMSb(byte *pic);
1153  void initScoobyLevelGraphics();
1154  bool initScoobyLevelAssets();
1155  void cleanUpScoobyLevelGraphics();
1156  void setScoobySpriteDirection(int16 startMember);
1157  void playSoundMapScooby(int16 memberIdx);
1158  void playWallSound();
1159  void animateWalls();
1160  void decideDirection();
1161  void updateScoobySound();
1162  void setScoobySound(int16 mode);
1163  void updateScoobyLocation();
1164  void updateScoobyWalls();
1165  void updateScoobyDirection(int16 inputDir);
1166  void updateScoobyTransition();
1167  bool initScoobyLevel();
1168  bool resumeScoobyLevel();
1169  bool initScooby();
1170  void cleanUpScooby();
1171  int16 helpScooby();
1172  void hiliteScoobyHelpObject(byte *entry, int16 highlight);
1173  int16 xpDirToBOLTDir(uint32 xpDir);
1174  int16 playScooby();
1175  int16 scoobyGame(int16 prevBooth);
1176  void swapScoobyHelpEntry();
1177  void swapScoobyWordArray();
1178 
1179  static void swapScoobyHelpEntryCb();
1180  static void swapScoobyWordArrayCb();
1181 
1182  BOLTLib *_scoobyBoltLib = nullptr;
1183  BOLTCallbacks _scoobyBoltCallbacks;
1184 
1185  static BOLTCallback _scoobyTypeLoadCallbacks[28];
1186  static BOLTCallback _scoobyTypeFreeCallbacks[28];
1187 
1188  int16 _scoobySoundMode = 0;
1189  int16 _scoobySoundPlaying = 0;
1190  int16 _scoobyShowHelp = 1;
1191 
1192  int16 _scoobyLastInputDir = 0;
1193  int16 _scoobyTransitionFrom = 0;
1194  int16 _scoobyTransitionTarget = 0;
1195  int16 _scoobyTransitionVelX = 0;
1196  int16 _scoobyTransitionVelY = 0;
1197  XPPicDesc _scoobyTempPic;
1198  byte _scoobyGlobalSaveData[0x3C] = { 0 };
1199  ScoobyState _scoobyGameState;
1200  SSprite _scoobySprite;
1201  byte *_scoobyBaseData = nullptr;
1202  byte *_scoobyBgPic = nullptr;
1203  byte *_scoobyWallPicsA[4] = { nullptr };
1204  byte *_scoobyWallPicsB[5] = { nullptr };
1205  ScoobyRect _scoobyCellBounds[25];
1206  Common::Point _scoobyLevelStartXY[25];
1207  byte *_scoobyLevelData = nullptr;
1208  int16 _scoobySelectedGraphicsGroup = 0;
1209  int16 _scoobyDifficulty = 0;
1210  int16 _scoobyLevelCount = 0;
1211  int16 _scoobyMoveRequested = 0;
1212  int16 _scoobyTransitioning = 0;
1213  int16 _scoobyDesiredDir = 0;
1214  int16 _scoobyInputHoldCount = 0;
1215  int16 _scoobyWallAnimating = 0;
1216  int16 _scoobyWallAnimStep = 0;
1217  int16 _scoobyWallsToOpen = 0;
1218  int16 _scoobyWallsToClose = 0;
1219 
1220  // --- TOPCAT ---
1221  int16 topCatGame(int16 prevBooth);
1222  bool initTopCat();
1223  void cleanUpTopCat();
1224  int16 playTopCat();
1225  int16 handleActionButton(int16 *result);
1226  void queueAnim(int16 animType, int16 param);
1227  bool maintainAnim(int16 soundEvent);
1228  void maintainIdleSound(int16 decrement);
1229  bool startNextAnim(int16 *playAnswerAnim);
1230  void setAnimType(int16 newType);
1231  void highlightObject(byte *entry, int16 highlight);
1232  bool setupNextQuestion();
1233  void adjustColors(byte *pic, int8 shift);
1234  void shuffleTopCatQuestions();
1235  void shuffleTopCatPermutations();
1236  void getTopCatSoundInfo(BOLTLib *lib, int16 memberId, SoundInfo *soundInfo);
1237  void setScoreLights(int16 litMask);
1238  void swapTopCatHelpEntry();
1239 
1240  static void swapTopCatHelpEntryCb();
1241 
1242  RTFResource *_topCatRtfHandle = nullptr;
1243  RTFResource *_topCatAvHandle = nullptr;
1244  BOLTLib *_topCatBoltLib = nullptr;
1245  BOLTCallbacks _topCatBoltCallbacks;
1246 
1247  static BOLTCallback _topCatTypeLoadCallbacks[26];
1248  static BOLTCallback _topCatTypeFreeCallbacks[26];
1249 
1250  byte *_topCatBackgroundPalette = nullptr;
1251  byte *_topCatBackground = nullptr;
1252  byte *_topCatBackgroundAnimationPalette = nullptr;
1253  byte *_topCatGraphicsAssets = nullptr;
1254 
1255  int16 _topCatBackgroundAnimFrame = 0;
1256  int16 _topCatMaxBackgroundAnimFrames = 0;
1257  int16 _topCatCurrentAnimType = 0;
1258  int16 _topCatAnimStateMachineStep = 0;
1259  int16 _topCatAnimQueueSize = 0;
1260  int16 _topCatQueuedSoundFrames = 0;
1261  byte *_topCatButtonsPalette = nullptr;
1262  byte *_topCatBlinkEntries = nullptr;
1263  byte *_topCatLightsPalette = nullptr;
1264  int16 *_topCatBlinkSeqPtr = nullptr;
1265  byte *_topCatSelectedChoiceOverlayGfx = nullptr;
1266  byte *_topCatCycleData = nullptr;
1267  XPCycleState _topCatCycleSpecs[4];
1268  byte *_topCatShuffledQuestions = nullptr;
1269  byte *_topCatShuffledAnswers = nullptr;
1270  byte *_topCatAnswersPermutations = nullptr;
1271  byte *_topCatAnswers = nullptr;
1272  byte *_topCatAnswersScreenPositions = nullptr;
1273  int16 _topCatSavedScore = 0;
1274  int16 _topCatSaveHistory = 0;
1275  int16 _topCatScore = 0;
1276  int16 _topCatShuffledQuestionsArrayIdx = 0;
1277  uint32 _topCatBlinkTimer = 0;
1278  SoundInfo _topCatSoundInfo;
1279  byte _topCatSavedShuffledQuestions[60] = { 0 };
1280  byte _topCatSavedShuffledAnswers[60] = { 0 };
1281  byte _topCatSavedAnswersPermutations[60 * 3] = { 0 };
1282  byte _topCatSaveBuffer[302] = { 0 };
1283  byte *_topCatHoveredEntry = nullptr;
1284  byte *_topCatHelpButton = nullptr;
1285  byte *_topCatBackButton = nullptr;
1286  byte *_topCatBlinkEntry = nullptr;
1287  int16 _topCatCycleStep = 0;
1288  int16 _topCatDrawnQuestionId = 0;
1289  int16 _topCatCurrentAnswerIdx = 0;
1290  XPCycleState _topCatChoiceCycleState[4];
1291  TopCatAnim _topCatAnimQueue[3];
1292  int16 _topCatCorrectAnimIdx = 0;
1293  int16 _topCatWrongAnimIdx = 0;
1294  int16 _topCatShouldPlayAnswerAnim = 0;
1295  int16 _topCatMaintainSoundFlag = 0;
1296  int16 _topCatPermTableA[3] = { 0, 1, 2 };
1297  int16 _topCatPermTableB[3] = { 0, 1, 2 };
1298  int16 _topCatBlinkSeq0[5] = { 0x01, 0x00, 0x01, 0x00, 0x01 };
1299  int16 _topCatBlinkSeq1[5] = { 0x03, 0x01, 0x03, 0x01, 0x03 };
1300  int16 _topCatBlinkSeq2[5] = { 0x07, 0x03, 0x07, 0x03, 0x07 };
1301  int16 _topCatBlinkSeq3[5] = { 0x0F, 0x07, 0x0F, 0x07, 0x0F };
1302  int16 _topCatBlinkSeq4[5] = { 0x1F, 0x0F, 0x1F, 0x0F, 0x1F };
1303  int16 _topCatBlinkSeq5[5] = { 0x3F, 0x1F, 0x3F, 0x1F, 0x3F };
1304  int16 _topCatBlinkSeq6[25] = {
1305  0x09, 0x12, 0x24, 0x09, 0x12, 0x24,
1306  0x09, 0x12, 0x24, 0x09, 0x12, 0x24,
1307  0x09, 0x12, 0x24, 0x09, 0x12, 0x24,
1308  0x09, 0x12, 0x24, 0x09, 0x12, 0x24,
1309  0x3F
1310  };
1311 
1312  int16 *_topCatBlinkSeqTable[7] = {
1313  _topCatBlinkSeq0, _topCatBlinkSeq1, _topCatBlinkSeq2,
1314  _topCatBlinkSeq3, _topCatBlinkSeq4, _topCatBlinkSeq5,
1315  _topCatBlinkSeq6
1316  };
1317 
1318  // --- YOGI ---
1319  void playSoundMapYogi(int16 memberId);
1320  void waitSoundMapYogi();
1321  void stopSoundYogi();
1322  void setYogiColors(int16 which);
1323  void restoreYogiColors(int16 which);
1324  void drawBasket(int16 slot, byte *basketSprite);
1325  void drawAllBaskets();
1326  void handleYogiMatch();
1327  bool loadYogiBgPic();
1328  void unloadYogiBgPic();
1329  void drawYogiLevel();
1330  bool loadYogiLevel();
1331  void unloadYogiResources();
1332  bool initYogiLevel();
1333  bool resumeYogiLevel();
1334  bool initYogi();
1335  void yogiToggleBlinking(int16 which, int16 *state);
1336  void yogiUpdateHotSpots(int16 x, int16 y);
1337  int16 findBasket(int16 x, int16 y);
1338  void resolveYogiSelection();
1339  bool handleBasketSelect(int16 x, int16 y);
1340  void yogiHandleActionButton(int16 x, int16 y);
1341  void handleYogiEvent(int16 eventType, uint32 eventData);
1342  void playYogi();
1343  void cleanUpYogi();
1344  int16 yogiGame(int16 prevBooth);
1345 
1346  void swapYogiAllWords();
1347  void swapYogiFirstWord();
1348 
1349  static void swapYogiAllWordsCb();
1350  static void swapYogiFirstWordCb();
1351 
1352  BOLTLib *_yogiBoltLib = nullptr;
1353  BOLTCallbacks _yogiBoltCallbacks;
1354 
1355  static BOLTCallback _yogiTypeLoadCallbacks[27];
1356  static BOLTCallback _yogiTypeFreeCallbacks[27];
1357 
1358  int16 _yogiSoundPlaying = 0;
1359  int16 _yogiSoundActive = 0;
1360  int16 _yogiHotSpotCount = 0;
1361  int16 _yogiAnimActive = 0;
1362  uint32 _yogiBlinkTimer1 = 0;
1363  uint32 _yogiBlinkTimer2 = 0;
1364  int16 _yogiBlinkState1 = 0;
1365  int16 _yogiBlinkState2 = 0;
1366  int16 _yogiGlobal[0xA0] = { 0 };
1367  YogiState _yogiState;
1368  byte *_yogiBasketPic = nullptr;
1369  int16 _yogiLevelGroupId = 0;
1370  byte *_yogiBgPic = nullptr;
1371  byte *_yogiNormalSprite = nullptr;
1372  byte *_yogiHlSprite = nullptr;
1373  byte *_yogiAnimSprite = nullptr;
1374  int16 _yogiSpriteStride = 0;
1375  int16 _yogiSpriteHeight = 0;
1376  int16 _yogiPalRange[8] = { 0 };
1377  int16 _yogiReturnBooth = 0;
1378  int16 _yogiExitFlag = 0;
1379  int16 _yogiLevelId = 0;
1380  int16 _yogiCursorX = 0;
1381  int16 _yogiCursorY = 0;
1382  byte _yogiPalSave0[15] = { 0 };
1383  byte _yogiPalHighlight0[15] = { 0 };
1384  byte _yogiPalSave1[15] = { 0 };
1385  byte _yogiPalHighlight1[15] = { 0 };
1386  XPPicDesc _yogiScratchBuf;
1387 };
1388 
1389 extern BoltEngine *g_engine;
1390 #define SHOULD_QUIT ::Bolt::g_engine->shouldQuit()
1391 
1392 } // End of namespace Bolt
1393 
1394 #endif // BOLT_H
Definition: bolt.h:40
Definition: xplib.h:52
Definition: str.h:59
EngineFeature
Definition: engine.h:258
Definition: bolt.h:483
bool canLoadGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: bolt.h:575
Definition: error.h:81
Definition: advancedDetector.h:164
Definition: bolt.h:97
Definition: bolt.h:157
Definition: random.h:44
bool canSaveGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: bolt.h:578
Definition: bolt.h:176
Definition: bolt.h:301
Definition: bolt.h:549
Definition: rect.h:524
Definition: xplib.h:68
Definition: bolt.h:233
Definition: bolt.h:58
Definition: bolt.h:119
Definition: bolt.h:515
Engine * g_engine
Definition: bolt.h:316
Definition: bolt.h:79
Definition: bolt.h:350
Definition: ustr.h:57
Definition: file.h:47
Definition: bolt.h:382
Definition: bolt.h:424
Definition: bolt.h:499
Definition: rect.h:144
Definition: xplib.h:153
bool hasFeature(EngineFeature f) const override
Definition: bolt.h:570
Definition: bolt.h:65
Definition: system.h:164
Definition: engine.h:144
Definition: bolt.h:50
Definition: bolt.h:202