ScummVM API documentation
kyra_v1.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 KYRA_KYRA_V1_H
23 #define KYRA_KYRA_V1_H
24 
25 #include "engines/engine.h"
26 
27 #include "common/array.h"
28 #include "common/error.h"
29 #include "common/events.h"
30 #include "common/hashmap.h"
31 #include "common/random.h"
32 #include "common/rendermode.h"
33 
34 #include "audio/mixer.h"
35 
36 #include "kyra/script/script.h"
37 #include "kyra/engine/item.h"
38 #include "kyra/detection.h"
39 
40 namespace Common {
41 class OutSaveFile;
42 class SeekableReadStream;
43 class WriteStream;
44 } // End of namespace Common
45 
46 namespace Graphics {
47 struct Surface;
48 }
49 
50 class KyraMetaEngine;
51 
87 namespace Kyra {
88 
89 struct KeyCodeHash : public Common::UnaryFunction<Common::KeyCode, uint> {
90  uint operator()(Common::KeyCode val) const { return (uint)val; }
91 };
92 
93 // TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable
94 // in the future we maybe merge some flags and/or create new ones
97  kDebugLevelScript = 1 << 1,
98  kDebugLevelSprites = 1 << 2,
99  kDebugLevelScreen = 1 << 3,
100  kDebugLevelSound = 1 << 4,
102  kDebugLevelMain = 1 << 6,
103  kDebugLevelGUI = 1 << 7,
105  kDebugLevelMovie = 1 << 9,
106  kDebugLevelTimer = 1 << 10
107 };
108 
109 enum AudioResourceSet {
110  kMusicIntro = 0,
111  kMusicIngame,
112  kMusicFinale
113 };
114 
115 class Screen;
116 class Resource;
117 class Sound;
118 class TextDisplayer;
119 class StaticResource;
120 class TimerManager;
121 class Debugger;
122 class GUI;
123 
124 struct Button;
125 
126 class KyraEngine_v1 : public Engine {
127 friend class Debugger;
128 friend class ::KyraMetaEngine;
129 friend class GUI;
130 friend class GUI_v1;
131 friend class GUI_EoB;
132 friend class GUI_EoB_SegaCD;
133 friend class SoundMidiPC; // For _eventMan
134 friend class SeqPlayer_HOF; // For skipFlag()
135 friend class TransferPartyWiz; // For save state API
136 public:
137  KyraEngine_v1(OSystem *system, const GameFlags &flags);
138  ~KyraEngine_v1() override;
139 
140  uint8 game() const { return _flags.gameID; }
141  const GameFlags &gameFlags() const { return _flags; }
142 
143  // access to Kyra specific functionallity
144  Resource *resource() { return _res; }
145  virtual Screen *screen() = 0;
146  virtual TextDisplayer *text() { return _text; }
147  virtual GUI *gui() const { return 0; }
148  Sound *sound() { return _sound; }
149  StaticResource *staticres() { return _staticres; }
150  TimerManager *timer() { return _timer; }
151 
152  uint32 tickLength() const { return _tickLength; }
153 
155 
156  // input
157  void setMousePos(int x, int y);
158  Common::Point getMousePos();
159 
160  // config specific
161  bool speechEnabled();
162  bool textEnabled();
163 
164  enum kVolumeEntry {
165  kVolumeMusic = 0,
166  kVolumeSfx = 1,
167  kVolumeSpeech = 2
168  };
169 
170  // volume reaches per default from 2 to 97
171  void setVolume(kVolumeEntry vol, uint8 value);
172  uint8 getVolume(kVolumeEntry vol);
173 
174  void syncSoundSettings() override;
175 
176  // game flag handling
177  int setGameFlag(int flag);
178  int queryGameFlag(int flag) const;
179  int resetGameFlag(int flag);
180 
181  // sound
182  virtual void snd_playTheme(int file, int track);
183  virtual void snd_playSoundEffect(int id, int volume=0xFF);
184  virtual void snd_playWanderScoreViaMap(int command, int restart);
185  virtual void snd_playVoiceFile(int id) = 0;
186  virtual bool snd_voiceIsPlaying();
187  virtual void snd_stopVoice();
188 
189  // delay functionallity
190  virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false);
191  virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false);
192  virtual void delayWithTicks(int ticks);
193 
194 protected:
195  // Engine APIs
196  virtual Common::Error init();
197  virtual Common::Error go() = 0;
198 
199  Common::Error run() override {
200  Common::Error err;
201  registerDefaultSettings();
202  err = init();
203  if (err.getCode() != Common::kNoError)
204  return err;
205  return go();
206  }
207 
208  bool hasFeature(EngineFeature f) const override;
209  void pauseEngineIntern(bool pause) override;
210 
211  // intern
212  Resource *_res;
213  Sound *_sound;
214  TextDisplayer *_text;
215  StaticResource *_staticres;
216  TimerManager *_timer;
217  EMCInterpreter *_emc;
218 
219  // input
220  void setupKeyMap();
221  void updateInput();
222  int checkInput(Button *buttonList, bool mainLoop = false, int eventFlag = 0x8000);
223  void removeInputTop();
224 
225  int _mouseX, _mouseY;
226 
227  // This is a somewhat hacky but probably least invasive way to move
228  // the whole ingame screen output down a couple of lines for EOB SegaCD.
229  void transposeScreenOutputY(int yAdd);
230  int _transOffsY;
231 
232  struct Event {
233  Common::Event event;
234  bool causedSkip;
235 
236  Event() : event(), causedSkip(false) {}
237  Event(Common::Event e) : event(Common::move(e)), causedSkip(false) {}
238  Event(Common::Event e, bool skip) : event(Common::move(e)), causedSkip(skip) {}
239 
240  operator Common::Event() const { return event; }
241  };
242  Common::List<Event> _eventList;
244  KeyMap _keyMap;
245  bool _asciiCodeEvents;
246  bool _kbEventSkip;
247 
248  // config specific
249  virtual void registerDefaultSettings();
250  virtual void readSettings();
251  virtual void writeSettings();
252 
253  uint8 _configWalkspeed;
254 
255  int _configMusic;
256  bool _configSounds;
257  uint8 _configVoice;
258  bool _configNullSound;
259 
260  Common::RenderMode _configRenderMode;
261 
262  // game speed
263  virtual bool skipFlag() const;
264  virtual void resetSkipFlag(bool removeEvent = true);
265 
266  uint16 _tickLength;
267  uint16 _gameSpeed;
268 
269  // run
270  int8 _deathHandler;
271 
272  // timer
273  virtual void setupTimers() = 0;
274 
275  virtual void setWalkspeed(uint8 speed) = 0;
276 
277  // detection
278  GameFlags _flags;
279 
280  // opcode
281  virtual void setupOpcodeTable() = 0;
283 
284  int o1_queryGameFlag(EMCState *script);
285  int o1_setGameFlag(EMCState *script);
286  int o1_resetGameFlag(EMCState *script);
287  int o1_getRand(EMCState *script);
288  int o1_hideMouse(EMCState *script);
289  int o1_showMouse(EMCState *script);
290  int o1_setMousePos(EMCState *script);
291  int o1_setHandItem(EMCState *script);
292  int o1_removeHandItem(EMCState *script);
293  int o1_getMouseState(EMCState *script);
294  int o1_setDeathHandler(EMCState *script);
295  int o1_playWanderScoreViaMap(EMCState *script);
296  int o1_fillRect(EMCState *script);
297  int o1_blockInWalkableRegion(EMCState *script);
298  int o1_blockOutWalkableRegion(EMCState *script);
299  int o1_playSoundEffect(EMCState *script);
300 
301  // script debug
302 #ifndef RELEASE_BUILD
303  int16 emcSafeReadStack(EMCState *s, int x, int line, const char *file) {
304  if (s->sp+x > EMCState::kStackLastEntry) {
305  //assert(sp+x < kStackSize);
306  warning("Invalid EMC stack read attempt from: '%s', line %d", file, line);
307  return 0;
308  }
309  return s->stack[s->sp+x];
310  }
311 #endif
312 
313  // items
314  int _mouseState;
315 
316  virtual void setHandItem(Item item) = 0;
317  virtual void removeHandItem() = 0;
318 
319  // game flags
320  uint8 _flagsTable[100]; // TODO: check this value
321 
322  // sound
323  Audio::SoundHandle _speechHandle;
324 
325  int _curMusicTheme;
326  int _curSfxFile;
327  int16 _lastMusicCommand;
328 
329  const int8 *_trackMap;
330  int _trackMapSize;
331 
332  bool _preventScriptSfx;
333 
334  virtual int convertVolumeToMixer(int value);
335  virtual int convertVolumeFromMixer(int value);
336 
337  // pathfinder
338  virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize);
339  int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end);
340  int getFacingFromPointToPoint(int x, int y, int toX, int toY);
341  int getOppositeFacingDirection(int dir);
342  void changePosTowardsFacing(int &x, int &y, int facing);
343  int getMoveTableSize(int *moveTable);
344  virtual bool lineIsPassable(int x, int y) = 0;
345 
346  static const int8 _addXPosTable[];
347  static const int8 _addYPosTable[];
348 
349  // Character
350 
351  static const int8 _charAddXPosTable[];
352  static const int8 _charAddYPosTable[];
353 
354  // save/load
355  int _gameToLoad;
356 
357  bool _isSaveAllowed;
358 
359  bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
360  bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _isSaveAllowed; }
361  int getAutosaveSlot() const override { return 999; }
362 
363  const char *getSavegameFilename(int num);
364  Common::String _savegameFilename;
365  static Common::String getSavegameFilename(const Common::String &target, int num);
366  bool saveFileLoadable(int slot);
367 
368  struct SaveHeader {
369  Common::String description;
370  uint32 version;
371  byte gameID;
372  uint32 flags;
373 
374  bool originalSave; // savegame from original interpreter
375  bool oldHeader; // old scummvm save header
376 
377  Graphics::Surface *thumbnail;
378 
379  TimeDate timeDate;
380  uint32 totalPlaySecs;
381  };
382 
383  enum ReadSaveHeaderError {
384  kRSHENoError = 0,
385  kRSHEInvalidType = 1,
386  kRSHEInvalidVersion = 2,
387  kRSHEIoError = 3
388  };
389 
390  WARN_UNUSED_RESULT static ReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, SaveHeader &header, bool skipThumbnail = true);
391 
392  void loadGameStateCheck(int slot);
393  Common::Error loadGameState(int slot) override = 0;
394  Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override {
395  return saveGameStateIntern(slot, desc.c_str(), 0);
396  }
397  virtual Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) = 0;
398 
399  Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header, bool checkID = true);
400  Common::OutSaveFile *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const;
401 
402  // TODO: Consider moving this to Screen
403  virtual Graphics::Surface *generateSaveThumbnail() const { return 0; }
404 
405  // Officially used in EOB SegaCD (appears in the final stats), but we also use this for the savegame metadata for all games.
406  void updatePlayTimer();
407  void restartPlayTimerAt(uint32 totalPlaySecs);
408  void pausePlayTimer(bool pause);
409 
410  uint32 _lastSecTick;
411  uint32 _lastSecTickAtPauseStart;
412  uint32 _totalPlaySecs;
413 };
414 
415 } // End of namespace Kyra
416 
417 #endif
Definition: script.h:113
Definition: resource.h:1250
Definition: system.h:105
Definition: str.h:59
bool canLoadGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: kyra_v1.h:359
Definition: surface.h:66
EngineFeature
Definition: engine.h:250
Definition: savefile.h:54
Definition: error.h:84
debug level for "TimerManager" functions
Definition: kyra_v1.h:106
ErrorCode getCode() const
Definition: error.h:115
Definition: text.h:32
void warning(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: resource.h:48
DebugLevels
Definition: kyra_v1.h:95
Definition: random.h:44
Definition: list.h:44
Definition: kyra_v1.h:126
Definition: screen.h:565
Definition: kyra_v1.h:232
RenderMode
Definition: rendermode.h:48
No error occurred.
Definition: error.h:48
bool canSaveGameStateCurrently(Common::U32String *msg=nullptr) override
Definition: kyra_v1.h:360
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave=false) override
Definition: kyra_v1.h:394
Definition: kyra_v1.h:89
Definition: stream.h:745
Definition: system.h:45
Definition: sound.h:91
debug level for "SeqPlayer" functions
Definition: kyra_v1.h:104
Definition: script.h:47
Definition: mixer.h:49
Definition: kyra_v1.h:368
Definition: ustr.h:57
debug level for "Screen" functions
Definition: kyra_v1.h:99
debug level for o::_* functions
Definition: kyra_v1.h:96
constexpr remove_reference_t< T > && move(T &&t) noexcept
Definition: util.h:209
Definition: events.h:198
Definition: algorithm.h:29
Definition: formatinfo.h:28
Common::Error run() override
Definition: kyra_v1.h:199
Definition: rect.h:45
bool skipThumbnail(Common::SeekableReadStream &in)
Definition: timer.h:48
Definition: detection.h:38
Definition: detection.h:27
Definition: gui.h:38
int getAutosaveSlot() const override
Definition: kyra_v1.h:361
Definition: debugger.h:34
Definition: system.h:167
debug level for "ScreenAnimator" functions
Definition: kyra_v1.h:101
Definition: gui_v1.h:82
Definition: engine.h:143
Definition: sound_intern.h:58
Definition: func.h:43
debug level for "EMCInterpreter" functions
Definition: kyra_v1.h:97
debug level for movie specific funtions
Definition: kyra_v1.h:105