2009-02-17 15:20:21 +00:00
|
|
|
/* 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$
|
|
|
|
*
|
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#include "common/system.h"
|
|
|
|
#include "common/config-manager.h"
|
2010-05-04 11:59:22 +00:00
|
|
|
#include "common/debug-channels.h"
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 08:20:53 +00:00
|
|
|
#include "engines/advancedDetector.h"
|
2010-05-04 11:58:12 +00:00
|
|
|
#include "engines/util.h"
|
|
|
|
|
2009-02-15 11:03:21 +00:00
|
|
|
#include "sci/sci.h"
|
2009-07-03 14:22:50 +00:00
|
|
|
#include "sci/debug.h"
|
2009-02-20 21:26:31 +00:00
|
|
|
#include "sci/console.h"
|
2009-12-04 17:38:24 +00:00
|
|
|
#include "sci/event.h"
|
2009-05-11 13:31:17 +00:00
|
|
|
|
2010-02-13 17:44:58 +00:00
|
|
|
#include "sci/engine/features.h"
|
2010-06-10 07:32:05 +00:00
|
|
|
#include "sci/engine/message.h"
|
2009-02-27 02:23:40 +00:00
|
|
|
#include "sci/engine/state.h"
|
2009-02-24 05:51:55 +00:00
|
|
|
#include "sci/engine/kernel.h"
|
2010-02-02 22:52:41 +00:00
|
|
|
#include "sci/engine/script.h" // for script_adjust_opcode_formats
|
2010-06-10 09:18:57 +00:00
|
|
|
#include "sci/engine/selector.h" // for SELECTOR
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-01-05 01:22:16 +00:00
|
|
|
#include "sci/sound/audio.h"
|
|
|
|
#include "sci/sound/soundcmd.h"
|
2010-06-15 15:44:24 +00:00
|
|
|
#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"
|
2010-05-24 17:21:11 +00:00
|
|
|
#include "sci/graphics/maciconbar.h"
|
2010-06-09 21:41:20 +00:00
|
|
|
#include "sci/graphics/menu.h"
|
2010-06-15 13:34:40 +00:00
|
|
|
#include "sci/graphics/paint16.h"
|
2010-06-15 15:44:24 +00:00
|
|
|
#include "sci/graphics/paint32.h"
|
2010-01-31 12:35:15 +00:00
|
|
|
#include "sci/graphics/ports.h"
|
2010-01-05 01:37:57 +00:00
|
|
|
#include "sci/graphics/palette.h"
|
|
|
|
#include "sci/graphics/screen.h"
|
2010-06-15 15:44:24 +00:00
|
|
|
#include "sci/graphics/text16.h"
|
|
|
|
#include "sci/graphics/transitions.h"
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2010-01-29 22:02:28 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-06-15 15:44:24 +00:00
|
|
|
#include "sci/graphics/frameout.h"
|
2010-01-29 22:02:28 +00:00
|
|
|
#endif
|
|
|
|
|
2009-02-20 14:45:28 +00:00
|
|
|
namespace Sci {
|
|
|
|
|
2010-02-13 17:42:49 +00:00
|
|
|
SciEngine *g_sci = 0;
|
|
|
|
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
class GfxDriver;
|
2009-02-21 10:23:36 +00:00
|
|
|
|
2009-10-09 23:19:53 +00:00
|
|
|
SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc)
|
2009-10-03 20:49:18 +00:00
|
|
|
: Engine(syst), _gameDescription(desc), _system(syst) {
|
2009-02-20 21:26:31 +00:00
|
|
|
|
2010-02-14 12:32:25 +00:00
|
|
|
assert(g_sci == 0);
|
2010-02-13 17:42:49 +00:00
|
|
|
g_sci = this;
|
2010-06-15 12:15:52 +00:00
|
|
|
|
|
|
|
_gfxMacIconBar = 0;
|
|
|
|
|
|
|
|
_audio = 0;
|
2010-02-13 17:44:58 +00:00
|
|
|
_features = 0;
|
2010-06-15 12:15:52 +00:00
|
|
|
_resMan = 0;
|
|
|
|
_gamestate = 0;
|
|
|
|
_kernel = 0;
|
|
|
|
_vocabulary = 0;
|
|
|
|
_eventMan = 0;
|
|
|
|
_console = 0;
|
2010-02-13 17:42:49 +00:00
|
|
|
|
2009-02-17 18:16:48 +00:00
|
|
|
// Set up the engine specific debug levels
|
2010-04-27 21:40:52 +00:00
|
|
|
DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelNodes, "Lists", "Lists and nodes debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelGraphics, "Graphics", "Graphics debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelStrings, "Strings", "Strings debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelMemory, "Memory", "Memory debugging");
|
|
|
|
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");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelRoom, "Room", "Room number debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelAvoidPath, "Pathfinding", "Pathfinding debugging");
|
|
|
|
DebugMan.addDebugChannel(kDebugLevelDclInflate, "DCL", "DCL inflate debugging");
|
|
|
|
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");
|
2009-02-17 18:16:48 +00:00
|
|
|
|
2010-05-04 11:56:52 +00:00
|
|
|
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, "wav"); // speech files in WAV format
|
|
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); // music/sound files in WAV format
|
|
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot files
|
2010-02-05 03:29:04 +00:00
|
|
|
|
2010-02-05 09:02:36 +00:00
|
|
|
// 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
|
2010-02-05 07:06:43 +00:00
|
|
|
if (strcmp(getGameID(), "kq6"))
|
2010-05-04 11:56:52 +00:00
|
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "patches"); // resource patches
|
2009-02-17 18:16:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SciEngine::~SciEngine() {
|
|
|
|
// Remove all of our debug levels here
|
2010-04-27 21:40:52 +00:00
|
|
|
DebugMan.clearAllDebugChannels();
|
2009-02-20 21:26:31 +00:00
|
|
|
|
2009-11-04 09:36:18 +00:00
|
|
|
delete _audio;
|
2009-07-11 23:45:54 +00:00
|
|
|
delete _kernel;
|
|
|
|
delete _vocabulary;
|
2009-02-20 21:26:31 +00:00
|
|
|
delete _console;
|
2009-09-02 12:02:37 +00:00
|
|
|
delete _resMan;
|
2010-02-13 17:44:58 +00:00
|
|
|
delete _features;
|
2010-05-24 21:51:45 +00:00
|
|
|
delete _gfxMacIconBar;
|
2010-02-13 17:42:49 +00:00
|
|
|
|
|
|
|
g_sci = 0;
|
2009-02-17 18:16:48 +00:00
|
|
|
}
|
|
|
|
|
2009-03-01 04:42:46 +00:00
|
|
|
Common::Error SciEngine::run() {
|
2010-01-26 19:25:33 +00:00
|
|
|
// Assign default values to the config manager, in case settings are missing
|
|
|
|
ConfMan.registerDefault("undither", "true");
|
|
|
|
ConfMan.registerDefault("enable_fb01", "false");
|
|
|
|
|
2009-09-02 12:02:37 +00:00
|
|
|
_resMan = new ResourceManager();
|
2010-06-15 12:15:52 +00:00
|
|
|
assert(_resMan);
|
|
|
|
_resMan->addAppropriateSources();
|
|
|
|
_resMan->init();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-06-15 12:15:52 +00:00
|
|
|
// TODO: Add error handling. Check return values of addAppropriateSources
|
|
|
|
// and init. We first have to *add* sensible return values, though ;).
|
|
|
|
/*
|
2009-09-02 12:02:37 +00:00
|
|
|
if (!_resMan) {
|
2009-10-10 00:07:19 +00:00
|
|
|
warning("No resources found, aborting");
|
2009-02-17 18:16:48 +00:00
|
|
|
return Common::kNoGameDataFoundError;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2010-06-15 12:15:52 +00:00
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-06-09 18:42:21 +00:00
|
|
|
// Add the after market GM patches for the specified game, if they exist
|
|
|
|
_resMan->addNewGMPatch(getGameID());
|
2010-06-10 08:11:38 +00:00
|
|
|
_gameObj = _resMan->findGameObject();
|
2010-06-09 18:42:21 +00:00
|
|
|
|
2010-05-18 12:16:48 +00:00
|
|
|
SegManager *segMan = new SegManager(_resMan);
|
|
|
|
|
2009-10-31 10:54:19 +00:00
|
|
|
// Scale the screen, if needed
|
2010-05-15 14:17:50 +00:00
|
|
|
int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED;
|
2010-01-28 21:53:07 +00:00
|
|
|
|
|
|
|
// 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"))
|
2010-05-15 15:16:32 +00:00
|
|
|
upscaledHires = GFX_SCREEN_UPSCALED_640x440;
|
2010-01-28 21:59:05 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-01-28 21:53:07 +00:00
|
|
|
if (!strcmp(getGameID(), "gk1"))
|
2010-05-15 14:17:50 +00:00
|
|
|
upscaledHires = GFX_SCREEN_UPSCALED_640x480;
|
2010-01-28 21:59:05 +00:00
|
|
|
#endif
|
2010-01-28 21:53:07 +00:00
|
|
|
}
|
2009-10-31 14:38:25 +00:00
|
|
|
|
2010-01-06 18:25:43 +00:00
|
|
|
// Japanese versions of games use hi-res font on upscaled version of the game
|
|
|
|
if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1))
|
2010-05-15 14:17:50 +00:00
|
|
|
upscaledHires = GFX_SCREEN_UPSCALED_640x400;
|
2009-10-31 10:54:19 +00:00
|
|
|
|
2010-06-15 15:44:24 +00:00
|
|
|
// 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;
|
|
|
|
_gfxScreen = 0;
|
|
|
|
_gfxText16 = 0;
|
|
|
|
_gfxTransitions = 0;
|
|
|
|
#ifdef ENABLE_SCI32
|
|
|
|
_gfxFrameout = 0;
|
|
|
|
_gfxPaint32 = 0;
|
|
|
|
#endif
|
|
|
|
|
2009-10-31 10:54:19 +00:00
|
|
|
// Initialize graphics-related parts
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2010-01-28 21:59:05 +00:00
|
|
|
if (_resMan->detectHires())
|
2010-06-09 10:45:54 +00:00
|
|
|
_gfxScreen = new GfxScreen(_resMan, 640, 480);
|
2010-01-28 21:01:57 +00:00
|
|
|
else
|
2010-06-09 10:45:54 +00:00
|
|
|
_gfxScreen = new GfxScreen(_resMan, 320, 200, upscaledHires);
|
2010-01-06 12:21:27 +00:00
|
|
|
|
2010-06-09 18:42:21 +00:00
|
|
|
_gfxScreen->debugUnditherSetState(ConfMan.getBool("undither"));
|
|
|
|
|
2010-05-24 17:21:11 +00:00
|
|
|
if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
|
2010-05-24 21:47:06 +00:00
|
|
|
_gfxMacIconBar = new GfxMacIconBar();
|
2010-05-24 17:21:11 +00:00
|
|
|
|
2010-06-09 10:45:54 +00:00
|
|
|
_gfxPalette = new GfxPalette(_resMan, _gfxScreen);
|
|
|
|
_gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette);
|
|
|
|
_gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-10-31 10:54:19 +00:00
|
|
|
// Create debugger console. It requires GFX to be initialized
|
|
|
|
_console = new Console(this);
|
|
|
|
|
2010-05-18 12:16:48 +00:00
|
|
|
_kernel = new Kernel(_resMan, segMan);
|
2010-06-09 18:42:21 +00:00
|
|
|
_features = new GameFeatures(segMan, _kernel);
|
2010-01-23 19:10:56 +00:00
|
|
|
// Only SCI0 and SCI01 games used a parser
|
|
|
|
_vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL;
|
2009-11-04 09:36:18 +00:00
|
|
|
_audio = new AudioPlayer(_resMan);
|
2010-06-01 15:11:20 +00:00
|
|
|
_gamestate = new EngineState(segMan);
|
2010-06-09 07:59:42 +00:00
|
|
|
_eventMan = new EventManager(_resMan);
|
2009-10-08 08:00:30 +00:00
|
|
|
|
2010-06-09 21:41:20 +00:00
|
|
|
// 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)
|
2010-06-10 07:32:05 +00:00
|
|
|
if (!initGame()) { /* Initialize */
|
2010-06-09 21:41:20 +00:00
|
|
|
warning("Game initialization failed: Aborting...");
|
|
|
|
// TODO: Add an "init failed" error?
|
|
|
|
return Common::kUnknownError;
|
|
|
|
}
|
|
|
|
|
2010-01-29 22:02:28 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-01-29 22:56:39 +00:00
|
|
|
if (getSciVersion() >= SCI_VERSION_2) {
|
2010-06-15 15:44:24 +00:00
|
|
|
// SCI32 graphic objects creation
|
|
|
|
_gfxCoordAdjuster = new GfxCoordAdjuster32(segMan);
|
|
|
|
_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
|
|
|
|
_gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
|
|
|
|
_gfxPaint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette);
|
|
|
|
_gfxPaint = _gfxPaint32;
|
|
|
|
_gfxFrameout = new GfxFrameout(segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32);
|
2010-01-29 22:56:39 +00:00
|
|
|
} else {
|
2010-01-31 17:30:58 +00:00
|
|
|
#endif
|
2010-06-15 15:44:24 +00:00
|
|
|
// SCI0-SCI1.1 graphic objects creation
|
2010-06-09 10:45:54 +00:00
|
|
|
_gfxPorts = new GfxPorts(segMan, _gfxScreen);
|
2010-06-15 15:44:24 +00:00
|
|
|
_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
|
|
|
|
_gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager());
|
|
|
|
_gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
|
|
|
|
_gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA());
|
|
|
|
_gfxPaint16 = new GfxPaint16(g_sci->getResMan(), 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(segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
|
|
|
|
_gfxMenu = new GfxMenu(g_sci->getEventManager(), segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
|
|
|
|
|
|
|
|
_gfxMenu->reset();
|
2010-01-31 17:30:58 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2010-06-09 21:41:20 +00:00
|
|
|
#endif
|
|
|
|
|
2010-06-09 18:42:21 +00:00
|
|
|
_kernel->loadKernelNames(_features); // Must be called after game_init()
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-06-15 07:21:52 +00:00
|
|
|
script_adjust_opcode_formats();
|
2009-08-30 14:53:58 +00:00
|
|
|
|
2010-02-13 17:44:58 +00:00
|
|
|
SciVersion soundVersion = _features->detectDoSoundType();
|
2009-12-25 18:59:15 +00:00
|
|
|
|
2010-01-18 22:39:56 +00:00
|
|
|
_gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion);
|
2009-11-12 15:24:11 +00:00
|
|
|
|
2009-12-26 00:50:09 +00:00
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
2010-06-10 07:41:48 +00:00
|
|
|
initGameSound(0, soundVersion);
|
2009-12-26 00:50:09 +00:00
|
|
|
#endif
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-01-12 00:51:37 +00:00
|
|
|
syncSoundSettings();
|
|
|
|
|
2010-06-15 13:34:40 +00:00
|
|
|
initGraphics();
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2010-02-13 11:58:15 +00:00
|
|
|
debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-01-30 19:08:00 +00:00
|
|
|
// Check whether loading a savestate was requested
|
|
|
|
if (ConfMan.hasKey("save_slot")) {
|
2010-06-06 23:00:33 +00:00
|
|
|
_gamestate->loadFromLauncher = ConfMan.getInt("save_slot");
|
2010-01-30 19:08:00 +00:00
|
|
|
} else {
|
2010-06-06 23:00:33 +00:00
|
|
|
_gamestate->loadFromLauncher = -1;
|
2010-01-30 19:08:00 +00:00
|
|
|
}
|
|
|
|
|
2010-06-10 07:32:05 +00:00
|
|
|
runGame();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2010-01-12 00:51:37 +00:00
|
|
|
ConfMan.flushToDisk();
|
|
|
|
|
2009-11-12 15:24:11 +00:00
|
|
|
delete _gamestate->_soundCmd;
|
2010-02-07 15:48:47 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-06-15 15:44:24 +00:00
|
|
|
delete _gfxFrameout;
|
2010-02-07 15:48:47 +00:00
|
|
|
#endif
|
2010-06-15 15:44:24 +00:00
|
|
|
delete _gfxMenu;
|
|
|
|
delete _gfxControls;
|
|
|
|
delete _gfxText16;
|
|
|
|
delete _gfxAnimate;
|
|
|
|
delete _gfxPaint;
|
|
|
|
delete _gfxTransitions;
|
|
|
|
delete _gfxCompare;
|
|
|
|
delete _gfxCoordAdjuster;
|
2010-02-13 17:43:31 +00:00
|
|
|
delete _gfxPorts;
|
|
|
|
delete _gfxCache;
|
|
|
|
delete _gfxPalette;
|
2010-06-09 10:45:54 +00:00
|
|
|
delete _gfxCursor;
|
2010-02-13 17:43:31 +00:00
|
|
|
delete _gfxScreen;
|
2010-06-15 15:44:24 +00:00
|
|
|
|
2010-06-09 07:59:42 +00:00
|
|
|
delete _eventMan;
|
2009-11-04 14:22:17 +00:00
|
|
|
delete segMan;
|
2009-06-03 14:09:25 +00:00
|
|
|
delete _gamestate;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 08:20:53 +00:00
|
|
|
return Common::kNoError;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2010-06-10 07:32:05 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
_gamestate->_msgState = new MessageState(_gamestate->_segMan);
|
2010-06-10 11:43:20 +00:00
|
|
|
_gamestate->gcCountDown = GC_INTERVAL - 1;
|
2010-06-10 07:32:05 +00:00
|
|
|
|
|
|
|
// Script 0 should always be at segment 1
|
|
|
|
if (script0Segment != 1) {
|
|
|
|
debug(2, "Failed to instantiate script.000");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_gamestate->initGlobals();
|
|
|
|
|
|
|
|
if (_gamestate->abortScriptProcessing == kAbortRestartGame && _gfxMenu)
|
|
|
|
_gfxMenu->reset();
|
|
|
|
|
|
|
|
_gamestate->_segMan->initSysStrings();
|
|
|
|
|
|
|
|
_gamestate->r_acc = _gamestate->r_prev = NULL_REG;
|
|
|
|
|
|
|
|
_gamestate->_executionStack.clear(); // Start without any execution stack
|
2010-06-10 11:18:10 +00:00
|
|
|
_gamestate->executionStackBase = -1; // No vm is running yet
|
2010-06-10 07:32:05 +00:00
|
|
|
_gamestate->_executionStackPosChanged = false;
|
|
|
|
|
|
|
|
_gamestate->abortScriptProcessing = kAbortNone;
|
|
|
|
_gamestate->gameWasRestarted = false;
|
|
|
|
|
|
|
|
_gamestate->stack_base = stack->_entries;
|
|
|
|
_gamestate->stack_top = stack->_entries + stack->_capacity;
|
|
|
|
|
|
|
|
if (!script_instantiate(_resMan, _gamestate->_segMan, 0)) {
|
|
|
|
warning("initGame(): Could not instantiate script 0");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset parser
|
|
|
|
if (_vocabulary) {
|
|
|
|
_vocabulary->parserIsValid = false; // Invalidate parser
|
|
|
|
_vocabulary->parser_event = NULL_REG; // Invalidate parser event
|
|
|
|
_vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE);
|
|
|
|
}
|
|
|
|
|
2010-06-14 08:36:52 +00:00
|
|
|
_gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
|
2010-06-10 07:32:05 +00:00
|
|
|
|
|
|
|
srand(g_system->getMillis()); // Initialize random number generator
|
|
|
|
|
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
|
|
|
if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
|
2010-06-10 07:41:48 +00:00
|
|
|
initGameSound(0, _features->detectDoSoundType());
|
2010-06-10 07:32:05 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Load game language into printLang property of game object
|
2010-06-10 11:18:10 +00:00
|
|
|
setSciLanguage();
|
2010-06-10 07:32:05 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-06-15 13:34:40 +00:00
|
|
|
void SciEngine::initGraphics() {
|
|
|
|
if (_gfxPorts) {
|
|
|
|
_gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16);
|
|
|
|
_gfxPaint16->init(_gfxAnimate, _gfxText16);
|
|
|
|
}
|
|
|
|
// Set default (EGA, amiga or resource 999) palette
|
|
|
|
_gfxPalette->setDefault();
|
|
|
|
}
|
|
|
|
|
2010-06-10 07:41:48 +00:00
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
|
|
|
|
|
|
|
void SciEngine::initGameSound(int sound_flags, SciVersion soundVersion) {
|
|
|
|
if (getSciVersion() > SCI_VERSION_0_LATE)
|
|
|
|
sound_flags |= SFX_STATE_FLAG_MULTIPLAY;
|
|
|
|
|
|
|
|
_gamestate->sfx_init_flags = sound_flags;
|
|
|
|
_gamestate->_sound.sfx_init(_resMan, sound_flags, soundVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-06-10 07:32:05 +00:00
|
|
|
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
|
2010-06-10 08:11:38 +00:00
|
|
|
if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) {
|
|
|
|
_console->printObject(_gameObj);
|
2010-06-10 07:32:05 +00:00
|
|
|
error("initStackBaseWithSelector: error while registering the first selector in the call stack");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SciEngine::runGame() {
|
2010-06-10 09:18:57 +00:00
|
|
|
initStackBaseWithSelector(SELECTOR(play)); // Call the play selector
|
2010-06-10 07:32:05 +00:00
|
|
|
|
|
|
|
// Attach the debug console on game startup, if requested
|
|
|
|
if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
|
|
|
|
_console->attach();
|
|
|
|
|
|
|
|
do {
|
|
|
|
_gamestate->_executionStackPosChanged = false;
|
|
|
|
run_vm(_gamestate, (_gamestate->abortScriptProcessing == kAbortLoadGame));
|
|
|
|
exitGame();
|
|
|
|
|
|
|
|
if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
|
|
|
|
_gamestate->_segMan->resetSegMan();
|
|
|
|
initGame();
|
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
|
|
|
_gamestate->_sound.sfx_reset_player();
|
|
|
|
#endif
|
2010-06-10 09:18:57 +00:00
|
|
|
initStackBaseWithSelector(SELECTOR(play));
|
2010-06-10 07:32:05 +00:00
|
|
|
_gamestate->gameWasRestarted = true;
|
|
|
|
} else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
|
|
|
|
_gamestate->abortScriptProcessing = kAbortNone;
|
2010-06-10 09:18:57 +00:00
|
|
|
initStackBaseWithSelector(SELECTOR(replay));
|
2010-06-10 07:32:05 +00:00
|
|
|
} else {
|
|
|
|
break; // exit loop
|
|
|
|
}
|
|
|
|
} while (true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SciEngine::exitGame() {
|
|
|
|
if (_gamestate->abortScriptProcessing != kAbortLoadGame) {
|
|
|
|
_gamestate->_executionStack.clear();
|
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
|
|
|
_gamestate->_sound.sfx_exit();
|
|
|
|
// Reinit because some other code depends on having a valid state
|
2010-06-10 07:41:48 +00:00
|
|
|
initGameSound(SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType());
|
2010-06-10 07:32:05 +00:00
|
|
|
#else
|
|
|
|
_audio->stopAllAudio();
|
|
|
|
_gamestate->_soundCmd->clearPlayList();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO Free parser segment here
|
|
|
|
|
|
|
|
// TODO Free scripts here
|
|
|
|
|
|
|
|
// Close all opened file handles
|
|
|
|
_gamestate->_fileHandles.clear();
|
|
|
|
_gamestate->_fileHandles.resize(5);
|
|
|
|
}
|
|
|
|
|
2009-07-03 14:22:50 +00:00
|
|
|
// Invoked by error() when a severe error occurs
|
2009-05-11 13:31:17 +00:00
|
|
|
GUI::Debugger *SciEngine::getDebugger() {
|
2009-07-07 06:53:53 +00:00
|
|
|
if (_gamestate) {
|
|
|
|
ExecStack *xs = &(_gamestate->_executionStack.back());
|
2009-09-17 13:21:19 +00:00
|
|
|
xs->addr.pc.offset = g_debugState.old_pc_offset;
|
|
|
|
xs->sp = g_debugState.old_sp;
|
2009-07-07 06:53:53 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 13:21:19 +00:00
|
|
|
g_debugState.runningStep = 0; // Stop multiple execution
|
|
|
|
g_debugState.seeking = kDebugSeekNothing; // Stop special seeks
|
2009-07-03 14:22:50 +00:00
|
|
|
|
|
|
|
return _console;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Used to obtain the engine's console in order to print messages to it
|
|
|
|
Console *SciEngine::getSciDebugger() {
|
2009-05-11 13:31:17 +00:00
|
|
|
return _console;
|
|
|
|
}
|
|
|
|
|
2009-02-20 14:45:28 +00:00
|
|
|
const char* SciEngine::getGameID() const {
|
2009-10-09 23:19:53 +00:00
|
|
|
return _gameDescription->gameid;
|
2009-02-20 14:45:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::Language SciEngine::getLanguage() const {
|
2009-10-09 23:19:53 +00:00
|
|
|
return _gameDescription->language;
|
2009-02-20 14:45:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::Platform SciEngine::getPlatform() const {
|
2009-10-09 23:19:53 +00:00
|
|
|
return _gameDescription->platform;
|
2009-02-20 14:45:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 SciEngine::getFlags() const {
|
2009-05-14 09:12:27 +00:00
|
|
|
return _gameDescription->flags;
|
2009-02-20 14:45:28 +00:00
|
|
|
}
|
|
|
|
|
2009-12-30 16:00:56 +00:00
|
|
|
bool SciEngine::isDemo() const {
|
|
|
|
return getFlags() & ADGF_DEMO;
|
|
|
|
}
|
|
|
|
|
2009-02-20 23:41:15 +00:00
|
|
|
Common::String SciEngine::getSavegameName(int nr) const {
|
2009-07-25 10:26:17 +00:00
|
|
|
return _targetName + Common::String::printf(".%03d", nr);
|
2009-02-20 23:41:15 +00:00
|
|
|
}
|
|
|
|
|
2009-02-27 01:17:24 +00:00
|
|
|
Common::String SciEngine::getSavegamePattern() const {
|
|
|
|
return _targetName + ".???";
|
|
|
|
}
|
|
|
|
|
2010-01-01 09:40:28 +00:00
|
|
|
Common::String SciEngine::getFilePrefix() const {
|
|
|
|
const char* gameID = getGameID();
|
|
|
|
if (!strcmp(gameID, "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")) {
|
|
|
|
// Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data
|
|
|
|
if (_gamestate->currentRoomNumber() == 54)
|
|
|
|
return "qfg2";
|
|
|
|
}
|
|
|
|
// TODO: Implement the same for qfg4, when sci32 is good enough
|
|
|
|
return _targetName;
|
|
|
|
}
|
|
|
|
|
2009-02-27 01:17:24 +00:00
|
|
|
Common::String SciEngine::wrapFilename(const Common::String &name) const {
|
2010-01-01 09:40:28 +00:00
|
|
|
return getFilePrefix() + "-" + name;
|
2009-02-27 01:17:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::String SciEngine::unwrapFilename(const Common::String &name) const {
|
2010-01-01 09:40:28 +00:00
|
|
|
Common::String prefix = getFilePrefix() + "-";
|
2009-02-27 01:17:24 +00:00
|
|
|
if (name.hasPrefix(prefix.c_str()))
|
|
|
|
return Common::String(name.c_str() + prefix.size());
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2009-06-02 19:03:43 +00:00
|
|
|
void SciEngine::pauseEngineIntern(bool pause) {
|
2009-12-20 13:38:13 +00:00
|
|
|
#ifdef USE_OLD_MUSIC_FUNCTIONS
|
2009-06-03 14:09:25 +00:00
|
|
|
_gamestate->_sound.sfx_suspend(pause);
|
2009-12-20 13:38:13 +00:00
|
|
|
#endif
|
2009-06-02 19:03:43 +00:00
|
|
|
_mixer->pauseAll(pause);
|
|
|
|
}
|
|
|
|
|
2010-01-12 00:51:37 +00:00
|
|
|
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) {
|
|
|
|
int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume;
|
|
|
|
_gamestate->_soundCmd->setMasterVolume(vol);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-02-20 14:45:28 +00:00
|
|
|
} // End of namespace Sci
|