aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/detection.cpp7
-rw-r--r--engines/sci/engine/game.cpp151
-rw-r--r--engines/sci/engine/vm.cpp51
-rw-r--r--engines/sci/engine/vm.h59
-rw-r--r--engines/sci/module.mk1
-rw-r--r--engines/sci/sci.cpp132
-rw-r--r--engines/sci/sci.h41
7 files changed, 177 insertions, 265 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 1ccfc6bf02..f36bae2d6d 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -36,7 +36,6 @@
#include "sci/engine/script.h"
#include "sci/engine/seg_manager.h"
#include "sci/engine/state.h"
-#include "sci/engine/vm.h" // for convertSierraGameId
namespace Sci {
@@ -198,6 +197,12 @@ static const OldNewIdTableEntry s_oldNewTable[] = {
{ "", "", SCI_VERSION_NONE }
};
+/**
+ * Converts the builtin Sierra game IDs to the ones we use in ScummVM
+ * @param[in] gameId The internal game ID
+ * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos
+ * @return The equivalent ScummVM game id
+ */
Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) {
// Convert the id to lower case, so that we match all upper/lower case variants.
sierraId.toLowercase();
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
deleted file mode 100644
index 04f8501027..0000000000
--- a/engines/sci/engine/game.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/* 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/file.h"
-
-#include "engines/advancedDetector.h" // for ADGF_DEMO
-
-#include "sci/sci.h"
-#include "sci/resource.h"
-#include "sci/engine/features.h"
-#include "sci/engine/state.h"
-#include "sci/engine/kernel.h"
-#include "sci/engine/message.h"
-#include "sci/graphics/gui.h"
-#include "sci/graphics/menu.h"
-#include "sci/sound/audio.h"
-#include "sci/sound/music.h"
-
-namespace Sci {
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) {
- if (getSciVersion() > SCI_VERSION_0_LATE)
- sound_flags |= SFX_STATE_FLAG_MULTIPLAY;
-
- s->sfx_init_flags = sound_flags;
- s->_sound.sfx_init(g_sci->getResMan(), sound_flags, soundVersion);
-
- return 0;
-}
-#endif
-
-/*************************************************************/
-/* Game instance stuff: Init/Unitialize state-dependant data */
-/*************************************************************/
-
-int game_init(EngineState *s) {
- // FIXME Use new VM instantiation code all over the place
- // Script 0 needs to be allocated here before anything else!
- int script0Segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK);
- DataStack *stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL);
-
- s->_msgState = new MessageState(s->_segMan);
- s->gc_countdown = GC_INTERVAL - 1;
-
- // Script 0 should always be at segment 1
- if (script0Segment != 1) {
- debug(2, "Failed to instantiate script.000");
- return 1;
- }
-
- s->initGlobals();
-
- if (s->abortScriptProcessing == kAbortRestartGame && g_sci->_gfxMenu)
- g_sci->_gfxMenu->reset();
-
- s->_segMan->initSysStrings();
-
- s->r_acc = s->r_prev = NULL_REG;
-
- s->_executionStack.clear(); // Start without any execution stack
- s->execution_stack_base = -1; // No vm is running yet
- s->_executionStackPosChanged = false;
-
- s->abortScriptProcessing = kAbortNone;
- s->gameWasRestarted = false;
-
- s->stack_base = stack->_entries;
- s->stack_top = stack->_entries + stack->_capacity;
-
- if (!script_instantiate(g_sci->getResMan(), s->_segMan, 0)) {
- warning("game_init(): Could not instantiate script 0");
- return 1;
- }
-
- // Reset parser
- Vocabulary *voc = g_sci->getVocabulary();
- if (voc) {
- voc->parserIsValid = false; // Invalidate parser
- voc->parser_event = NULL_REG; // Invalidate parser event
- voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE);
- }
-
- s->game_start_time = g_system->getMillis();
- s->last_wait_time = s->game_start_time;
-
- srand(g_system->getMillis()); // Initialize random number generator
-
- s->_gameObj = g_sci->getResMan()->findGameObject();
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
- game_init_sound(s, 0, g_sci->_features->detectDoSoundType());
-#endif
-
- // Load game language into printLang property of game object
- // FIXME: It's evil to achieve this as a side effect of a getter.
- // Much better to have an explicit init method for this.
- g_sci->getSciLanguage();
-
- return 0;
-}
-
-int game_exit(EngineState *s) {
- if (s->abortScriptProcessing != kAbortLoadGame) {
- s->_executionStack.clear();
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_exit();
- // Reinit because some other code depends on having a valid state
- game_init_sound(s, SFX_STATE_FLAG_NOSOUND, g_sci->_features->detectDoSoundType());
-#else
- g_sci->_audio->stopAllAudio();
- s->_soundCmd->clearPlayList();
-#endif
- }
-
- // TODO Free parser segment here
-
- // TODO Free scripts here
-
- // Close all opened file handles
- s->_fileHandles.clear();
- s->_fileHandles.resize(5);
-
- return 0;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index eb2824d9c7..2c92bdadc3 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -1664,57 +1664,6 @@ void run_vm(EngineState *s, bool restoring) {
}
}
-static void _init_stack_base_with_selector(EngineState *s, Selector selector) {
- s->stack_base[0] = make_reg(0, (uint16)selector);
- s->stack_base[1] = NULL_REG;
-}
-
-void game_run(EngineState **_s) {
- EngineState *s = *_s;
-
- debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID());
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector
-
- // Now: Register the first element on the execution stack
- if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) {
- g_sci->getSciDebugger()->printObject(s->_gameObj);
- error("Failed to run the game! Aborting...");
- return;
- }
-
- // and ENGAGE!
-
- // Attach the debug console on game startup, if requested
- if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
- g_sci->getSciDebugger()->attach();
-
- do {
- s->_executionStackPosChanged = false;
- run_vm(s, (s->abortScriptProcessing == kAbortLoadGame));
- game_exit(s);
-
- if (s->abortScriptProcessing == kAbortRestartGame) {
- s->_segMan->resetSegMan();
- game_init(s);
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_reset_player();
-#endif
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play);
- send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base);
- s->gameWasRestarted = true;
- } else if (s->abortScriptProcessing == kAbortLoadGame) {
- s->abortScriptProcessing = kAbortNone;
- // Insert a replay selector
- _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay);
- send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base);
- } else {
- break; // exit loop
- }
- } while (true);
-
- debugC(2, kDebugLevelVM, "Game::play() finished.");
-}
-
reg_t *ObjVarRef::getPointer(SegManager *segMan) const {
Object *o = segMan->getObject(obj);
return o ? &o->getVariableRef(varindex) : 0;
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 1764284dae..fa57a1151c 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -330,65 +330,6 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_n
void script_uninstantiate(SegManager *segMan, int script_nr);
/**
- * Converts the builtin Sierra game IDs to the ones we use in ScummVM
- * @param[in] gameId The internal game ID
- * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos
- * @return The equivalent ScummVM game id
- */
-Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan);
-
-/**
- * Initializes an SCI game
- * This function must be run before script_run() is executed. Graphics data
- * is initialized iff s->gfx_state != NULL.
- * @param[in] s The state to operate on
- * @return 0 on success, 1 if an error occured.
- */
-int game_init(EngineState *s);
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-/**
- * Initializes the sound part of an SCI game
- * This function may only be called if game_init() did not initialize
- * the sound data.
- * @param[in] s The state to initialize the sound in
- * @param[in] sound_flags Flags to pass to the sound subsystem
- * @param[in] soundVersion sound-version that got detected during game init
- * @return 0 on success, 1 if an error occured
- */
-int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion);
-#endif
-
-/**
- * Runs an SCI game
- * This is the main function for SCI games. It takes a valid state, loads
- * script 0 to it, finds the game object, allocates a stack, and runs the
- * init method of the game object. In layman's terms, this runs an SCI game.
- * Note that, EngineState *s may be changed during the game, e.g. if a game
- * state is restored.
- * @param[in] s Pointer to the pointer of the state to operate on
- */
-void game_run(EngineState **s);
-
-/**
- * Restores an SCI game state and runs the game
- * This restores a savegame; otherwise, it behaves just like game_run().
- * @param[in] s Pointer to the pointer of the state to
- * operate on
- * @param[in] savegame_name Name of the savegame to restore
- * @return 0 on success, 1 if an error occured.
- */
-int game_restore(EngineState **s, char *savegame_name);
-
-/**
- * Uninitializes an initialized SCI game
- * This function should be run after each script_run() call.
- * @param[in] s The state to operate on
- * @return 0 on success, 1 if an error occured.
- */
-int game_exit(EngineState *s);
-
-/**
* Read a PMachine instruction from a memory buffer and return its length.
*
* @param[in] src address from which to start parsing
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index a2cfd38f95..4860ac7c2f 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -10,7 +10,6 @@ MODULE_OBJS := \
sci.o \
util.o \
engine/features.o \
- engine/game.o \
engine/gc.o \
engine/kernel.o \
engine/kevent.o \
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index d5cab1adc9..08236597b4 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -36,6 +36,7 @@
#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
@@ -197,7 +198,7 @@ Common::Error SciEngine::run() {
// 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 (game_init(_gamestate)) { /* Initialize */
+ if (!initGame()) { /* Initialize */
warning("Game initialization failed: Aborting...");
// TODO: Add an "init failed" error?
return Common::kUnknownError;
@@ -259,7 +260,7 @@ Common::Error SciEngine::run() {
_gamestate->loadFromLauncher = -1;
}
- game_run(&_gamestate); // Run the game
+ runGame();
ConfMan.flushToDisk();
@@ -280,6 +281,133 @@ Common::Error SciEngine::run() {
return Common::kNoError;
}
+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);
+ _gamestate->gc_countdown = GC_INTERVAL - 1;
+
+ // 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
+ _gamestate->execution_stack_base = -1; // No vm is running yet
+ _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);
+ }
+
+ _gamestate->game_start_time = _gamestate->last_wait_time = g_system->getMillis();
+
+ srand(g_system->getMillis()); // Initialize random number generator
+
+ _gamestate->_gameObj = _resMan->findGameObject();
+
+#ifdef USE_OLD_MUSIC_FUNCTIONS
+ if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
+ game_init_sound(_gamestate, 0, _features->detectDoSoundType());
+#endif
+
+ // Load game language into printLang property of game object
+ // FIXME: It's evil to achieve this as a side effect of a getter.
+ // Much better to have an explicit init method for this.
+ getSciLanguage();
+
+ return true;
+}
+
+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, _gamestate->_gameObj, _gamestate->_gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) {
+ _console->printObject(_gamestate->_gameObj);
+ error("initStackBaseWithSelector: error while registering the first selector in the call stack");
+ }
+
+}
+
+void SciEngine::runGame() {
+ initStackBaseWithSelector(_kernel->_selectorCache.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, (_gamestate->abortScriptProcessing == kAbortLoadGame));
+ exitGame();
+
+ if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
+ _gamestate->_segMan->resetSegMan();
+ initGame();
+#ifdef USE_OLD_MUSIC_FUNCTIONS
+ _gamestate->_sound.sfx_reset_player();
+#endif
+ initStackBaseWithSelector(_kernel->_selectorCache.play);
+ _gamestate->gameWasRestarted = true;
+ } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
+ _gamestate->abortScriptProcessing = kAbortNone;
+ initStackBaseWithSelector(_kernel->_selectorCache.replay);
+ } 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
+ game_init_sound(_gamestate, SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType());
+#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);
+}
+
// Invoked by error() when a severe error occurs
GUI::Debugger *SciEngine::getDebugger() {
if (_gamestate) {
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 0902a41139..0bcff8a02e 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -28,6 +28,7 @@
#include "engines/engine.h"
#include "common/util.h"
+#include "engine/vm_types.h" // for Selector
struct ADGameDescription;
@@ -219,6 +220,46 @@ public:
GameFeatures *_features;
private:
+ /**
+ * Initializes a SCI game
+ * This function must be run before script_run() is executed. Graphics data
+ * is initialized iff s->gfx_state != NULL.
+ * @param[in] s The state to operate on
+ * @return true on success, false if an error occured.
+ */
+ bool initGame();
+
+ /**
+ * Runs a SCI game
+ * This is the main function for SCI games. It takes a valid state, loads
+ * script 0 to it, finds the game object, allocates a stack, and runs the
+ * init method of the game object. In layman's terms, this runs a SCI game.
+ * @param[in] s Pointer to the pointer of the state to operate on
+ */
+ void runGame();
+
+ /**
+ * Uninitializes an initialized SCI game
+ * This function should be run after each script_run() call.
+ * @param[in] s The state to operate on
+ */
+ void exitGame();
+
+#ifdef USE_OLD_MUSIC_FUNCTIONS
+ /**
+ * Initializes the sound part of a SCI game
+ * This function may only be called if game_init() did not initialize
+ * the sound data.
+ * @param[in] s The state to initialize the sound in
+ * @param[in] sound_flags Flags to pass to the sound subsystem
+ * @param[in] soundVersion sound-version that got detected during game init
+ * @return 0 on success, 1 if an error occured
+ */
+ int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion);
+#endif
+
+ void initStackBaseWithSelector(Selector selector);
+
const ADGameDescription *_gameDescription;
ResourceManager *_resMan; /**< The resource manager */
EngineState *_gamestate;