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 struct BOLTHeader {
57  byte header[11];
58  byte groupCount;
59  uint32 groupDirOffset;
60 
61  BOLTHeader() {
62  memset(header, 0, sizeof(header));
63  groupCount = 0;
64  groupDirOffset = 0;
65  }
66 } BOLTHeader;
67 
68 typedef void (*BOLTCallback)(void);
69 
70 typedef struct BOLTCallbacks {
71  BOLTCallback *typeLoadCallbacks;
72  BOLTCallback *typeFreeCallbacks;
73  BOLTCallback *memberLoadCallbacks;
74  BOLTCallback *memberFreeCallbacks;
75  BOLTCallback *groupLoadCallbacks;
76  BOLTCallback *groupFreeCallbacks;
77 
78  BOLTCallbacks() {
79  typeLoadCallbacks = nullptr;
80  typeFreeCallbacks = nullptr;
81  memberLoadCallbacks = nullptr;
82  memberFreeCallbacks = nullptr;
83  groupLoadCallbacks = nullptr;
84  groupFreeCallbacks = nullptr;
85  }
87 
88 typedef struct BOLTMemberEntry {
89  byte flags;
90  byte preLoadCbIndex;
91  byte preFreeCbIndex;
92  byte typeCbIndex;
93  uint32 decompSize;
94  uint32 fileOffset;
95  uint32 dataPtrPlaceholder;
96  byte *dataPtr;
97 
98  BOLTMemberEntry() {
99  flags = 0;
100  preLoadCbIndex = 0;
101  preFreeCbIndex = 0;
102  typeCbIndex = 0;
103  decompSize = 0;
104  fileOffset = 0;
105  dataPtrPlaceholder = 0;
106  dataPtr = nullptr;
107  }
109 
110 typedef struct BOLTGroupEntry {
111  byte flags;
112  byte loadCbIndex;
113  byte freeCbIndex;
114  byte memberCount;
115  uint32 memberDirOffset;
116  uint32 memberDataOffset;
117  uint32 groupDataPtrPlaceholder;
118  byte *memberData;
119  BOLTMemberEntry *members;
120 
121  BOLTGroupEntry() {
122  flags = 0;
123  loadCbIndex = 0;
124  freeCbIndex = 0;
125  memberCount = 0;
126  memberDirOffset = 0;
127  memberDataOffset = 0;
128  groupDataPtrPlaceholder = 0;
129  memberData = nullptr;
130  members = nullptr;
131  }
132 
133  ~BOLTGroupEntry() {
134  free(memberData);
135  memberData = nullptr;
136 
137  delete[] members;
138  members = nullptr;
139  }
140 
141  void initMembers(int numMembers) {
142  int actualNumber = numMembers == 0 ? 256 : numMembers;
143  members = new BOLTMemberEntry[actualNumber];
144  }
145 
147 
148 typedef struct BOLTLib {
149  int16 refCount;
150  int16 groupCount;
151  Common::File *fileHandle;
152  BOLTCallbacks callbacks;
153  BOLTGroupEntry *groups;
154 
155  BOLTLib(int inGroupCount) {
156  refCount = 0;
157  groupCount = 0;
158  fileHandle = nullptr;
159  groups = new BOLTGroupEntry[inGroupCount];
160  }
161 
162  ~BOLTLib() {
163  delete[] groups;
164  }
165 } BOLTLib;
166 
167 typedef struct RTFResource {
168  Common::File *fileHandle;
169  uint32 *indexTablePtr;
170  int16 entryCount;
171  byte *indexTableRawData;
172  uint32 *indexTable;
173 
174  RTFResource() {
175  fileHandle = nullptr;
176  indexTablePtr = nullptr;
177  entryCount = 0;
178  indexTableRawData = nullptr;
179  indexTable = nullptr;
180  }
181 
182  ~RTFResource() {
183  if (indexTable)
184  delete[] indexTable;
185  }
186 
187  void reserveTableSize(int numElements) {
188  indexTable = new uint32[numElements];
189  }
190 } RTFResource;
191 
192 struct RTFPacket;
193 typedef struct RTFPacket {
194  uint32 tag;
195  uint32 allocSize;
196  uint32 dataSize;
197  byte *dataPtr;
198  int16 skipCount;
199  int16 frameRate;
200  int16 duration;
201  int16 timestamp;
202  RTFPacket *next;
203  byte *ringBufPtr;
204 
205  RTFPacket() {
206  tag = 0;
207  allocSize = 0;
208  dataSize = 0;
209  dataPtr = nullptr;
210  skipCount = 0;
211  frameRate = 0;
212  duration = 0;
213  timestamp = 0;
214  next = nullptr;
215  ringBufPtr = nullptr;
216  }
217 } RTFPacket;
218 
219 struct SSprite;
220 
221 typedef void (*SSpriteUpdateFunc)(void);
222 typedef void (*SSpritePathCallback)(SSprite *);
223 
224 typedef struct SSprite {
225  int16 flags;
226  int16 x;
227  int16 y;
228  int16 frameCount;
229  int16 currentFrame;
230  byte **frameData;
231  SSpriteUpdateFunc updateFunc;
232  SSpritePathCallback pathCallback;
233  int16 frameTimer;
234  int16 frameRate;
235  int16 startFrame;
236  int16 stopFrame;
237  int16 velocityX;
238  int16 velocityY;
239  int16 xLimitLow;
240  int16 xLimitHigh;
241  int16 yLimitLow;
242  int16 yLimitHigh;
243  int16 accelX;
244  int16 accelY;
245  int16 dragX;
246  int16 dragY;
247  byte *pathData;
248  int16 pathOffset;
249  int16 pathLength;
250  int16 collX;
251  int16 collY;
252  int16 collW;
253  int16 collH;
254  int16 userInfo;
255 
256  SSprite() {
257  flags = 0;
258  x = 0;
259  y = 0;
260  frameCount = 0;
261  currentFrame = 0;
262  frameData = nullptr;
263  updateFunc = nullptr;
264  pathCallback = nullptr;
265  frameTimer = 0;
266  frameRate = 0;
267  startFrame = 0;
268  stopFrame = 0;
269  velocityX = 0;
270  velocityY = 0;
271  xLimitLow = 0;
272  xLimitHigh = 0;
273  yLimitLow = 0;
274  yLimitHigh = 0;
275  accelX = 0;
276  accelY = 0;
277  dragX = 0;
278  dragY = 0;
279  pathData = nullptr;
280  pathOffset = 0;
281  pathLength = 0;
282  collX = 0;
283  collY = 0;
284  collW = 0;
285  collH = 0;
286  userInfo = 0;
287  }
288 } SSprite;
289 
290 // FRED GAME
291 
292 typedef struct SoundInfo {
293  byte *data;
294  uint32 size;
295  byte priority;
296  byte channel;
297 
298  SoundInfo() {
299  data = nullptr;
300  size = 0;
301  priority = 0;
302  channel = 0;
303  }
304 } SoundInfo;
305 
306 class BoltEngine : public Engine {
307 friend class XpLib;
308 
309 private:
310  const ADGameDescription *_gameDescription;
311  Common::RandomSource _randomSource;
312 protected:
313  // BoltEngine can only be constructed by one of the Carnival, Merlin or Crete engines.
314  BoltEngine(OSystem *syst, const ADGameDescription *gameDesc);
315 
316  // Engine APIs
317  Common::Error run() override;
318 
319 public:
320  ~BoltEngine() override;
321 
322  uint32 getFeatures() const;
323 
327  Common::String getGameId() const;
328 
329  bool hasFeature(EngineFeature f) const override {
330  return (f == kSupportsReturnToLauncher);
331  };
332 
333  // This engine doesn't save anything!
334  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
335  return false;
336  }
337  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
338  return false;
339  }
340 
341 protected:
342  DisplaySpecs _displaySpecs[2] = {
343  {0, 384, 240},
344  {1, 320, 200}
345  };
346 
347  XpLib *_xp = nullptr;
348  bool _extendedViewport = false;
349  bool _isDemo = false;
350 
351  // xpMain
352  virtual void boltMain() = 0;
353  void setCursorPict(byte *sprite);
354 
355  // Utils
356  void displayColors(byte *palette, int16 page, int16 flags);
357  byte getPixel(byte *sprite, int16 localX, int16 localY);
358  void boltPict2Pict(XPPicDesc *dest, byte *boltSprite);
359  void displayPic(byte *boltSprite, int16 xOff, int16 yOff, int16 page);
360  bool pointInRect(Common::Rect *rect, int16 x, int16 y);
361  const char *assetPath(const char *fileName);
362  void boltCycleToXPCycle(byte *srcData, XPCycleState *cycleDesc);
363  void unpackColors(int16 count, byte *packedColors);
364  bool intersectRect(const Common::Rect *a, const Common::Rect *b, Common::Rect *out);
365 
366  // Swap
367  void swapPicHeader();
368  void swapAndResolvePicDesc();
369  void swapFirstWord();
370  void swapFirstTwoWords();
371  void swapFirstFourWords();
372  void swapSpriteHeader();
373  void freeSpriteCleanUp();
374 
375  // Resource
376  bool libRead(Common::File *fileHandle, uint32 offset, byte *dest, uint32 size);
377  void decompress(byte *dest, uint32 decompSize, byte *src);
378  void resolveIt(uint32 *ref);
379  void resolvePendingFixups();
380  void resolveFunction(uint32 *ref);
381  void resolveAllRefs();
382  byte *getResolvedPtr(byte *data, int offset);
383  bool openBOLTLib(BOLTLib **outLib, BOLTCallbacks *outIdx, const char *fileName);
384  bool closeBOLTLib(BOLTLib **lib);
385  bool attemptFreeIndex(BOLTLib *lib, int16 groupId);
386  bool loadGroupDirectory();
387  bool getBOLTGroup(BOLTLib *lib, int16 groupId, int16 flags);
388  void freeBOLTGroup(BOLTLib *lib, int16 groupId, int16 flags);
389  byte *getBOLTMember(BOLTLib *lib, int16 resId);
390  bool freeBOLTMember(BOLTLib *lib, int16 resId);
391  Common::Rect memberToRect(byte *data);
392  byte *memberAddr(BOLTLib *lib, int16 resId);
393  byte *memberAddrOffset(BOLTLib *lib, uint32 resIdAndOffset);
394  uint32 memberSize(BOLTLib *lib, int16 resId);
395  byte *groupAddr(BOLTLib *lib, int16 groupId);
396  bool allocResourceIndex();
397  void freeResourceIndex();
398  void swapAllWords();
399  void swapAllLongs();
400 
401  BOLTLib *_boothsBoltLib = nullptr;
402  BOLTCallbacks _boothsBoltCallbacks;
403 
404  static BOLTCallback _defaultTypeLoadCallbacks[25];
405  static BOLTCallback _defaultTypeFreeCallbacks[25];
406  static BOLTCallback _defaultMemberLoadCallbacks[25];
407  static BOLTCallback _defaultMemberFreeCallbacks[25];
408  static BOLTCallback _defaultGroupLoadCallbacks[25];
409  static BOLTCallback _defaultGroupFreeCallbacks[25];
410 
411  static void noOpCb();
412 
413  static void swapAllWordsCb();
414  static void swapAllLongsCb();
415  static void swapPicHeaderCb();
416  static void swapAndResolvePicDescCb();
417  static void swapFirstWordCb();
418  static void swapFirstTwoWordsCb();
419  static void swapFirstFourWordsCb();
420  static void swapSpriteHeaderCb();
421  static void freeSpriteCleanUpCb();
422 
423  virtual void initCallbacks() = 0;
424 
425  int16 _resourceIndexCount = 1000;
426  uint32 **_resourceIndex = nullptr;
427  Common::Array<byte *> _resolvedPtrs;
428  Common::File *_cachedFileHandle = nullptr;
429  uint32 _cachedFilePos = 0xFFFFFFFF;
430  BOLTLib *_boltCurrentLib = nullptr;
431  BOLTHeader _boltFileHeader;
432  BOLTGroupEntry *_boltCurrentGroupEntry = nullptr;
433  int16 _boltLoadDepth = 0;
434  byte *_boltRawMemberData = nullptr;
435  BOLTMemberEntry *_boltCurrentMemberEntry = nullptr;
436  int16 _pendingFixupCount = 0;
437 
438  // Game state
439  bool initVRam(int16 poolSize);
440  void freeVRam();
441  bool vLoad(void *dest, const char *name);
442  bool vSave(void *src, uint16 srcSize, const char *name);
443  bool vDelete(const char *name);
444  byte *dataAddress(int16 recordOffset);
445  uint16 dataSize(int16 recordOffset);
446  bool findRecord(const char *name, int16 *outOffset);
447 
448  int32 _vramRecordCount = 0;
449  int32 _vramUsedBytes = 0;
450  byte *_allocatedMemPool = nullptr;
451  uint32 _allocatedMemPoolSize = 0;
452  int32 _curErrorCode = 0;
453 
454  // RTF
455  RTFResource *openRTF(const char *fileName);
456  void closeRTF(RTFResource *rtf);
457  bool playRTF(RTFResource *rtfFile, int16 animIndex, byte *ringBuffer, int32 bufferSize);
458  bool fillRTFBuffer();
459  void flushRTFSoundQueue();
460  bool maintainRTF(int16 mode, RTFPacket **outFrameData);
461  bool isRTFPlaying();
462  bool killRTF(uint32 *outFilePos);
463  bool readPacket();
464  void preProcessPacket(RTFPacket *packet);
465  void queuePacket(RTFPacket *packet);
466  RTFPacket *deQueuePacket();
467  RTFPacket *allocPacket(uint32 dataSize);
468  void freePacket(RTFPacket *packet);
469  void resetPlaybackState();
470  void setAVBufferSize(uint32 bufSize);
471 
472  RTFResource *_rtfHandle = nullptr;
473  Common::File *_rtfFileHandle = nullptr;
474  uint32 _rtfChunkRemaining = 0;
475  bool _rtfMidChunk = false;
476  RTFPacket *_rtfCurrentPacket = nullptr;
477  byte *_ringBufBase = nullptr;
478  byte *_ringBufWritePtr = nullptr;
479  uint32 _ringBufSize = 0;
480  uint32 _ringBufFreeSpace = 0;
481  uint32 _ringBufLowWater = 0;
482  uint32 _ringBufHighWater = 0;
483  uint32 _ringBufUsed = 0;
484  bool _rtfSoundActive = false;
485  int16 _rtfPlaybackTime = 0;
486  int16 _rtfCumulativeTime = 0;
487  RTFPacket *_rtfPendingFrame = nullptr;
488  RTFPacket *_rtfSoundQueueHead = nullptr;
489  RTFPacket *_rtfSoundPlayHead = nullptr;
490  RTFPacket *_rtfChunkListTail = nullptr;
491  RTFPacket *_rtfChunkListHead = nullptr;
492  int16 _rtfChunkCount = 0;
493  int16 _rtfQueuedSoundCount = 0;
494  int16 _rtfSoundTiming = 0;
495  uint32 _rtfAnimStartOffset = 0;
496  bool _rtfNeedInitialFill = false;
497  uint32 _rtfChunkTag = 0;
498  uint32 _rtfChunkSize = 0;
499 
500  // AV
501  bool prepareAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
502  bool maintainAV(int16 mode);
503  void stopAV();
504  bool playAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
505  void processPacket(RTFPacket *packet);
506  void processRL7(RTFPacket *packet);
507  void processPLTE(RTFPacket *packet);
508  bool initAV(RTFResource *rtfHandle, int16 animIndex, int16 width, int16 height, int16 xOff, int16 yOff);
509  void cleanUpAV();
510 
511  byte *_avRingBuffer = nullptr;
512  uint32 _avTargetBufSize = 0x0FA000;
513  int16 _avSkipLevel = 0;
514  byte *_avFrontPalette = nullptr;
515  byte *_avBackPalette = nullptr;
516  uint32 _avSavedInactivityTimer = 0;
517  uint32 _avSavedScreenSaverTimer = 0;
518  int16 _avFrameAccum = 0;
519  int16 _avDisplayX = 0;
520  int16 _avDisplayY = 0;
521 
522  XPPicDesc _avFrontBufDesc;
523  XPPicDesc _avBackBufDesc;
524 
525  // Anim
526  bool startAnimation(RTFResource *rtf, int16 animIndex);
527  void stopAnimation();
528  bool maintainAudioPlay(int16 mode);
529  bool initAnim(RTFResource *rtf, int16 animIndex);
530  void cleanUpAnim();
531 
532  int16 _animPrevInactivityTimer = 0;
533  byte *_animRingBuffer = nullptr;
534  Common::File *_animFileHandle = nullptr;
535 
536  // SSprite
537  void setUpSSprite(SSprite *sprite, int16 frameCount, byte **frameData, int16 frameRate, int16 velocityX, int16 velocityY);
538  void animateSSprite(SSprite *sprite, int16 page);
539  void displaySSprite(SSprite *sprite, int16 x, int16 y);
540  void eraseSSprite(SSprite *sprite);
541  void setSSpriteFrames(SSprite *sprite, int16 frameCount, byte **frameData, int16 frameRate);
542  void setSSpriteDrag(SSprite *sprite, int16 dragX, int16 dragY);
543  void setSSpriteAccel(SSprite *sprite, int16 accelX, int16 accelY);
544  void reverseSSpriteAccel(SSprite *sprite);
545  void addSSpriteAccel(SSprite *sprite, int16 dx, int16 dy);
546  void setSSpriteVelocity(SSprite *sprite, int16 vx, int16 vy);
547  void reverseSSpriteVelocity(SSprite *sprite);
548  void setSSpriteStart(SSprite *sprite, int16 startFrame, int16 x, int16 y);
549  void setSSpriteStop(SSprite *sprite, int16 stopFrame);
550  void setSSpritePath(SSprite *sprite, byte *pathData, int16 pathCount, SSpritePathCallback callback);
551  bool inSSprite(SSprite *sprite, int16 x, int16 y);
552  bool sSpriteCollide(SSprite *spriteA, SSprite *spriteB);
553  void setSSpriteCollision(SSprite *sprite, int16 *bounds);
554  bool sSpriteAlive(SSprite *sprite);
555  void getSSpriteLoc(SSprite *sprite, Common::Point *out);
556  void getSSpriteAccel(SSprite *sprite, int16 *out);
557  void getSSpriteVelocity(SSprite *sprite, int16 *out);
558  void getSSpriteDrag(SSprite *sprite, int16 *out);
559  void setSSpriteXLimit(SSprite *sprite, int16 high, int16 low);
560  void setSSpriteYLimit(SSprite *sprite, int16 high, int16 low);
561  void setSSpriteInfo(SSprite *sprite, int16 info);
562  int16 getSSpriteInfo(SSprite *sprite);
563  void freezeSSprite(SSprite *sprite);
564  void unfreezeSSprite(SSprite *sprite);
565 
566  int16 _spriteCollTempX = 0;
567  int16 _spriteCollTempY = 0;
568  int16 _spriteCollTempW = 0;
569  int16 _spriteCollTempH = 0;
570  int16 _spriteScreenX = 0;
571  int16 _spriteScreenY = 0;
572  int16 _spriteCollTempA[4] = { 0 };
573  int16 _spriteCollTempB[4] = { 0 };
574  int16 _spriteScreenAX = 0;
575  int16 _spriteScreenAY = 0;
576  int16 _spriteScreenBX = 0;
577  int16 _spriteScreenBY = 0;
578 };
579 
580 extern BoltEngine *g_engine;
581 #define SHOULD_QUIT ::Bolt::g_engine->shouldQuit()
582 
583 } // End of namespace Bolt
584 
585 #endif // BOLT_H
Definition: bolt.h:40
Definition: xplib.h:52
Definition: str.h:59
EngineFeature
Definition: engine.h:258
bool canLoadGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: bolt.h:334
Definition: error.h:81
Definition: advancedDetector.h:164
Definition: bolt.h:88
Definition: bolt.h:148
Definition: random.h:44
bool canSaveGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: bolt.h:337
Definition: bolt.h:167
Definition: bolt.h:292
Definition: bolt.h:306
Definition: rect.h:524
Definition: xplib.h:68
Definition: bolt.h:224
Definition: bolt.h:110
Engine * g_engine
Definition: bolt.h:70
Definition: ustr.h:57
Definition: file.h:47
Definition: rect.h:144
Definition: xplib.h:153
bool hasFeature(EngineFeature f) const override
Definition: bolt.h:329
Definition: bolt.h:56
Definition: system.h:165
Definition: engine.h:144
Definition: bolt.h:50
Definition: bolt.h:193