/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #include "common/system.h" #include "common/config-manager.h" #include "engines/advancedDetector.h" #include "sci/sci.h" #include "sci/debug.h" #include "sci/console.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual #include "sci/gui32/gui32.h" #include "sci/gui/gui_palette.h" #include "sci/gui/gui_cursor.h" #include "sci/gui/gui_screen.h" #include "sci/gfx/gfx_resource.h" #include "sci/gfx/gfx_tools.h" namespace Sci { class GfxDriver; SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc), _system(syst) { _console = NULL; // Set up the engine specific debug levels Common::addDebugChannel(kDebugLevelError, "Error", "Script error debugging"); Common::addDebugChannel(kDebugLevelNodes, "Lists", "Lists and nodes debugging"); Common::addDebugChannel(kDebugLevelGraphics, "Graphics", "Graphics debugging"); Common::addDebugChannel(kDebugLevelStrings, "Strings", "Strings debugging"); Common::addDebugChannel(kDebugLevelMemory, "Memory", "Memory debugging"); Common::addDebugChannel(kDebugLevelFuncCheck, "Func", "Function parameter debugging"); Common::addDebugChannel(kDebugLevelBresen, "Bresenham", "Bresenham algorithms debugging"); Common::addDebugChannel(kDebugLevelSound, "Sound", "Sound debugging"); Common::addDebugChannel(kDebugLevelGfxDriver, "Gfxdriver", "Gfx driver debugging"); Common::addDebugChannel(kDebugLevelBaseSetter, "Base", "Base Setter debugging"); Common::addDebugChannel(kDebugLevelParser, "Parser", "Parser debugging"); Common::addDebugChannel(kDebugLevelMenu, "Menu", "Menu handling debugging"); Common::addDebugChannel(kDebugLevelSaid, "Said", "Said specs debugging"); Common::addDebugChannel(kDebugLevelFile, "File", "File I/O debugging"); Common::addDebugChannel(kDebugLevelTime, "Time", "Time debugging"); Common::addDebugChannel(kDebugLevelRoom, "Room", "Room number debugging"); Common::addDebugChannel(kDebugLevelAvoidPath, "Pathfinding", "Pathfinding debugging"); Common::addDebugChannel(kDebugLevelDclInflate, "DCL", "DCL inflate debugging"); Common::addDebugChannel(kDebugLevelVM, "VM", "VM debugging"); Common::addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); Common::addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); Common::addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging"); _gamestate = 0; SearchMan.addSubDirectoryMatching(_gameDataDir, "seq"); // KQ6 SEQ directory } SciEngine::~SciEngine() { // Remove all of our debug levels here Common::clearAllDebugChannels(); delete _kernel; delete _vocabulary; delete _console; delete _resMan; } Common::Error SciEngine::run() { initGraphics(320, 200, false); // Create debugger console. It requires GFX to be initialized _console = new Console(this); /* bool end = false; Common::EventManager *em = _system->getEventManager(); while (!end) { Common::Event ev; if (em->pollEvent(ev)) { if (ev.type == Common::EVENT_KEYDOWN) { end = true; } } _system->delayMillis(10); } */ // FIXME/TODO: Move some of the stuff below to init() _resMan = new ResourceManager(); if (!_resMan) { warning("No resources found, aborting"); return Common::kNoGameDataFoundError; } _kernel = new Kernel(_resMan); _vocabulary = new Vocabulary(_resMan); SciGuiScreen *screen = new SciGuiScreen(); SciGuiPalette *palette = new SciGuiPalette(_resMan, screen); SciGuiCursor *cursor = new SciGuiCursor(_resMan, palette); // We'll set the GUI below _gamestate = new EngineState(_resMan, _kernel, _vocabulary, NULL, cursor); if (script_init_engine(_gamestate)) return Common::kUnknownError; // Gui change //_gamestate->_gui = new SciGui(_gamestate, screen, palette, cursor); // new _gamestate->_gui = new SciGui32(_gamestate, screen, palette, cursor); // old if (game_init(_gamestate)) { /* Initialize */ warning("Game initialization failed: Aborting..."); // TODO: Add an "init failed" error? return Common::kUnknownError; } script_adjust_opcode_formats(_gamestate); // Set the savegame dir (actually, we set it to a fake value, // since we cannot let the game control where saves are stored) strcpy(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value, "/"); GfxState gfx_state; _gamestate->gfx_state = &gfx_state; // Assign default values to the config manager, in case settings are missing ConfMan.registerDefault("dither_mode", "0"); // Default config: gfx_options_t gfx_options; #ifdef CUSTOM_GRAPHICS_OPTIONS gfx_options.pic0_unscaled = 1; gfx_options.pic0_dither_mode = (DitherMode)ConfMan.getInt("dither_mode"); gfx_options.pic0_brush_mode = GFX_BRUSH_MODE_RANDOM_ELLIPSES; gfx_options.pic0_line_mode = GFX_LINE_MODE_CORRECT; for (int i = 0; i < GFX_RESOURCE_TYPES_NR; i++) { gfx_options.res_conf.assign[i] = NULL; gfx_options.res_conf.mod[i] = NULL; } gfx_options.workarounds = 0; // Default config ends #endif gfxop_init(&gfx_state, &gfx_options, _resMan, screen, palette, 1); if (game_init_graphics(_gamestate)) { // Init interpreter graphics warning("Game initialization failed: Error in GFX subsystem. Aborting..."); return Common::kUnknownError; } if (game_init_sound(_gamestate, 0)) { warning("Game initialization failed: Error in sound subsystem. Aborting..."); return Common::kUnknownError; } _gamestate->_gui->init(_gamestate->usesOldGfxFunctions()); debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str()); game_run(&_gamestate); // Run the game game_exit(_gamestate); script_free_engine(_gamestate); // Uninitialize game state script_free_breakpoints(_gamestate); delete cursor; delete palette; delete screen; delete _gamestate; gfxop_exit(&gfx_state); return Common::kNoError; } // Invoked by error() when a severe error occurs GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { ExecStack *xs = &(_gamestate->_executionStack.back()); xs->addr.pc.offset = g_debugState.old_pc_offset; xs->sp = g_debugState.old_sp; } g_debugState.runningStep = 0; // Stop multiple execution g_debugState.seeking = kDebugSeekNothing; // Stop special seeks return _console; } // Used to obtain the engine's console in order to print messages to it Console *SciEngine::getSciDebugger() { return _console; } const char* SciEngine::getGameID() const { return _gameDescription->gameid; } Common::Language SciEngine::getLanguage() const { return _gameDescription->language; } Common::Platform SciEngine::getPlatform() const { return _gameDescription->platform; } uint32 SciEngine::getFlags() const { return _gameDescription->flags; } Common::String SciEngine::getSavegameName(int nr) const { return _targetName + Common::String::printf(".%03d", nr); } Common::String SciEngine::getSavegamePattern() const { return _targetName + ".???"; } Common::String SciEngine::wrapFilename(const Common::String &name) const { return _targetName + "-" + name; } Common::String SciEngine::unwrapFilename(const Common::String &name) const { Common::String prefix = name + "-"; if (name.hasPrefix(prefix.c_str())) return Common::String(name.c_str() + prefix.size()); return name; } void SciEngine::pauseEngineIntern(bool pause) { _gamestate->_sound.sfx_suspend(pause); _mixer->pauseAll(pause); } } // End of namespace Sci