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