scummvm/engines/tetraedge/tetraedge.cpp

366 lines
9.8 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "tetraedge/tetraedge.h"
#include "tetraedge/detection.h"
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/system.h"
#include "common/savefile.h"
#include "engines/util.h"
#include "engines/dialogs.h"
#include "tetraedge/game/amerzone_game.h"
#include "tetraedge/game/syberia_game.h"
#include "tetraedge/game/application.h"
#include "tetraedge/game/character.h"
#include "tetraedge/te/te_core.h"
#include "tetraedge/te/te_renderer.h"
#include "tetraedge/te/te_resource_manager.h"
#include "tetraedge/te/te_lua_thread.h"
#include "tetraedge/te/te_sound_manager.h"
#include "tetraedge/te/te_input_mgr.h"
#include "tetraedge/te/te_particle.h"
namespace Tetraedge {
TetraedgeEngine *g_engine;
TetraedgeEngine::TetraedgeEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Tetraedge"), _resourceManager(nullptr),
_core(nullptr), _application(nullptr), _game(nullptr), _renderer(nullptr),
_soundManager(nullptr), _inputMgr(nullptr), _gameType(kNone) {
g_engine = this;
}
TetraedgeEngine::~TetraedgeEngine() {
//TeObject::deleteNow();
delete _core;
delete _game;
delete _application;
delete _renderer;
delete _soundManager;
delete _resourceManager;
delete _inputMgr;
Object3D::cleanup();
Character::cleanup();
TeAnimation::cleanup();
TeLuaThread::cleanup();
TeTimer::cleanup();
TeObject::cleanup();
TeParticle::cleanup();
}
/*static*/
Common::StringArray TetraedgeEngine::splitString(const Common::String &text, char c) {
Common::StringArray values;
Common::String str = text;
size_t pos;
while ((pos = str.findFirstOf(c)) != Common::String::npos) {
values.push_back(Common::String(str.c_str(), pos));
str = Common::String(str.c_str() + pos + 1);
}
values.push_back(str);
return values;
}
Application *TetraedgeEngine::getApplication() {
// created in run()
return _application;
}
TeCore *TetraedgeEngine::getCore() {
if (_core == nullptr)
_core = new TeCore();
return _core;
}
Game *TetraedgeEngine::getGame() {
if (_game == nullptr) {
if (gameIsAmerzone())
_game = new AmerzoneGame();
else
_game = new SyberiaGame();
}
return _game;
}
TeSoundManager *TetraedgeEngine::getSoundManager() {
if (_soundManager == nullptr)
_soundManager = new TeSoundManager();
return _soundManager;
}
TeRenderer *TetraedgeEngine::getRenderer() {
// created in run()
return _renderer;
}
TeResourceManager *TetraedgeEngine::getResourceManager() {
if (_resourceManager == nullptr)
_resourceManager = new TeResourceManager();
return _resourceManager;
}
TeInputMgr *TetraedgeEngine::getInputMgr() {
if (_inputMgr == nullptr)
_inputMgr = new TeInputMgr();
return _inputMgr;
}
uint32 TetraedgeEngine::getFeatures() const {
return _gameDescription->flags;
}
Common::String TetraedgeEngine::getGameId() const {
return _gameDescription->gameId;
}
Common::Language TetraedgeEngine::getGameLanguage() const {
return _gameDescription->language;
}
Common::Platform TetraedgeEngine::getGamePlatform() const {
return _gameDescription->platform;
}
bool TetraedgeEngine::isGameDemo() const {
return (_gameDescription->flags & ADGF_DEMO) != 0;
}
bool TetraedgeEngine::canLoadGameStateCurrently(Common::U32String *msg) {
return _game && _application && !_application->mainMenu().isEntered();
}
bool TetraedgeEngine::canSaveGameStateCurrently(Common::U32String *msg) {
return canSaveAutosaveCurrently() && !_application->isLockCursor();
}
bool TetraedgeEngine::canSaveAutosaveCurrently() {
if (!_game || !_application)
return false;
bool sceneLoaded;
if (gameIsAmerzone()) {
AmerzoneGame *game = dynamic_cast<AmerzoneGame *>(_game);
assert(game);
sceneLoaded = (game->warpY() != nullptr);
} else {
sceneLoaded = !_game->currentScene().empty() && !_game->currentZone().empty();
}
return _game->running() && sceneLoaded;
}
Common::Error TetraedgeEngine::loadGameState(int slot) {
// In case autosaves are on, do a save first before loading the new save
saveAutosaveIfEnabled();
Common::String saveStateName = getSaveStateName(slot);
Common::InSaveFile *saveFile = getSaveFileManager()->openForLoading(saveStateName);
if (!saveFile)
return Common::kReadingFailed;
// The game will reopen the file and do the loading, see Game::initLoadedBackupData
getGame()->setLoadName(saveStateName);
delete saveFile;
return Common::kNoError;
}
Common::Error TetraedgeEngine::loadGameStream(Common::SeekableReadStream *stream) {
Common::Serializer s(stream, nullptr);
Common::Error retval = syncGame(s);
return retval;
}
void TetraedgeEngine::closeGameDialogs() {
if (!_game)
return;
_game->closeDialogs();
}
void TetraedgeEngine::configureSearchPaths() {
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
if (_gameDescription->platform != Common::kPlatformIOS)
SearchMan.addSubDirectoryMatching(gameDataDir, "Resources", 0, 5);
}
int TetraedgeEngine::getDefaultScreenWidth() const {
return gameIsAmerzone() ? 1280 : 800;
}
int TetraedgeEngine::getDefaultScreenHeight() const {
return gameIsAmerzone() ? 800 : 600;
}
bool TetraedgeEngine::onKeyUp(const Common::KeyState &state) {
switch (state.keycode) {
case Common::KEYCODE_l:
if (loadGameDialog())
_game->initLoadedBackupData();
break;
case Common::KEYCODE_s:
saveGameDialog();
break;
case Common::KEYCODE_ESCAPE:
closeGameDialogs();
break;
default:
break;
}
return false;
}
void TetraedgeEngine::registerConfigDefaults() {
// The skips are mostly for debugging to jump straight to certain
// things. If they are all enabled you get into a new game as
// soon as possible.
ConfMan.registerDefault("skip_videos", false);
ConfMan.registerDefault("skip_splash", false);
ConfMan.registerDefault("skip_mainmenu", false);
ConfMan.registerDefault("skip_confirm", false);
ConfMan.registerDefault("disable_shadows", false);
ConfMan.registerDefault("correct_movie_aspect", true);
ConfMan.registerDefault("restore_scenes", false);
}
Common::Error TetraedgeEngine::run() {
if (getGameId() == "syberia")
_gameType = kSyberia;
else if (getGameId() == "syberia2")
_gameType = kSyberia2;
else if (getGameId() == "amerzone")
_gameType = kAmerzone;
else
error("Unknown game id %s", getGameId().c_str());
registerConfigDefaults();
configureSearchPaths();
// from BasicOpenGLView::prepareOpenGL..
_application = new Application();
_renderer = TeRenderer::makeInstance();
_renderer->init(getDefaultScreenWidth(), getDefaultScreenHeight());
_renderer->reset();
getInputMgr()->_keyUpSignal.add(this, &TetraedgeEngine::onKeyUp);
// If a savegame was selected from the launcher, load it.
// Should be before application->create() because it only
// sets the game name to load inside the Game object. It will
// actually be loaded when the application is created.
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot != -1)
(void)loadGameState(saveSlot);
_application->create();
Common::Event e;
while (!shouldQuit()) {
while (g_system->getEventManager()->pollEvent(e)) {
getInputMgr()->handleEvent(e);
}
_application->run();
g_system->delayMillis(10);
}
// Ensure game has stopped.
_game->leave(true);
TeObject::deleteNow();
_application->destroy();
return Common::kNoError;
}
Common::Error TetraedgeEngine::syncGame(Common::Serializer &s) {
return getGame()->syncGame(s);
}
void TetraedgeEngine::openConfigDialog() {
GUI::ConfigDialog dlg;
dlg.runModal();
g_system->applyBackendSettings();
applyGameSettings();
syncSoundSettings();
}
Graphics::RendererType TetraedgeEngine::preferredRendererType() const {
Common::String rendererConfig = ConfMan.get("renderer");
Graphics::RendererType desiredRendererType = Graphics::Renderer::parseTypeCode(rendererConfig);
uint32 availableRendererTypes = Graphics::Renderer::getAvailableTypes();
availableRendererTypes &=
#if defined(USE_OPENGL_GAME)
Graphics::kRendererTypeOpenGL |
#endif
#if defined(USE_OPENGL_SHADERS)
Graphics::kRendererTypeOpenGLShaders |
#endif
#if defined(USE_TINYGL)
Graphics::kRendererTypeTinyGL |
#endif
0;
Graphics::RendererType matchingRendererType = Graphics::Renderer::getBestMatchingType(desiredRendererType, availableRendererTypes);
// Currently no difference between shaders and otherwise for this engine.
if (matchingRendererType == Graphics::kRendererTypeOpenGLShaders)
matchingRendererType = Graphics::kRendererTypeOpenGL;
if (matchingRendererType == 0) {
error("No supported renderer available.");
}
return matchingRendererType;
}
Common::Error TetraedgeEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
Common::Error result = Engine::saveGameState(slot, desc, isAutosave);
if (result.getCode() == Common::kNoError) {
ConfMan.setInt("last_save_slot", slot);
ConfMan.flushToDisk();
}
return result;
}
/*static*/
void TetraedgeEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
g_engine->getApplication()->getSavegameThumbnail(thumb);
}
} // namespace Tetraedge