diff options
Diffstat (limited to 'engines/sci/sci.cpp')
| -rw-r--r-- | engines/sci/sci.cpp | 467 | 
1 files changed, 324 insertions, 143 deletions
| diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 929bdf3307..d0c578bd45 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -26,6 +26,8 @@  #include "common/system.h"  #include "common/config-manager.h"  #include "common/debug-channels.h" +#include "common/EventRecorder.h" +#include "common/file.h"	// for Common::File::exists()  #include "engines/advancedDetector.h"  #include "engines/util.h" @@ -36,22 +38,33 @@  #include "sci/event.h"  #include "sci/engine/features.h" +#include "sci/engine/message.h"  #include "sci/engine/state.h"  #include "sci/engine/kernel.h"  #include "sci/engine/script.h"	// for script_adjust_opcode_formats +#include "sci/engine/selector.h"	// for SELECTOR  #include "sci/sound/audio.h"  #include "sci/sound/soundcmd.h" -#include "sci/graphics/gui.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls.h" +#include "sci/graphics/coordadjuster.h" +#include "sci/graphics/cursor.h"  #include "sci/graphics/maciconbar.h" +#include "sci/graphics/menu.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/paint32.h" +#include "sci/graphics/picture.h"  #include "sci/graphics/ports.h"  #include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h"  #include "sci/graphics/screen.h" -#include "sci/graphics/cache.h" +#include "sci/graphics/text16.h" +#include "sci/graphics/transitions.h"  #ifdef ENABLE_SCI32 -#include "sci/graphics/gui32.h" +#include "sci/graphics/frameout.h"  #endif  namespace Sci { @@ -61,13 +74,23 @@ SciEngine *g_sci = 0;  class GfxDriver; -SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) -		: Engine(syst), _gameDescription(desc), _system(syst) { -	_console = NULL; +SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId) +		: Engine(syst), _gameDescription(desc), _gameId(gameId) {  	assert(g_sci == 0);  	g_sci = this; + +	_gfxMacIconBar = 0; + +	_audio = 0;  	_features = 0; +	_resMan = 0; +	_gamestate = 0; +	_kernel = 0; +	_vocabulary = 0; +	_vocabularyLanguage = 1; // we load english vocabulary on startup +	_eventMan = 0; +	_console = 0;  	// Set up the engine specific debug levels  	DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging"); @@ -78,10 +101,8 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)  	DebugMan.addDebugChannel(kDebugLevelFuncCheck, "Func", "Function parameter debugging");  	DebugMan.addDebugChannel(kDebugLevelBresen, "Bresenham", "Bresenham algorithms debugging");  	DebugMan.addDebugChannel(kDebugLevelSound, "Sound", "Sound debugging"); -	DebugMan.addDebugChannel(kDebugLevelGfxDriver, "Gfxdriver", "Gfx driver debugging");  	DebugMan.addDebugChannel(kDebugLevelBaseSetter, "Base", "Base Setter debugging");  	DebugMan.addDebugChannel(kDebugLevelParser, "Parser", "Parser debugging"); -	DebugMan.addDebugChannel(kDebugLevelMenu, "Menu", "Menu handling debugging");  	DebugMan.addDebugChannel(kDebugLevelSaid, "Said", "Said specs debugging");  	DebugMan.addDebugChannel(kDebugLevelFile, "File", "File I/O debugging");  	DebugMan.addDebugChannel(kDebugLevelTime, "Time", "Time debugging"); @@ -91,26 +112,28 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)  	DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging");  	DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded");  	DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); -	DebugMan.addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging");  	DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging");  	DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); -	_gamestate = 0; -	_gfxMacIconBar = 0; -  	const Common::FSNode gameDataDir(ConfMan.get("path"));  	SearchMan.addSubDirectoryMatching(gameDataDir, "actors");	// KQ6 hi-res portraits  	SearchMan.addSubDirectoryMatching(gameDataDir, "aud");	// resource.aud and audio files -	SearchMan.addSubDirectoryMatching(gameDataDir, "avi");	// AVI movie files for Windows versions -	SearchMan.addSubDirectoryMatching(gameDataDir, "seq");	// SEQ movie files for DOS versions +	SearchMan.addSubDirectoryMatching(gameDataDir, "audio");// resource.aud and audio files +	SearchMan.addSubDirectoryMatching(gameDataDir, "audiosfx");// resource.aud and audio files  	SearchMan.addSubDirectoryMatching(gameDataDir, "wav");	// speech files in WAV format  	SearchMan.addSubDirectoryMatching(gameDataDir, "sfx");	// music/sound files in WAV format -	SearchMan.addSubDirectoryMatching(gameDataDir, "robot");	// robot files +	SearchMan.addSubDirectoryMatching(gameDataDir, "avi");	// AVI movie files for Windows versions +	SearchMan.addSubDirectoryMatching(gameDataDir, "seq");	// SEQ movie files for DOS versions +	SearchMan.addSubDirectoryMatching(gameDataDir, "robot");	// robot movie files +	SearchMan.addSubDirectoryMatching(gameDataDir, "robots");	// robot movie files +	SearchMan.addSubDirectoryMatching(gameDataDir, "movie");	// vmd movie files +	SearchMan.addSubDirectoryMatching(gameDataDir, "movies");	// vmd movie files +	SearchMan.addSubDirectoryMatching(gameDataDir, "vmd");	// vmd movie files  	// Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD  	// is for the demo of Phantasmagoria, included in the disk -	if (strcmp(getGameID(), "kq6")) +	if (_gameId != GID_KQ6)  		SearchMan.addSubDirectoryMatching(gameDataDir, "patches");	// resource patches  } @@ -118,183 +141,349 @@ SciEngine::~SciEngine() {  	// Remove all of our debug levels here  	DebugMan.clearAllDebugChannels(); +#ifdef ENABLE_SCI32 +	delete _gfxFrameout; +#endif +	delete _gfxMenu; +	delete _gfxControls; +	delete _gfxText16; +	delete _gfxAnimate; +	delete _gfxPaint; +	delete _gfxTransitions; +	delete _gfxCompare; +	delete _gfxCoordAdjuster; +	delete _gfxPorts; +	delete _gfxCache; +	delete _gfxPalette; +	delete _gfxCursor; +	delete _gfxScreen; +  	delete _audio; +	delete _soundCmd;  	delete _kernel;  	delete _vocabulary;  	delete _console; -	delete _resMan;  	delete _features;  	delete _gfxMacIconBar; +	delete _eventMan; +	delete _gamestate->_segMan; +	delete _gamestate; +	delete _resMan;	// should be deleted last  	g_sci = 0;  }  Common::Error SciEngine::run() { +	g_eventRec.registerRandomSource(_rng, "sci"); +  	// Assign default values to the config manager, in case settings are missing  	ConfMan.registerDefault("undither", "true");  	ConfMan.registerDefault("enable_fb01", "false");  	_resMan = new ResourceManager(); +	assert(_resMan); +	_resMan->addAppropriateSources(); +	_resMan->init(); +	// TODO: Add error handling. Check return values of addAppropriateSources +	// and init. We first have to *add* sensible return values, though ;). +/*  	if (!_resMan) {  		warning("No resources found, aborting");  		return Common::kNoGameDataFoundError;  	} +*/ + +	// Reset, so that error()s before SoundCommandParser is initialized wont cause a crash +	_soundCmd = NULL; + +	// Add the after market GM patches for the specified game, if they exist +	_resMan->addNewGMPatch(_gameId); +	_gameObj = _resMan->findGameObject();  	SegManager *segMan = new SegManager(_resMan); -	// Scale the screen, if needed -	int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; +	// Initialize the game screen +	_gfxScreen = new GfxScreen(_resMan); +	_gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); -	// King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as -	//  gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit -	//  it to platform windows. -	if (getPlatform() == Common::kPlatformWindows) { -		if (!strcmp(getGameID(), "kq6")) -			upscaledHires = GFX_SCREEN_UPSCALED_640x440; -#ifdef ENABLE_SCI32 -		if (!strcmp(getGameID(), "gk1")) -			upscaledHires = GFX_SCREEN_UPSCALED_640x480; -#endif +	// Create debugger console. It requires GFX to be initialized +	_console = new Console(this); +	_kernel = new Kernel(_resMan, segMan); +	_features = new GameFeatures(segMan, _kernel); +	// Only SCI0 and SCI01 games used a parser +	_vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan, false) : NULL; +	_audio = new AudioPlayer(_resMan); +	_gamestate = new EngineState(segMan); +	_eventMan = new EventManager(_resMan->detectFontExtended()); + +	// The game needs to be initialized before the graphics system is initialized, as +	// the graphics code checks parts of the seg manager upon initialization (e.g. for +	// the presence of the fastCast object) +	if (!initGame()) { /* Initialize */ +		warning("Game initialization failed: Aborting..."); +		// TODO: Add an "init failed" error? +		return Common::kUnknownError;  	} -	// Japanese versions of games use hi-res font on upscaled version of the game -	if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) -		upscaledHires = GFX_SCREEN_UPSCALED_640x400; +	script_adjust_opcode_formats(); -	// Initialize graphics-related parts -	GfxScreen *screen = 0; +	// Must be called after game_init(), as they use _features +	_kernel->loadKernelNames(_features); +	_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType()); -	// invokes initGraphics() -	if (_resMan->detectHires()) -		screen = new GfxScreen(_resMan, 640, 480); -	else -		screen = new GfxScreen(_resMan, 320, 200, upscaledHires); +	syncSoundSettings(); -	if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) -		_gfxMacIconBar = new GfxMacIconBar(); +	// Initialize all graphics related subsystems +	initGraphics(); -	GfxPalette *palette = new GfxPalette(_resMan, screen); -	GfxCache *cache = new GfxCache(_resMan, screen, palette); -	GfxCursor *cursor = new GfxCursor(_resMan, palette, screen); +	debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); -	// Create debugger console. It requires GFX to be initialized -	_console = new Console(this); +	if (_gameDescription->flags & ADGF_ADDENGLISH) { +		// if game is multilingual +		Common::Language selectedLanguage = Common::parseLanguage(ConfMan.get("language")); +		if (selectedLanguage == Common::EN_ANY) { +			// and english was selected as language +			if (SELECTOR(printLang) != -1) // set text language to english +				writeSelectorValue(segMan, _gameObj, SELECTOR(printLang), 1); +			if (SELECTOR(parseLang) != -1) // and set parser language to english as well +				writeSelectorValue(segMan, _gameObj, SELECTOR(parseLang), 1); +		} +	} -	_kernel = new Kernel(_resMan, segMan); -	// Only SCI0 and SCI01 games used a parser -	_vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; -	_audio = new AudioPlayer(_resMan); +	// Check whether loading a savestate was requested +	int saveSlot = ConfMan.getInt("save_slot"); +	if (saveSlot >= 0) { +		reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) };	// special call (argv[0] is NULL) +		kRestoreGame(_gamestate, 2, restoreArgv); + +		// TODO: The best way to do the following would be to invoke Game::init +		// here and stop when the room is about to be changed, otherwise some +		// game initialization won't take place + +		// Set audio language for KQ5CD (bug #3039477) +		if (g_sci->getGameId() == GID_KQ5 && Common::File::exists("AUDIO001.002")) { +			reg_t doAudioArgv[2] = { make_reg(0, 9), make_reg(0, 1) }; +			kDoAudio(_gamestate, 2, doAudioArgv); +		} + +		// Initialize the game menu, if there is one. +		// This is not done when loading, so we must do it manually. +		reg_t menuBarObj = _gamestate->_segMan->findObjectByName("MenuBar"); +		if (menuBarObj.isNull()) +			menuBarObj = _gamestate->_segMan->findObjectByName("TheMenuBar");	// LSL2 +		if (menuBarObj.isNull()) +			menuBarObj = _gamestate->_segMan->findObjectByName("menuBar");	// LSL6 +		if (!menuBarObj.isNull()) { +			// Reset abortScriptProcessing before initializing the game menu, so that the +			// VM call performed by invokeSelector will actually run. +			_gamestate->abortScriptProcessing = kAbortNone; +			Object *menuBar = _gamestate->_segMan->getObject(menuBarObj); +			// Invoke the first method (init) of the menuBar object +			invokeSelector(_gamestate, menuBarObj, menuBar->getFuncSelector(0), 0, _gamestate->stack_base); +			_gamestate->abortScriptProcessing = kAbortLoadGame; +		} +	} -	_features = new GameFeatures(segMan, _kernel); +	runGame(); -	_gamestate = new EngineState(segMan); +	ConfMan.flushToDisk(); -	_gamestate->_event = new SciEvent(_resMan); +	return Common::kNoError; +} -	if (script_init_engine(_gamestate)) -		return Common::kUnknownError; +bool SciEngine::initGame() { +	// Script 0 needs to be allocated here before anything else! +	int script0Segment = _gamestate->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); +	DataStack *stack = _gamestate->_segMan->allocateStack(VM_STACK_SIZE, NULL); -#ifdef ENABLE_SCI32 -	if (getSciVersion() >= SCI_VERSION_2) { -		_gfxAnimate = 0; -		_gfxControls = 0; -		_gfxMenu = 0; -		_gfxPaint16 = 0; -		_gfxPorts = 0; -		_gui = 0; -		_gui32 = new SciGui32(_gamestate->_segMan, _gamestate->_event, screen, palette, cache, cursor); -	} else { -#endif -		_gfxPorts = new GfxPorts(segMan, screen); -		_gui = new SciGui(_gamestate, screen, palette, cache, cursor, _gfxPorts, _audio); -#ifdef ENABLE_SCI32 -		_gui32 = 0; -		_gfxFrameout = 0; +	_gamestate->_msgState = new MessageState(_gamestate->_segMan); +	_gamestate->gcCountDown = GC_INTERVAL - 1; + +	// Script 0 should always be at segment 1 +	if (script0Segment != 1) { +		debug(2, "Failed to instantiate script.000"); +		return false;  	} -#endif -	_gfxPalette = palette; -	_gfxScreen = screen; -	_gfxCache = cache; -	_gfxCursor = cursor; +	_gamestate->initGlobals(); +	_gamestate->_segMan->initSysStrings(); -	if (game_init(_gamestate)) { /* Initialize */ -		warning("Game initialization failed: Aborting..."); -		// TODO: Add an "init failed" error? -		return Common::kUnknownError; +	_gamestate->r_acc = _gamestate->r_prev = NULL_REG; + +	_gamestate->_executionStack.clear();    // Start without any execution stack +	_gamestate->executionStackBase = -1; // No vm is running yet +	_gamestate->_executionStackPosChanged = false; + +	_gamestate->abortScriptProcessing = kAbortNone; +	_gamestate->gameIsRestarting = GAMEISRESTARTING_NONE; + +	_gamestate->stack_base = stack->_entries; +	_gamestate->stack_top = stack->_entries + stack->_capacity; + +	if (!_gamestate->_segMan->instantiateScript(0)) { +		error("initGame(): Could not instantiate script 0"); +		return false;  	} -	// Add the after market GM patches for the specified game, if they exist -	_resMan->addNewGMPatch(getGameID()); +	// Reset parser +	if (_vocabulary) { +		_vocabulary->reset(); +	} -	script_adjust_opcode_formats(_gamestate); -	_kernel->loadKernelNames(getGameID()); +	_gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis(); -	SciVersion soundVersion = _features->detectDoSoundType(); +	// Load game language into printLang property of game object +	setSciLanguage(); -	_gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); +	return true; +} -	screen->debugUnditherSetState(ConfMan.getBool("undither")); +void SciEngine::initGraphics() { -#ifdef USE_OLD_MUSIC_FUNCTIONS -	if (game_init_sound(_gamestate, 0, soundVersion)) { -		warning("Game initialization failed: Error in sound subsystem. Aborting..."); -		return Common::kUnknownError; -	} +	// Reset all graphics objects +	_gfxAnimate = 0; +	_gfxCache = 0; +	_gfxCompare = 0; +	_gfxControls = 0; +	_gfxCoordAdjuster = 0; +	_gfxCursor = 0; +	_gfxMacIconBar = 0; +	_gfxMenu = 0; +	_gfxPaint = 0; +	_gfxPaint16 = 0; +	_gfxPalette = 0; +	_gfxPorts = 0; +	_gfxText16 = 0; +	_gfxTransitions = 0; +#ifdef ENABLE_SCI32 +	_gfxFrameout = 0; +	_gfxPaint32 = 0;  #endif -	syncSoundSettings(); +	if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) +		_gfxMacIconBar = new GfxMacIconBar(); + +	bool paletteMerging = true; +	if (getSciVersion() >= SCI_VERSION_1_1) { +		// there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying +		if (getSciVersion() == SCI_VERSION_1_1) +			paletteMerging = _resMan->detectForPaletteMergingForSci11(); +		else +			paletteMerging = false; +	} + +	_gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging); +	_gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); +	_gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen);  #ifdef ENABLE_SCI32 -	if (_gui32) -		_gui32->init(); -	else +	if (getSciVersion() >= SCI_VERSION_2) { +		// SCI32 graphic objects creation +		_gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan); +		_gfxCursor->init(_gfxCoordAdjuster, _eventMan); +		_gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); +		_gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); +		_gfxPaint = _gfxPaint32; +		_gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); +	} else { +#endif +		// SCI0-SCI1.1 graphic objects creation +		_gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen); +		_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); +		_gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); +		_gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); +		_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); +		_gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); +		_gfxPaint = _gfxPaint16; +		_gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); +		_gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); +		_gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); +		_gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); + +		_gfxMenu->reset(); +#ifdef ENABLE_SCI32 +	}  #endif -		_gui->init(_features->usesOldGfxFunctions()); -	debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); +	if (_gfxPorts) { +		_gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16); +		_gfxPaint16->init(_gfxAnimate, _gfxText16); +	} +	// Set default (EGA, amiga or resource 999) palette +	_gfxPalette->setDefault(); +} -	// Check whether loading a savestate was requested -	if (ConfMan.hasKey("save_slot")) { -		_gamestate->loadFromLauncher = ConfMan.getInt("save_slot"); -	} else { -		_gamestate->loadFromLauncher = -1; +void SciEngine::initStackBaseWithSelector(Selector selector) { +	_gamestate->stack_base[0] = make_reg(0, (uint16)selector); +	_gamestate->stack_base[1] = NULL_REG; + +	// Register the first element on the execution stack +	if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) { +		_console->printObject(_gameObj); +		error("initStackBaseWithSelector: error while registering the first selector in the call stack");  	} -	game_run(&_gamestate); // Run the game +} -	game_exit(_gamestate); +void SciEngine::runGame() { +	initStackBaseWithSelector(SELECTOR(play)); // Call the play selector + +	// Attach the debug console on game startup, if requested +	if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) +		_console->attach(); + +	do { +		_gamestate->_executionStackPosChanged = false; +		run_vm(_gamestate); +		exitGame(); + +		if (_gamestate->abortScriptProcessing == kAbortRestartGame) { +			_gamestate->_segMan->resetSegMan(); +			initGame(); +			initStackBaseWithSelector(SELECTOR(play)); +			_gamestate->gameIsRestarting = GAMEISRESTARTING_RESTART; +			if (_gfxMenu) +				_gfxMenu->reset(); +			_gamestate->abortScriptProcessing = kAbortNone; +		} else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { +			_gamestate->abortScriptProcessing = kAbortNone; +			_gamestate->_executionStack.clear(); +			initStackBaseWithSelector(SELECTOR(replay)); +			_gamestate->shrinkStackToBase(); +			_gamestate->abortScriptProcessing = kAbortNone; +		} else { +			break;	// exit loop +		} +	} while (true); +} -	ConfMan.flushToDisk(); +void SciEngine::exitGame() { +	if (_gamestate->abortScriptProcessing != kAbortLoadGame) { +		_gamestate->_executionStack.clear(); +		_audio->stopAllAudio(); +		g_sci->_soundCmd->clearPlayList(); +	} -	delete _gamestate->_soundCmd; -	delete _gui; -#ifdef ENABLE_SCI32 -	delete _gui32; -#endif -	delete _gfxPorts; -	delete _gfxCache; -	delete _gfxPalette; -	delete cursor; -	delete _gfxScreen; -	delete _gamestate->_event; -	delete segMan; -	delete _gamestate; +	// TODO Free parser segment here -	return Common::kNoError; +	// TODO Free scripts here + +	// Close all opened file handles +	_gamestate->_fileHandles.clear(); +	_gamestate->_fileHandles.resize(5);  }  // 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; +		xs->addr.pc.offset = _debugState.old_pc_offset; +		xs->sp = _debugState.old_sp;  	} -	g_debugState.runningStep = 0; // Stop multiple execution -	g_debugState.seeking = kDebugSeekNothing; // Stop special seeks +	_debugState.runningStep = 0; // Stop multiple execution +	_debugState.seeking = kDebugSeekNothing; // Stop special seeks  	return _console;  } @@ -304,7 +493,7 @@ Console *SciEngine::getSciDebugger() {  	return _console;  } -const char* SciEngine::getGameID() const { +const char *SciEngine::getGameIdStr() const {  	return _gameDescription->gameid;  } @@ -316,12 +505,8 @@ Common::Platform SciEngine::getPlatform() const {  	return _gameDescription->platform;  } -uint32 SciEngine::getFlags() const { -	return _gameDescription->flags; -} -  bool SciEngine::isDemo() const { -	return getFlags() & ADGF_DEMO; +	return _gameDescription->flags & ADGF_DEMO;  }  Common::String SciEngine::getSavegameName(int nr) const { @@ -333,19 +518,20 @@ Common::String SciEngine::getSavegamePattern() const {  }  Common::String SciEngine::getFilePrefix() const { -	const char* gameID = getGameID(); -	if (!strcmp(gameID, "qfg2")) { +	if (_gameId == GID_QFG2) {  		// Quest for Glory 2 wants to read files from Quest for Glory 1 (EGA/VGA) to import character data  		if (_gamestate->currentRoomNumber() == 805)  			return "qfg1";  		// TODO: Include import-room for qfg1vga -	} -	if (!strcmp(gameID, "qfg3")) { +	} else if (_gameId == GID_QFG3) {  		// Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data  		if (_gamestate->currentRoomNumber() == 54)  			return "qfg2"; +	} else if (_gameId == GID_QFG4) { +		// Quest for Glory 4 wants to read files from Quest for Glory 3 to import character data +		if (_gamestate->currentRoomNumber() == 54) +			return "qfg3";  	} -	// TODO: Implement the same for qfg4, when sci32 is good enough  	return _targetName;  } @@ -361,27 +547,22 @@ Common::String SciEngine::unwrapFilename(const Common::String &name) const {  }  void SciEngine::pauseEngineIntern(bool pause) { -#ifdef USE_OLD_MUSIC_FUNCTIONS -	_gamestate->_sound.sfx_suspend(pause); -#endif  	_mixer->pauseAll(pause);  }  void SciEngine::syncSoundSettings() {  	Engine::syncSoundSettings(); -#ifndef USE_OLD_MUSIC_FUNCTIONS  	bool mute = false;  	if (ConfMan.hasKey("mute"))  		mute = ConfMan.getBool("mute");  	int soundVolumeMusic = (mute ? 0 : ConfMan.getInt("music_volume")); -	if (_gamestate && _gamestate->_soundCmd) { +	if (_gamestate && g_sci->_soundCmd) {  		int vol =  (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume; -		_gamestate->_soundCmd->setMasterVolume(vol); +		g_sci->_soundCmd->setMasterVolume(vol);  	} -#endif  }  } // End of namespace Sci | 
