ScummVM API documentation
agi.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 AGI_AGI_H
23 #define AGI_AGI_H
24 
25 #include "common/scummsys.h"
26 #include "common/error.h"
27 #include "common/util.h"
28 #include "common/file.h"
29 #include "common/keyboard.h"
30 #include "common/rect.h"
31 #include "common/rendermode.h"
32 #include "common/stack.h"
33 #include "common/str.h"
34 #include "common/system.h"
35 
36 #include "engines/engine.h"
37 
38 #include "gui/debugger.h"
39 
40 // AGI resources
41 #include "agi/console.h"
42 #include "agi/view.h"
43 #include "agi/picture.h"
44 #include "agi/logic.h"
45 #include "agi/sound.h"
46 
47 namespace Common {
48 class RandomSource;
49 }
50 
63 namespace Agi {
64 
65 #define TITLE "AGI engine"
66 
67 #define DIR_ "dir"
68 #define LOGDIR "logdir"
69 #define PICDIR "picdir"
70 #define VIEWDIR "viewdir"
71 #define SNDDIR "snddir"
72 #define OBJECTS "object"
73 #define WORDS "words.tok"
74 
75 #define MAX_DIRECTORY_ENTRIES 256
76 #define MAX_CONTROLLERS 256
77 #define MAX_VARS 256
78 #define MAX_FLAGS (256 >> 3)
79 #define SCREENOBJECTS_MAX 255 // KQ3 uses o255!
80 #define SCREENOBJECTS_EGO_ENTRY 0 // first entry is ego
81 #define MAX_WORDS 20
82 #define MAX_STRINGS 24 // MAX_STRINGS + 1 used for get.num
83 #define MAX_STRINGLEN 40
84 #define MAX_CONTROLLER_KEYMAPPINGS 39
85 
86 #define SAVEDGAME_DESCRIPTION_LEN 30
87 
88 #define _EMPTY 0xfffff
89 #define EGO_OWNED 0xff
90 #define EGO_OWNED_V1 0xf9
91 
92 #define CRYPT_KEY_SIERRA "Avis Durgan"
93 #define CRYPT_KEY_AGDS "Alex Simkin"
94 
95 #define ADD_PIC 1
96 #define ADD_VIEW 2
97 
98 #define CMD_BSIZE 12
99 
100 enum AgiGameType {
101  GType_PreAGI = 0,
102  GType_V1 = 1,
103  GType_V2 = 2,
104  GType_V3 = 3,
105  GType_A2 = 4
106 };
107 
108 enum AgiGameFeatures {
109  GF_AGIMOUSE = (1 << 0), // marks games created with AGIMOUSE, disables "Click-to-walk mouse interface"
110  GF_AGDS = (1 << 1), // marks games created with AGDS - all using AGI version 2.440
111  GF_AGI256 = (1 << 2), // marks fanmade AGI-256 games
112  GF_FANMADE = (1 << 3), // marks fanmade games
113  GF_2GSOLDSOUND = (1 << 5),
114  GF_EXTCHAR = (1 << 6) // use WORDS.TOK.EXTENDED
115 };
116 
117 enum AgiGameID {
118  GID_AGIDEMO,
119  GID_BC,
120  GID_DDP,
121  GID_GOLDRUSH, // V3
122  GID_KQ1,
123  GID_KQ2,
124  GID_KQ3,
125  GID_KQ4,
126  GID_LSL1,
127  GID_MH1, // V3
128  GID_MH2, // V3
129  GID_MIXEDUP,
130  GID_PQ1,
131  GID_SQ1,
132  GID_SQ2,
133  GID_XMASCARD,
134  GID_FANMADE,
135  GID_GETOUTTASQ, // Fanmade
136  GID_MICKEY, // PreAGI
137  GID_WINNIE, // PreAGI
138  GID_TROLL // PreAGI
139 };
140 
141 enum AGIErrors {
142  errOK = 0,
143  errFilesNotFound,
144  errBadFileOpen,
145  errNotEnoughMemory,
146  errBadResource,
147  errIOError,
148 
149  errUnk = 127
150 };
151 
152 enum kDebugLevels {
153  kDebugLevelMain = 1 << 0,
154  kDebugLevelResources = 1 << 1,
155  kDebugLevelSprites = 1 << 2,
156  kDebugLevelInventory = 1 << 3,
157  kDebugLevelInput = 1 << 4,
158  kDebugLevelMenu = 1 << 5,
159  kDebugLevelScripts = 1 << 6,
160  kDebugLevelSound = 1 << 7,
161  kDebugLevelText = 1 << 8,
162  kDebugLevelSavegame = 1 << 9
163 };
164 
168 enum {
169  RESOURCETYPE_LOGIC = 1,
170  RESOURCETYPE_SOUND,
171  RESOURCETYPE_VIEW,
172  RESOURCETYPE_PICTURE
173 };
174 
175 enum {
176  RES_LOADED = 0x01,
177  RES_COMPRESSED = 0x40,
178  RES_PICTURE_V3_NIBBLE_PARM = 0x80 // Flag that gets set for picture resources,
179  // which use a nibble instead of a byte as F0+F2 parameters
180 };
181 
182 enum {
183  lCOMMAND_MODE = 1,
184  lTEST_MODE
185 };
186 
187 struct gameIdList {
188  gameIdList *next;
189  uint32 version;
190  uint32 crc;
191  char *gName;
192  char *switches;
193 };
194 
195 struct Mouse {
196  int button;
197  Common::Point pos;
198 
199  Mouse() : button(0) {}
200 };
201 
202 // Used by AGI Mouse protocol 1.0 for v27 (i.e. button pressed -variable).
203 enum AgiMouseButton {
204  kAgiMouseButtonUp, // Mouse button is up (not pressed)
205  kAgiMouseButtonLeft, // Left mouse button
206  kAgiMouseButtonRight, // Right mouse button
207  kAgiMouseButtonMiddle // Middle mouse button
208 };
209 
213 enum {
214  VM_VAR_CURRENT_ROOM = 0, // 0
215  VM_VAR_PREVIOUS_ROOM, // 1
216  VM_VAR_BORDER_TOUCH_EGO, // 2
217  VM_VAR_SCORE, // 3
218  VM_VAR_BORDER_CODE, // 4
219  VM_VAR_BORDER_TOUCH_OBJECT, // 5
220  VM_VAR_EGO_DIRECTION, // 6
221  VM_VAR_MAX_SCORE, // 7
222  VM_VAR_FREE_PAGES, // 8
223  VM_VAR_WORD_NOT_FOUND, // 9
224  VM_VAR_TIME_DELAY, // 10
225  VM_VAR_SECONDS, // 11
226  VM_VAR_MINUTES, // 12
227  VM_VAR_HOURS, // 13
228  VM_VAR_DAYS, // 14
229  VM_VAR_JOYSTICK_SENSITIVITY, // 15
230  VM_VAR_EGO_VIEW_RESOURCE, // 16
231  VM_VAR_AGI_ERROR_CODE, // 17
232  VM_VAR_AGI_ERROR_INFO, // 18
233  VM_VAR_KEY, // 19
234  VM_VAR_COMPUTER, // 20
235  VM_VAR_WINDOW_AUTO_CLOSE_TIMER, // 21
236  VM_VAR_SOUNDGENERATOR, // 22
237  VM_VAR_VOLUME, // 23
238  VM_VAR_MAX_INPUT_CHARACTERS, // 24
239  VM_VAR_SELECTED_INVENTORY_ITEM, // 25
240  VM_VAR_MONITOR = 26, // 26
241  VM_VAR_MOUSE_BUTTONSTATE = 27, // 27
242  VM_VAR_MOUSE_X = 28, // 28
243  VM_VAR_MOUSE_Y = 29 // 29
244 };
245 
251  kAgiMonitorCga = 0,
252  //kAgiMonitorTandy = 1, // Not sure about this
253  kAgiMonitorHercules = 2,
254  kAgiMonitorEga = 3
255  //kAgiMonitorVga = 4 // Not sure about this
256 };
257 
263  kAgiComputerPC = 0,
264  kAgiComputerApple2 = 3,
265  kAgiComputerAtariST = 4,
266  kAgiComputerAmiga = 5,
267  kAgiComputerApple2GS = 7
268 };
269 
270 enum AgiSoundType {
271  kAgiSoundPC = 1,
272  kAgiSoundTandy = 3, // Tandy (This value is also used by the Amiga AGI and Apple IIGS AGI)
273  kAgiSound2GSOld = 8 // Apple IIGS's Gold Rush! (Version 1.0M 1989-02-28 (CE), AGI 3.003) uses value 8
274 };
275 
279 enum {
280  VM_FLAG_EGO_WATER = 0, // 0
281  VM_FLAG_EGO_INVISIBLE,
282  VM_FLAG_ENTERED_CLI,
283  VM_FLAG_EGO_TOUCHED_P2,
284  VM_FLAG_SAID_ACCEPTED_INPUT,
285  VM_FLAG_NEW_ROOM_EXEC, // 5
286  VM_FLAG_RESTART_GAME,
287  VM_FLAG_SCRIPT_BLOCKED,
288  VM_FLAG_JOY_SENSITIVITY,
289  VM_FLAG_SOUND_ON,
290  VM_FLAG_DEBUGGER_ON, // 10
291  VM_FLAG_LOGIC_ZERO_FIRST_TIME,
292  VM_FLAG_RESTORE_JUST_RAN,
293  VM_FLAG_STATUS_SELECTS_ITEMS,
294  VM_FLAG_MENUS_ACCESSIBLE,
295  VM_FLAG_OUTPUT_MODE, // 15
296  VM_FLAG_AUTO_RESTART
297 };
298 
300  uint16 keycode;
301  byte controllerSlot;
302 
303  AgiControllerKeyMapping() : keycode(0), controllerSlot(0) {}
304 };
305 
306 struct AgiObject {
307  int location;
308  Common::String name;
309 };
310 
311 struct AgiDir {
312  uint8 volume;
313  uint32 offset;
314  uint32 len;
315  uint32 clen;
316 
317  // 0 = not in mem, can be freed
318  // 1 = in mem, can be released
319  // 2 = not in mem, can't be released
320  // 3 = in mem, can't be released
321  // 0x40 = was compressed
322  uint8 flags;
323 
324  void reset() {
325  volume = 0xff;
326  offset = _EMPTY;
327  len = 0;
328  clen = 0;
329  flags = 0;
330  }
331 
332  AgiDir() { reset(); }
333 };
334 
335 struct AgiBlock {
336  bool active;
337  int16 x1, y1;
338  int16 x2, y2;
339 
340  AgiBlock() : active(false), x1(0), y1(0), x2(0), y2(0) {}
341 };
342 
343 struct ScriptPos {
344  int script;
345  int curIP;
346 };
347 
348 enum CycleInnerLoopType {
349  CYCLE_INNERLOOP_GETSTRING = 0,
350  CYCLE_INNERLOOP_GETNUMBER,
351  CYCLE_INNERLOOP_INVENTORY,
352  CYCLE_INNERLOOP_MENU_VIA_KEYBOARD,
353  CYCLE_INNERLOOP_MENU_VIA_MOUSE,
354  CYCLE_INNERLOOP_SYSTEMUI_SELECTSAVEDGAMESLOT,
355  CYCLE_INNERLOOP_SYSTEMUI_VERIFICATION,
356  CYCLE_INNERLOOP_MESSAGEBOX,
357  CYCLE_INNERLOOP_HAVEKEY
358 };
359 
361 
363 
369 struct AgiGame {
370  AgiEngine *_vm;
371 
372  // TODO: Check whether adjMouseX and adjMouseY must be saved and loaded when using savegames.
373  // If they must be then loading and saving is partially broken at the moment.
374  int adjMouseX;
375  int adjMouseY;
377  char id[8];
378  uint32 crc;
380  // game flags and variables
381  uint8 flags[MAX_FLAGS];
382  uint8 vars[MAX_VARS];
384  // internal variables
385  int16 horizon;
387  bool cycleInnerLoopActive;
388  int16 cycleInnerLoopType;
389 
390  int16 curLogicNr;
391  Common::Array<ScriptPos> execStack;
392 
393  // internal flags
398  // windows
399  AgiBlock block;
400 
401  // graphics & text
402  bool gfxMode;
403 
404  unsigned int numObjects;
405 
406  bool controllerOccurred[MAX_CONTROLLERS];
407  AgiControllerKeyMapping controllerKeyMapping[MAX_CONTROLLER_KEYMAPPINGS];
408 
409  char strings[MAX_STRINGS + 1][MAX_STRINGLEN];
411  // directory entries for resources
412  AgiDir dirLogic[MAX_DIRECTORY_ENTRIES];
413  AgiDir dirPic[MAX_DIRECTORY_ENTRIES];
414  AgiDir dirView[MAX_DIRECTORY_ENTRIES];
415  AgiDir dirSound[MAX_DIRECTORY_ENTRIES];
416 
417  // resources
418  AgiPicture pictures[MAX_DIRECTORY_ENTRIES];
419  AgiLogic logics[MAX_DIRECTORY_ENTRIES];
420  AgiView views[MAX_DIRECTORY_ENTRIES];
421  AgiSound *sounds[MAX_DIRECTORY_ENTRIES];
423  AgiLogic *_curLogic;
424 
425  // view table
426  ScreenObjEntry screenObjTable[SCREENOBJECTS_MAX];
427 
428  ScreenObjEntry addToPicView;
429 
431  char automaticSaveDescription[SAVEDGAME_DESCRIPTION_LEN + 1];
432 
435  bool mouseHidden;
438  // IF condition handling
439  bool testResult;
440 
441  int max_logics;
442  int logic_list[256];
443 
444  // used to detect situations, where the game shows some text and changes rooms right afterwards
445  // for example Space Quest 2 intro right at the start
446  // or Space Quest 2, when entering the vent also right at the start
447  // The developers assumed that loading the new room would take a bit.
448  // In ScummVM it's basically done in an instant, which means that
449  // the text would only get shown for a split second.
450  // We delay a bit as soon as such situations get detected.
451  bool nonBlockingTextShown;
452  int16 nonBlockingTextCyclesLeft;
453 
454  bool automaticRestoreGame;
455 
456  byte speedLevel;
458  uint16 appleIIgsSpeedControllerSlot;
459 
460  const char *getString(int number);
461  void setString(int number, const char *str);
465  void setSpeedLevel(byte s);
466 
467  AgiGame() {
468  _vm = nullptr;
469 
470  adjMouseX = 0;
471  adjMouseY = 0;
472 
473  memset(id, 0, sizeof(id));
474  crc = 0;
475  memset(flags, 0, sizeof(flags));
476  memset(vars, 0, sizeof(vars));
477 
478  horizon = 0;
479 
480  cycleInnerLoopActive = false;
481  cycleInnerLoopType = 0;
482 
483  curLogicNr = 0;
484 
485  // execStack is defaulted by Common::Array constructor
486 
487  playerControl = false;
488  exitAllLogics = false;
489  pictureShown = false;
490 
491  // block defaulted by AgiBlock constructor
492 
493  gfxMode = false;
494 
495  numObjects = 0;
496 
497  memset(controllerOccurred, 0, sizeof(controllerOccurred));
498 
499  // controllerKeyMapping defaulted by AgiControllerKeyMapping constructor
500 
501  memset(strings, 0, sizeof(strings));
502 
503  // dirLogic cleared by AgiDir constructor
504  // dirPic cleared by AgiDir constructor
505  // dirView cleared by AgiDir constructor
506  // dirSound cleared by AgiDir constructor
507 
508  // pictures cleared by AgiPicture constructor
509  // logics cleared by AgiLogic constructor
510  // views cleared by AgiView constructor
511  memset(sounds, 0, sizeof(sounds));
512 
513  _curLogic = nullptr;
514 
515  // screenObjTable cleared by ScreenObjEntry constructor
516 
517  // addToPicView cleared by ScreenObjEntry constructor
518 
519  automaticSave = false;
520  memset(automaticSaveDescription, 0, sizeof(automaticSaveDescription));
521 
522  // mouseFence cleared by Common::Rect constructor
523  mouseEnabled = false;
524  mouseHidden = false;
525  predictiveDlgOnMouseClick = false;
526 
527  testResult = false;
528 
529  max_logics = 0;
530  memset(logic_list, 0, sizeof(logic_list));
531 
532  nonBlockingTextShown = false;
533  nonBlockingTextCyclesLeft = 0;
534 
535  automaticRestoreGame = false;
536 
537  speedLevel = 2; // normal speed
538 
539  appleIIgsSpeedControllerSlot = 0xffff; // we didn't add yet speed menu
540  }
541 };
542 
544  uint32 disk;
545  uint32 offset;
546 
547  AgiDiskVolume() : disk(_EMPTY), offset(0) {}
548  AgiDiskVolume(uint32 d, uint32 o) : disk(d), offset(o) {}
549 };
550 
556  A2DirVersionOld, // 4 bits for volume, 8 for track
557  A2DirVersionNew, // 5 bits for volume, 7 for track
558 };
559 
560 class AgiLoader {
561 public:
562  AgiLoader(AgiEngine *vm) : _vm(vm) {}
563  virtual ~AgiLoader() {}
564 
569  virtual void init() {}
570 
575  virtual int loadDirs() = 0;
576 
580  virtual uint8 *loadVolumeResource(AgiDir *agid) = 0;
581 
585  virtual int loadObjects() = 0;
586 
590  virtual int loadWords() = 0;
591 
592 protected:
593  AgiEngine *_vm;
594 };
595 
596 class AgiLoader_A2 : public AgiLoader {
597 public:
598  AgiLoader_A2(AgiEngine *vm) : AgiLoader(vm) {}
599  ~AgiLoader_A2() override;
600 
601  void init() override;
602  int loadDirs() override;
603  uint8 *loadVolumeResource(AgiDir *agid) override;
604  int loadObjects() override;
605  int loadWords() override;
606 
607 private:
610  AgiDir _logDir;
611  AgiDir _picDir;
612  AgiDir _viewDir;
613  AgiDir _soundDir;
614  AgiDir _objects;
615  AgiDir _words;
616 
617  int readDiskOne(Common::SeekableReadStream &stream, Common::Array<uint32> &volumeMap);
618  static bool readInitDir(Common::SeekableReadStream &stream, byte index, AgiDir &agid);
619  static bool readDir(Common::SeekableReadStream &stream, int position, AgiDir &agid);
620  static bool readVolumeMap(Common::SeekableReadStream &stream, uint32 position, uint32 bufferLength, Common::Array<uint32> &volumeMap);
621 
622  A2DirVersion detectDirVersion(Common::SeekableReadStream &stream);
623  bool loadDir(AgiDir *dir, Common::SeekableReadStream &disk, uint32 dirOffset, uint32 dirLength, A2DirVersion dirVersion);
624 };
625 
626 class AgiLoader_v1 : public AgiLoader {
627 public:
628  AgiLoader_v1(AgiEngine *vm) : AgiLoader(vm) {}
629 
630  void init() override;
631  int loadDirs() override;
632  uint8 *loadVolumeResource(AgiDir *agid) override;
633  int loadObjects() override;
634  int loadWords() override;
635 
636 private:
637  Common::Array<Common::String> _imageFiles;
639  AgiDir _logDir;
640  AgiDir _picDir;
641  AgiDir _viewDir;
642  AgiDir _soundDir;
643  AgiDir _objects;
644  AgiDir _words;
645 
646  bool readDiskOneV1(Common::SeekableReadStream &stream);
647  bool readDiskOneV2001(Common::SeekableReadStream &stream, int &vol0Offset);
648  static bool readInitDirV1(Common::SeekableReadStream &stream, byte index, AgiDir &agid);
649  static bool readInitDirV2001(Common::SeekableReadStream &stream, byte index, AgiDir &agid);
650 
651  bool loadDir(AgiDir *dir, Common::File &disk, uint32 dirOffset, uint32 dirLength);
652 };
653 
654 class AgiLoader_v2 : public AgiLoader {
655 private:
656  bool _hasV3VolumeFormat;
657 
658  int loadDir(AgiDir *agid, const char *fname);
659  bool detectV3VolumeFormat();
660 
661 public:
662  AgiLoader_v2(AgiEngine *vm) : _hasV3VolumeFormat(false), AgiLoader(vm) {}
663 
664  int loadDirs() override;
665  uint8 *loadVolumeResource(AgiDir *agid) override;
666  int loadObjects() override;
667  int loadWords() override;
668 };
669 
670 class AgiLoader_v3 : public AgiLoader {
671 private:
672  Common::String _name;
674  int loadDir(AgiDir *agid, Common::File *fp, uint32 offs, uint32 len);
675 
676 public:
677  AgiLoader_v3(AgiEngine *vm) : AgiLoader(vm) {}
678 
679  void init() override;
680  int loadDirs() override;
681  uint8 *loadVolumeResource(AgiDir *agid) override;
682  int loadObjects() override;
683  int loadWords() override;
684 };
685 
686 class GfxFont;
687 class GfxMgr;
688 class SpritesMgr;
689 class InventoryMgr;
690 class TextMgr;
691 class GfxMenu;
692 class SystemUI;
693 class Words;
694 struct AGIGameDescription;
695 
696 // Image stack support
698  uint8 type;
699  uint8 pad;
700  int16 parm1;
701  int16 parm2;
702  int16 parm3;
703  int16 parm4;
704  int16 parm5;
705  int16 parm6;
706  int16 parm7;
707 };
708 
709 #define TICK_SECONDS 20
710 
711 #define KEY_QUEUE_SIZE 16
712 
713 class AgiBase : public ::Engine {
714 protected:
715  // Engine API
716  Common::Error init();
717  virtual Common::Error go() = 0;
718  Common::Error run() override {
719  Common::Error err;
720  err = init();
721  if (err.getCode() != Common::kNoError)
722  return err;
723  return go();
724  }
725  bool hasFeature(EngineFeature f) const override;
726 
727  virtual void initialize() = 0;
728 
729  void initRenderMode();
730 
731 public:
732  Words *_words;
733 
734  GfxFont *_font;
735  GfxMgr *_gfx;
736 
737  Common::RenderMode _renderMode;
738  AgiDebug _debug;
739  AgiGame _game;
740  Common::RandomSource *_rnd;
741 
742  SoundMgr *_sound;
743 
744  Mouse _mouse;
745 
746  bool _noSaveLoadAllowed;
747 
748  virtual bool promptIsEnabled() {
749  return false;
750  }
751 
752  virtual int getKeypress() = 0;
753  virtual bool isKeypress() = 0;
754  virtual void clearKeyQueue() = 0;
755 
756  AgiBase(OSystem *syst, const AGIGameDescription *gameDesc);
757  ~AgiBase() override;
758 
759  virtual void clearImageStack() = 0;
760  virtual void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
761  int16 p4, int16 p5, int16 p6, int16 p7) = 0;
762  virtual void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
763  int16 p4, int16 p5, int16 p6, int16 p7) = 0;
764  virtual void releaseImageStack() = 0;
765 
766  int _soundemu;
767 
768  bool getFlag(int16 flagNr);
769  void setFlag(int16 flagNr, bool newState);
770  void flipFlag(int16 flagNr);
772  void setFlagOrVar(int16 flagNr, bool newState);
773 
774  const AGIGameDescription *_gameDescription;
775 
776  uint32 _gameFeatures;
777  uint16 _gameVersion;
778 
779  uint32 getGameID() const;
780  uint32 getFeatures() const;
781  uint16 getVersion() const;
782  uint16 getGameType() const;
783  Common::Language getLanguage() const;
784  bool isLanguageRTL() const;
785  Common::Platform getPlatform() const;
786  const char *getGameMD5() const;
787  void initFeatures();
788  void initVersion();
789 
790  const char *getDiskName(uint16 id);
791 
792  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
793  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
794 
795  const byte *getFontData();
796 
797  void cycleInnerLoopActive(int16 loopType) {
798  _game.cycleInnerLoopActive = true;
799  _game.cycleInnerLoopType = loopType;
800  };
801  void cycleInnerLoopInactive() {
802  _game.cycleInnerLoopActive = false;
803  };
804  bool cycleInnerLoopIsActive() {
805  return _game.cycleInnerLoopActive;
806  }
807 };
808 
809 enum AgiArtificialDelayTriggerType {
810  ARTIFICIALDELAYTYPE_NEWROOM = 0,
811  ARTIFICIALDELAYTYPE_NEWPICTURE = 1,
812  ARTIFICIALDELAYTYPE_END = -1
813 };
814 
816  uint32 gameId;
817  Common::Platform platform;
818  AgiArtificialDelayTriggerType triggerType;
819  int16 orgNr;
820  int16 newNr;
821  uint16 millisecondsDelay;
822 };
823 
824 typedef void (*AgiOpCodeFunction)(AgiGame *state, AgiEngine *vm, uint8 *p);
825 
827  const char *name;
828  const char *parameters;
829  AgiOpCodeFunction functionPtr;
830  uint16 parameterSize;
831 };
832 
834  const char *name;
835  const char *parameters;
836  AgiOpCodeFunction functionPtr;
837 };
838 
839 class AgiEngine : public AgiBase {
840 protected:
841  // Engine APIs
842  Common::Error go() override;
843 
844  void initialize() override;
845 
846 public:
847  AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc);
848  ~AgiEngine() override;
849 
850  bool promptIsEnabled() override;
851 
852  Common::Error loadGameState(int slot) override;
853  Common::Error saveGameState(int slot, const Common::String &description, bool isAutosave = false) override;
854 
855 private:
856  int _keyQueue[KEY_QUEUE_SIZE];
857  int _keyQueueStart;
858  int _keyQueueEnd;
859 
860  bool _allowSynthetic;
861 
862  bool checkPriority(ScreenObjEntry *v);
863  bool checkCollision(ScreenObjEntry *v);
864  bool checkPosition(ScreenObjEntry *v);
865 
866  int _firstSlot;
867 
868 public:
869  Common::Array<AgiObject> _objects; // objects in the game
870 
871  SavedGameSlotIdArray getSavegameSlotIds();
872  bool getSavegameInformation(int16 slotId, Common::String &saveDescription, uint32 &saveDate, uint32 &saveTime, bool &saveIsValid);
873 
874  int saveGame(const Common::String &fileName, const Common::String &descriptionString);
875  int loadGame(const Common::String &fileName, bool checkId = true);
876  bool saveGameDialog();
877  bool saveGameAutomatic();
878  bool loadGameDialog();
879  bool loadGameAutomatic();
880  int doSave(int slot, const Common::String &desc);
881  int doLoad(int slot, bool showMessages);
882  int scummVMSaveLoadDialog(bool isSave);
883 
884  uint8 *_intobj;
885  bool _restartGame;
886 
887  SpritesMgr *_sprites;
888  TextMgr *_text;
889  InventoryMgr *_inventory;
890  PictureMgr *_picture;
891  AgiLoader *_loader;
892  GfxMenu *_menu;
893  SystemUI *_systemUI;
894  Common::DumpFile *_logFile; // File used for the log() agi command.
895 
897 
898  void clearImageStack() override;
899  void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
900  int16 p4, int16 p5, int16 p6, int16 p7) override;
901  void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
902  int16 p4, int16 p5, int16 p6, int16 p7) override;
903  void releaseImageStack() override;
904 
905  void wait(uint32 msec, bool busy = false);
906 
907  int agiInit();
908  void agiDeinit();
909  int loadResource(int16 resourceType, int16 resourceNr);
910  void unloadResource(int16 resourceType, int16 resourceNr);
914  void unloadResources();
915 
916  int getKeypress() override;
917  bool isKeypress() override;
918  void clearKeyQueue() override;
919 
920  byte getVar(int16 varNr);
921  void setVar(int16 varNr, byte newValue);
922 
923 private:
924  void applyVolumeToMixer();
925 
926 public:
927  void syncSoundSettings() override;
928 
929 public:
930  void decrypt(uint8 *mem, int len);
931  uint16 processAGIEvents();
932  int runGame();
933 
934  void newRoom(int16 newRoomNr);
935  void resetControllers();
936  void interpretCycle();
937  void playGame();
938 
939  void allowSynthetic(bool);
940  void processScummVMEvents();
941  void checkQuickLoad();
942 
943  const Common::String getTargetName() const { return _targetName; }
944 
945 private:
946  byte getAppleIIgsTimeDelay(const AgiAppleIIgsDelayOverwriteGameEntry *appleIIgsDelayOverwrite, byte &newTimeDelay) const;
947 
948  // Objects
949 public:
950  int loadObjects(const char *fname);
951  int loadObjects(Common::SeekableReadStream &fp, int flen);
952  const char *objectName(uint16 objectNr);
953  int objectGetLocation(uint16 objectNr);
954  void objectSetLocation(uint16 objectNr, int location);
955 private:
956  int decodeObjects(uint8 *mem, uint32 flen);
957 
958  // Logic
959 public:
960  int decodeLogic(int16 logicNr);
961  void unloadLogic(int16 logicNr);
962  int runLogic(int16 logicNr);
963  void debugConsole(int lognum, int mode, const char *str);
964  bool testIfCode(int16 logicNr);
965  void executeAgiCommand(uint8 op, uint8 *p);
966 
967 private:
968  bool _veryFirstInitialCycle;
969  uint32 _instructionCounter;
971  bool _setVolumeBrokenFangame;
972 
973  void resetGetVarSecondsHeuristic();
974  void getVarSecondsHeuristicTrigger();
975  uint32 _getVarSecondsHeuristicLastInstructionCounter;
976  uint16 _getVarSecondsHeuristicCounter;
978  uint32 _playTimeInSecondsAdjust;
980  void setVarSecondsTrigger(byte newSeconds);
981 
982 public:
983  // Some submethods of testIfCode
984  void skipInstruction(byte op);
985  void skipInstructionsUntil(byte v);
986  bool testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2);
987  bool testObjCenter(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2);
988  bool testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2);
989  bool testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2);
990  bool testSaid(uint8 nwords, uint8 *cc);
991  bool testController(uint8 cont);
992  bool testCompareStrings(uint8 s1, uint8 s2);
993 
994  // View
995 private:
996  void updateView(ScreenObjEntry *screenObj);
997 
998 public:
999  void setView(ScreenObjEntry *screenObj, int16 viewNr);
1000  void setLoop(ScreenObjEntry *screenObj, int16 loopNr);
1001  void setCel(ScreenObjEntry *screenObj, int16 celNr);
1002 
1003  void clipViewCoordinates(ScreenObjEntry *screenObj);
1004 
1005  void startUpdate(ScreenObjEntry *viewPtr);
1006  void stopUpdate(ScreenObjEntry *viewPtr);
1007  void updateScreenObjTable();
1008  void unloadView(int16 viewNr);
1009  int decodeView(byte *resourceData, uint16 resourceSize, int16 viewNr);
1010 
1011 private:
1012  void unpackViewCelData(AgiViewCel *celData, byte *compressedData, uint16 compressedSize, int16 viewNr);
1013  void unpackViewCelDataAGI256(AgiViewCel *celData, byte *compressedData, uint16 compressedSize, int16 viewNr);
1014 
1015 public:
1016  bool isEgoView(const ScreenObjEntry *screenObj);
1017 
1018  // Motion
1019 private:
1020  int checkStep(int delta, int step);
1021  bool checkBlock(int16 x, int16 y);
1022  void changePos(ScreenObjEntry *screenObj);
1023  void motionWander(ScreenObjEntry *screenObj);
1024  void motionFollowEgo(ScreenObjEntry *screenObj);
1025  void motionMoveObj(ScreenObjEntry *screenObj);
1026  void motionMoveObjStop(ScreenObjEntry *screenObj);
1027  void checkMotion(ScreenObjEntry *screenObj);
1028 
1029 public:
1030  void motionActivated(ScreenObjEntry *screenObj);
1031  void cyclerActivated(ScreenObjEntry *screenObj);
1032  void checkAllMotions();
1033  void moveObj(ScreenObjEntry *screenObj);
1034  void inDestination(ScreenObjEntry *screenObj);
1035  void fixPosition(int16 screenObjNr);
1036  void fixPosition(ScreenObjEntry *screenObj);
1037  void updatePosition();
1038  int getDirection(int16 objX, int16 objY, int16 destX, int16 destY, int16 stepSize);
1039 
1040  bool _keyHoldMode;
1041  Common::KeyCode _keyHoldModeLastKey;
1042 
1043  // Keyboard
1044  int doPollKeyboard();
1045 
1046  bool handleMouseClicks(uint16 &key);
1047  bool handleController(uint16 key);
1048 
1049  bool showPredictiveDialog();
1050 
1051  int waitKey();
1052  int waitAnyKey();
1053  void waitAnyKeyOrFinishedSound();
1054 
1055  void nonBlockingText_IsShown();
1056  void nonBlockingText_Forget();
1057 
1058  void artificialDelay_Reset();
1059  void artificialDelay_CycleDone();
1060 
1061  uint16 artificialDelay_SearchTable(AgiArtificialDelayTriggerType triggerType, int16 orgNr, int16 newNr);
1062 
1063  void artificialDelayTrigger_NewRoom(int16 newRoomNr);
1064  void artificialDelayTrigger_DrawPicture(int16 newPictureNr);
1065 
1066 private:
1067  int16 _artificialDelayCurrentRoom;
1068  int16 _artificialDelayCurrentPicture;
1069 
1070 public:
1071  void redrawScreen();
1072 
1073  void inGameTimerReset(uint32 newPlayTime = 0);
1074  void inGameTimerResetPassedCycles();
1075  uint32 inGameTimerGet();
1076  uint32 inGameTimerGetPassedCycles();
1077 
1078  void inGameTimerUpdate();
1079 
1080 private:
1081  uint32 _lastUsedPlayTimeInCycles; // 40 per second
1082  uint32 _lastUsedPlayTimeInSeconds; // actual seconds
1083  uint32 _passedPlayTimeCycles; // increased by 1 every time we passed a cycle
1084 
1085 private:
1086  AgiOpCodeEntry _opCodes[256]; // always keep those at 256, so that there is no way for invalid memory access
1087  AgiOpCodeEntry _opCodesCond[256];
1088 
1089  void setupOpCodes(uint16 version);
1090 
1091 public:
1092  const AgiOpCodeEntry *getOpCodesTable() { return _opCodes; }
1093 
1094 private:
1095  void goldRushClockTimeWorkaround_OnReadVar();
1096  void goldRushClockTimeWorkaround_OnWriteVar(byte oldValue);
1097 };
1098 
1099 } // End of namespace Agi
1100 
1101 #endif /* AGI_AGI_H */
bool pictureShown
Definition: agi.h:396
Definition: str.h:59
int adjMouseX
Definition: agi.h:374
Definition: agi.h:713
EngineFeature
Definition: engine.h:253
Definition: agi.h:596
Definition: agi.h:626
Definition: error.h:84
ErrorCode getCode() const
Definition: error.h:115
Definition: agi.h:187
bool playerControl
Definition: agi.h:394
Definition: agi.h:311
Definition: random.h:44
RenderMode
Definition: rendermode.h:48
No error occurred.
Definition: error.h:48
Definition: menu.h:55
bool predictiveDlgOnMouseClick
Definition: agi.h:436
Definition: agi.h:697
Definition: rect.h:144
Definition: picture.h:66
Definition: view.h:98
Definition: stream.h:745
Definition: file.h:145
Definition: inv.h:35
Definition: systemui.h:51
virtual void init()
Definition: agi.h:569
Definition: view.h:27
Definition: agi.h:826
AgiMonitorType
Definition: agi.h:250
int adjMouseY
Definition: agi.h:375
Definition: agi.h:306
Definition: agi.h:195
Definition: console.h:32
byte speedLevel
Definition: agi.h:456
Definition: sound.h:76
Definition: logic.h:30
Definition: ustr.h:57
Definition: file.h:47
bool mouseEnabled
Definition: agi.h:434
Definition: graphics.h:58
Definition: agi.h:670
Definition: agi.h:839
int16 curLogicNr
Definition: agi.h:390
uint32 crc
Definition: agi.h:378
Definition: algorithm.h:29
Definition: rect.h:45
bool automaticSave
Definition: agi.h:430
A2DirVersion
Definition: agi.h:555
Definition: sprite.h:51
bool mouseHidden
Definition: agi.h:435
Definition: agi.h:543
Definition: agi.h:299
Definition: agi.h:343
Definition: picture.h:33
bool exitAllLogics
Definition: agi.h:395
Common::Error run() override
Definition: agi.h:718
AgiComputerType
Definition: agi.h:262
Definition: agi.h:815
Definition: words.h:35
Definition: appleIIgs_timedelay_overwrite.h:36
Definition: system.h:161
Definition: agi.h:369
int16 horizon
Definition: agi.h:385
Definition: agi.h:335
Definition: agi.h:560
Definition: sound.h:115
Definition: stack.h:102
Common::Rect mouseFence
Definition: agi.h:433
Definition: agi.h:833
Definition: engine.h:144
Definition: agi.h:654
Definition: detection.h:29
Definition: agi.h:63
Platform
Definition: platform.h:46
Definition: font.h:27
Definition: text.h:76
Definition: view.h:43
Language
Definition: language.h:45