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