1 
2 /* ScummVM - Graphic Adventure Engine
3  *
4  * ScummVM is the legal property of its developers, whose names
5  * are too numerous to list here. Please refer to the COPYRIGHT
6  * file distributed with this source distribution.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #ifndef ULTIMA8_ULTIMA8
25 #define ULTIMA8_ULTIMA8
26 
27 #include "common/stream.h"
28 #include "ultima/shared/std/containers.h"
29 #include "ultima/shared/engine/ultima.h"
30 #include "ultima/ultima8/usecode/intrinsics.h"
31 #include "ultima/ultima8/misc/common_types.h"
32 #include "ultima/ultima8/games/game_info.h"
33 #include "ultima/detection.h"
34 
35 namespace Ultima {
36 namespace Ultima8 {
37 
38 class Debugger;
39 class Kernel;
40 class UCMachine;
41 class Game;
42 class Gump;
43 class GameMapGump;
44 class MenuGump;
45 class InverterGump;
46 class RenderSurface;
47 class PaletteManager;
48 class GameData;
49 class World;
50 class ObjectManager;
51 class FontManager;
52 class Mouse;
53 class AvatarMoverProcess;
54 class Texture;
55 class AudioMixer;
56 class FileSystem;
57 class ConfigFileManager;
58 struct GameInfo;
59 
60 #define GAME_IS_U8 (Ultima8Engine::get_instance()->getGameInfo()->_type == GameInfo::GAME_U8)
61 #define GAME_IS_REMORSE (Ultima8Engine::get_instance()->getGameInfo()->_type == GameInfo::GAME_REMORSE)
62 #define GAME_IS_REGRET (Ultima8Engine::get_instance()->getGameInfo()->_type == GameInfo::GAME_REGRET)
63 #define GAME_IS_CRUSADER (GAME_IS_REMORSE || GAME_IS_REGRET)
64 
65 class Ultima8Engine : public Shared::UltimaEngine {
66 	friend class Debugger;
67 private:
68 	bool _isRunning;
69 	GameInfo *_gameInfo;
70 
71 	// minimal system
72 	FileSystem *_fileSystem;
73 	ConfigFileManager *_configFileMan;
74 
75 	static Ultima8Engine *_instance;
76 
77 	Std::list<ObjId> _textModes;      //!< Gumps that want text mode
78 	bool _fontOverride;
79 	bool _fontAntialiasing;
80 	// Audio Mixer
81 	AudioMixer *_audioMixer;
82 	uint32 _saveCount;
83 
84 	// full system
85 	Game *_game;
86 	Std::string _errorMessage;
87 	Std::string _errorTitle;
88 
89 	Kernel *_kernel;
90 	ObjectManager *_objectManager;
91 	UCMachine *_ucMachine;
92 	RenderSurface *_screen;
93 	Mouse *_mouse;
94 	PaletteManager *_paletteManager;
95 	GameData *_gameData;
96 	World *_world;
97 	FontManager *_fontManager;
98 
99 	Gump *_desktopGump;
100 	GameMapGump *_gameMapGump;
101 	InverterGump *_inverterGump;
102 	AvatarMoverProcess *_avatarMoverProcess;
103 
104 	// Various dependancy flags
105 	// Timing stuff
106 	int32 _lerpFactor;       //!< Interpolation factor for this frame (0-256)
107 	bool _inBetweenFrame;    //!< Set true if we are doing an inbetween frame
108 
109 	bool _highRes;			 //!< Set to true to enable larger screen size
110 	bool _frameSkip;         //!< Set to true to enable frame skipping (default false)
111 	bool _frameLimit;        //!< Set to true to enable frame limiting (default true)
112 	bool _interpolate;       //!< Set to true to enable interpolation (default true)
113 	int32 _animationRate;    //!< The animation rate, frames per second in "fast" ticks (3000 per second). Affects all processes! (default 100 = 30 fps)
114 
115 	// Sort of Camera Related Stuff, move somewhere else
116 
117 	bool _avatarInStasis;    //!< If this is set to true, Avatar can't move,
118 	//!< nor can Avatar start more usecode
119 	bool _paintEditorItems;  //!< If true, paint items with the SI_EDITOR flag
120 	bool _showTouching;          //!< If true, highlight items touching Avatar
121 	int32 _timeOffset;
122 	bool _hasCheated;
123 	bool _cheatsEnabled;
124 	unsigned int _inversion;
125 	bool _unkCrusaderFlag; //!< not sure what this is but it's only used in usecode for crusader, so just keep track of it..
126 	uint32 _moveKeyFrame; //!< An imperfect way for the Crusader usecode to stop remote camera viewing.
127 	bool _cruStasis; //!< A slightly different kind of stasis for Crusader that stops some keyboard events
128 private:
129 	/**
130 	 * Does engine deinitialization
131 	 */
132 	void deinitialize() override;
133 
134 	/**
135 	 * Shows the Pentagram splash screen
136 	 */
137 	void showSplashScreen();
138 
139 private:
140 	//! write savegame info (time, ..., game-specifics)
141 	void writeSaveInfo(Common::WriteStream *ws);
142 
143 	//! save CoreApp/Ultima8Engine data
144 	void save(Common::WriteStream *ws);
145 
146 	//! load CoreApp/Ultima8Engine data
147 	bool load(Common::ReadStream *rs, uint32 version);
148 
149 	//! reset engine (including World, UCMachine, a.o.)
150 	void resetEngine();
151 
152 	//! create core gumps (DesktopGump, GameMapGump, ConsoleGump, ...)
153 	void setupCoreGumps();
154 
155 	//! Does a Full reset of the Engine (including shutting down Video)
156 //	void fullReset();
157 
158 	// called depending upon command line arguments
159 	void GraphicSysInit(); // starts/restarts the graphics subsystem
160 
161 	void handleDelayedEvents();
162 
163 	//! Fill a GameInfo struct for the give game name
164 	//! \param game The id of the game to check (from pentagram.cfg)
165 	//! \param gameinfo The GameInfo struct to fill
166 	//! \return true if detected all the fields, false if detection failed
167 	bool getGameInfo(const istring &game, GameInfo *gameinfo);
168 
169 protected:
170 	// Engine APIs
171 	Common::Error run() override;
172 
173 	bool initialize() override;
174 
175 	void pauseEngineIntern(bool pause) override;
176 
177 	/**
178 	 * Returns the data archive folder and version that's required
179 	 */
180 	bool isDataRequired(Common::String &folder, int &majorVersion, int &minorVersion) override;
181 
182 public:
183 	Ultima8Engine(OSystem *syst, const Ultima::UltimaGameDescription *gameDesc);
184 	~Ultima8Engine() override;
185 
get_instance()186 	static Ultima8Engine *get_instance() {
187 		return _instance;
188 	}
189 
190 	bool hasFeature(EngineFeature f) const override;
191 
192 	bool startup();
193 	void shutdown();
194 
195 	bool setupGame();
196 	bool startupGame();
197 	void shutdownGame(bool reloading = true);
198 
199 	void changeVideoMode(int width, int height);
200 
201 	//! Get current GameInfo struct
getGameInfo()202 	const GameInfo *getGameInfo() const {
203 		return _gameInfo;
204 	}
205 
getRenderScreen()206 	RenderSurface *getRenderScreen() {
207 		return _screen;
208 	}
209 
210 	Graphics::Screen *getScreen() const override;
211 
212 	bool runGame();
213 	virtual void handleEvent(const Common::Event &event);
214 
215 	void paint();
216 
217 	static const int U8_DEFAULT_SCREEN_WIDTH = 320;
218 	static const int U8_DEFAULT_SCREEN_HEIGHT = 200;
219 	static const int CRUSADER_DEFAULT_SCREEN_WIDTH = 640;
220 	static const int CRUSADER_DEFAULT_SCREEN_HEIGHT = 480;
221 
222 	static const int U8_HIRES_SCREEN_WIDTH = 640;
223 	static const int U8_HIRES_SCREEN_HEIGHT = 400;
224 	static const int CRUSADER_HIRES_SCREEN_WIDTH = 1024;
225 	static const int CRUSADER_HIRES_SCREEN_HEIGHT = 768;
226 
227 	INTRINSIC(I_getCurrentTimerTick);
228 	INTRINSIC(I_setAvatarInStasis);
229 	INTRINSIC(I_getAvatarInStasis);
230 	INTRINSIC(I_getTimeInGameHours);
231 	INTRINSIC(I_getTimeInMinutes);
232 	INTRINSIC(I_getTimeInSeconds);
233 	INTRINSIC(I_setTimeInGameHours);
234 	INTRINSIC(I_avatarCanCheat);
235 	INTRINSIC(I_getUnkCrusaderFlag);
236 	INTRINSIC(I_setUnkCrusaderFlag);
237 	INTRINSIC(I_clrUnkCrusaderFlag);
238 	INTRINSIC(I_makeAvatarACheater);
239 	INTRINSIC(I_closeItemGumps);
240 	INTRINSIC(I_setCruStasis);
241 	INTRINSIC(I_clrCruStasis);
242 	INTRINSIC(I_moveKeyDownRecently);
243 
setAvatarInStasis(bool stat)244 	void setAvatarInStasis(bool stat) {
245 		_avatarInStasis = stat;
246 	}
isAvatarInStasis()247 	bool isAvatarInStasis() const {
248 		return _avatarInStasis;
249 	}
toggleAvatarInStasis()250 	void toggleAvatarInStasis() {
251 		_avatarInStasis = !_avatarInStasis;
252 	}
isPaintEditorItems()253 	bool isPaintEditorItems() const {
254 		return _paintEditorItems;
255 	}
togglePaintEditorItems()256 	void togglePaintEditorItems() {
257 		_paintEditorItems = !_paintEditorItems;
258 	}
isShowTouchingItems()259 	bool isShowTouchingItems() const {
260 		return _showTouching;
261 	}
toggleShowTouchingItems()262 	void toggleShowTouchingItems() {
263 		_showTouching = !_showTouching;
264 	}
265 
isUnkCrusaderFlag()266 	bool isUnkCrusaderFlag() const {
267 		return _unkCrusaderFlag;
268 	}
setUnkCrusaderFlag(bool flag)269 	void setUnkCrusaderFlag(bool flag) {
270 		_unkCrusaderFlag = flag;
271 	}
setCruStasis(bool flag)272 	void setCruStasis(bool flag) {
273 		_cruStasis = flag;
274 	}
isCruStasis()275 	bool isCruStasis() const {
276 		return _cruStasis;
277 	}
278 
279 	void moveKeyEvent();
280 	bool moveKeyDownRecently();
281 
282 	uint32 getGameTimeInSeconds();
283 
getGameMapGump()284 	GameMapGump *getGameMapGump() {
285 		return _gameMapGump;
286 	}
getDesktopGump()287 	Gump *getDesktopGump() {
288 		return _desktopGump;
289 	}
290 	Gump *getGump(uint16 gumpid);
291 
292 	//! add a gump to the right core gump (such as desktopgump)
293 	//! \param gump the gump to be added
294 	void addGump(Gump *gump);
295 
getAvatarMoverProcess()296 	AvatarMoverProcess *getAvatarMoverProcess() {
297 		return _avatarMoverProcess;
298 	}
299 
300 	/**
301 	 * Notifies the engine that the sound settings may have changed
302 	 */
303 	void syncSoundSettings() override;
304 
305 	/**
306 	* Notifies the engine that the game settings may have changed
307 	*/
308 	void applyGameSettings() override;
309 
310 	/**
311 	* Opens the config dialog and apply setting after close
312 	*/
313 	void openConfigDialog();
314 
315 	/**
316 	 * Returns true if a savegame can be loaded
317 	 */
318 	bool canLoadGameStateCurrently(bool isAutosave = false) override { return true; }
319 
320 	/**
321 	 * Returns true if the game can be saved
322 	 */
323 	bool canSaveGameStateCurrently(bool isAutosave = false) override;
324 
325 	/**
326 	 * Load a game
327 	 */
328 	Common::Error loadGameState(int slot) override;
329 
330 	/**
331 	 * Saves the game
332 	 */
333 	Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
334 
335 	/**
336 	 * Load a game state
337 	 */
338 	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
339 
340 	/**
341 	 * Handles saving savegame state to a stream
342 	 */
343 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave) override;
344 
345 	//! save a game
346 	//! \param filename the file to save to
347 	//! \return true if succesful
348 	bool saveGame(int slot, const Std::string &desc);
349 
350 	//! start a new game
351 	//! \return true if succesful.
352 	bool newGame(int saveSlot = -1);
353 
354 	//! Enter gump text mode (aka Unicode keyhandling)
355 	void enterTextMode(Gump *);
356 
357 	//! Leave gump text mode (aka Unicode keyhandling)
358 	void leaveTextMode(Gump *);
359 
360 	//! Display an error message box
361 	//! \param message The message to display on the box
362 	void Error(Std::string message, Std::string title = Std::string());
363 public:
getInversion()364 	unsigned int getInversion() const {
365 		return _inversion;
366 	}
setInversion(unsigned int i)367 	void setInversion(unsigned int i) {
368 		_inversion = i & 0xFFFF;
369 	}
isInverted()370 	bool isInverted() {
371 		return (_inversion >= 0x4000 && _inversion < 0xC000);
372 	}
373 public:
areCheatsEnabled()374 	bool areCheatsEnabled() const {
375 		return _cheatsEnabled;
376 	}
setCheatMode(bool enabled)377 	void setCheatMode(bool enabled) {
378 		_cheatsEnabled = enabled;
379 	}
hasCheated()380 	bool hasCheated() const {
381 		return _hasCheated;
382 	}
makeCheater()383 	void makeCheater() {
384 		_hasCheated = true;
385 	}
386 	Gump *getMenuGump() const;
387 
isInterpolationEnabled()388 	bool isInterpolationEnabled() const {
389 		return _interpolate;
390 	}
391 };
392 
393 } // End of namespace Ultima8
394 } // End of namespace Ultima
395 
396 #endif
397