From c8fbac1517cd2cd60791d598fb1922846ff0b867 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 4 Nov 2009 14:22:17 +0000 Subject: - Changed the segment manager to be a static part of the engine, and stopped deleting and recreating it when restoring games - Merged game_exit(), script_free_vm_memory() and script_free_engine() - Cleanup svn-id: r45666 --- engines/sci/engine/game.cpp | 32 +++++++++----------------------- engines/sci/engine/savegame.cpp | 9 +++------ engines/sci/engine/seg_manager.cpp | 29 ++++++++++++++++++++--------- engines/sci/engine/seg_manager.h | 4 +++- engines/sci/engine/state.cpp | 5 ++--- engines/sci/engine/state.h | 2 +- engines/sci/engine/vm.cpp | 2 -- engines/sci/engine/vm.h | 14 -------------- engines/sci/gui/gui.cpp | 5 ++--- engines/sci/gui/gui_controls.cpp | 28 ++++++++++++++-------------- engines/sci/gui/gui_controls.h | 5 +++-- engines/sci/gui/gui_gfx.h | 2 -- engines/sci/gui32/gui32.cpp | 1 - engines/sci/sci.cpp | 7 +++++-- 14 files changed, 62 insertions(+), 83 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 94e49ab33f..6802888a3f 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -304,7 +304,6 @@ int game_init_sound(EngineState *s, int sound_flags) { // Architectural stuff: Init/Unintialize engine int script_init_engine(EngineState *s) { - s->_segMan = new SegManager(s->resMan); s->_msgState = new MessageState(s->_segMan); s->gc_countdown = GC_INTERVAL - 1; @@ -350,23 +349,6 @@ int script_init_engine(EngineState *s) { return 0; } -void script_free_vm_memory(EngineState *s) { - debug(2, "Freeing VM memory"); - - if (s->_segMan) - s->_segMan->_classtable.clear(); - - // Close all opened file handles - s->_fileHandles.clear(); - s->_fileHandles.resize(5); -} - -void script_free_engine(EngineState *s) { - script_free_vm_memory(s); - - debug(2, "Freeing state-dependant data"); -} - void script_free_breakpoints(EngineState *s) { Breakpoint *bp, *bp_next; @@ -451,11 +433,11 @@ int game_exit(EngineState *s) { game_init_sound(s, SFX_STATE_FLAG_NOSOUND); } - s->_segMan->_classtable.clear(); - delete s->_segMan; - s->_segMan = 0; - - debug(2, "Freeing miscellaneous data..."); + // Note: It's a bad idea to delete the segment manager here. + // This function is called right after a game is loaded, and + // the segment manager has already been initialized from the + // save game. Deleting or resetting it here will result in + // invalidating the loaded save state // TODO Free parser segment here @@ -465,6 +447,10 @@ int game_exit(EngineState *s) { _free_graphics_input(s); + // Close all opened file handles + s->_fileHandles.clear(); + s->_fileHandles.resize(5); + return 0; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 406c450107..6f3aee8539 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -257,11 +257,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { static void sync_SegManagerPtr(Common::Serializer &s, ResourceManager *&resMan, SegManager *&obj) { s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not - if (s.isLoading()) { - // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. - delete obj; - obj = new SegManager(resMan); - } + if (s.isLoading()) + obj->resetSegMan(); obj->saveLoadWithSerializer(s); } @@ -737,7 +734,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } // FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. - retval = new EngineState(s->resMan, s->_kernel, s->_voc, s->_gui, s->_audio); + retval = new EngineState(s->resMan, s->_kernel, s->_voc, s->_segMan, s->_gui, s->_audio); // Copy some old data retval->gfx_state = s->gfx_state; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 2af038185b..79f2e88f9e 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -57,21 +57,34 @@ SegManager::SegManager(ResourceManager *resMan) { _exportsAreWide = false; _resMan = resMan; - int result = 0; - - result = createClassTable(); - - if (result) - error("SegManager: Failed to initialize class table"); + createClassTable(); } // Destroy the object, free the memorys if allocated before SegManager::~SegManager() { + resetSegMan(); +} + +void SegManager::resetSegMan() { // Free memory for (uint i = 0; i < _heap.size(); i++) { if (_heap[i]) deallocate(i, false); } + + _heap.clear(); + + // And reinitialize + _heap.push_back(0); + + Clones_seg_id = 0; + Lists_seg_id = 0; + Nodes_seg_id = 0; + Hunks_seg_id = 0; + + // Reinitialize class table + _classtable.clear(); + createClassTable(); } SegmentId SegManager::findFreeSegment() const { @@ -1218,7 +1231,7 @@ int SegManager::freeDynmem(reg_t addr) { return 0; // OK } -int SegManager::createClassTable() { +void SegManager::createClassTable() { Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); if (!vocab996) @@ -1235,8 +1248,6 @@ int SegManager::createClassTable() { } _resMan->unlockResource(vocab996); - - return 0; } } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 1a9d20dea3..2e785b1341 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -58,6 +58,8 @@ public: */ ~SegManager(); + void resetSegMan(); + virtual void saveLoadWithSerializer(Common::Serializer &ser); // 1. Scripts @@ -456,7 +458,7 @@ private: SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid); LocalVariables *allocLocalsSegment(Script *scr, int count); int deallocate(SegmentId seg, bool recursive); - int createClassTable(); + void createClassTable(); SegmentId findFreeSegment() const; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 06cace2b99..7336bc71d6 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -32,8 +32,8 @@ namespace Sci { -EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, AudioPlayer *audio) -: resMan(res), _kernel(kernel), _voc(voc), _gui(gui), _audio(audio), _dirseeker(this) { +EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SegManager *segMan, SciGui *gui, AudioPlayer *audio) +: resMan(res), _kernel(kernel), _voc(voc), _segMan(segMan), _gui(gui), _audio(audio), _dirseeker(this) { gfx_state = 0; @@ -96,7 +96,6 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, _gameObj = NULL_REG; - _segMan = 0; gc_countdown = 0; successor = 0; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 21ccb2a07a..e368953aea 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -116,7 +116,7 @@ public: struct EngineState : public Common::Serializable { public: - EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, AudioPlayer *audio); + EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SegManager *segMan, SciGui *gui, AudioPlayer *audio); virtual ~EngineState(); virtual void saveLoadWithSerializer(Common::Serializer &ser); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a629e7fabd..e086b8c836 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1796,7 +1796,6 @@ static EngineState *_game_run(EngineState *&s, int restoring) { s->_executionStackPosChanged = false; game_exit(s); - script_free_engine(s); script_init_engine(s); game_init(s); s->_sound.sfx_reset_player(); @@ -1811,7 +1810,6 @@ static EngineState *_game_run(EngineState *&s, int restoring) { successor = s->successor; if (successor) { game_exit(s); - script_free_vm_memory(s); delete s; s = successor; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index d09cb27e30..391338ec09 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -419,20 +419,6 @@ void script_debug(EngineState *s, bool bp); */ int script_init_engine(EngineState *); -/** - * Frees all additional memory associated with a EngineState block - * @param[in] s The EngineState whose elements should be cleared - */ -void script_free_engine(EngineState *s); - -/** - * Frees all script memory (heap, hunk, and class tables). - * This operation is implicit in script_free_engine(), but is required for - * restoring the game state. - * @param[in] s The EngineState to free - */ -void script_free_vm_memory(EngineState *s); - /** * Looks up a selector and returns its type and value * varindex is written to iff it is non-NULL and the selector indicates a property of the object. diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index 992b66e5dd..e6b3bf422b 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -61,7 +61,7 @@ SciGui::SciGui(EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette, _animate = new SciGuiAnimate(_s, _gfx, _screen, _palette); _text = new SciGuiText(_s->resMan, _gfx, _screen); _windowMgr = new SciGuiWindowMgr(this, _screen, _gfx, _text); - _controls = new SciGuiControls(_gfx, _text); + _controls = new SciGuiControls(_s->_segMan, _gfx, _text); _menu = new SciGuiMenu(_gfx, _text, _screen); // _gui32 = new SciGui32(_s, _screen, _palette, _cursor); // for debug purposes } @@ -81,7 +81,6 @@ SciGui::~SciGui() { void SciGui::resetEngineState(EngineState *s) { _s = s; - _gfx->resetSegMan(s->_segMan); _animate->resetEngineState(s); } @@ -443,7 +442,7 @@ void SciGui::editControl(reg_t controlObject, reg_t eventObject) { switch (controlType) { case SCI_CONTROLS_TYPE_TEXTEDIT: // Only process textedit controls in here - _controls->TexteditChange(_s->_segMan, controlObject, eventObject); + _controls->TexteditChange(controlObject, eventObject); return; } } diff --git a/engines/sci/gui/gui_controls.cpp b/engines/sci/gui/gui_controls.cpp index f9239f9573..40b61f3ef6 100644 --- a/engines/sci/gui/gui_controls.cpp +++ b/engines/sci/gui/gui_controls.cpp @@ -36,8 +36,8 @@ namespace Sci { -SciGuiControls::SciGuiControls(SciGuiGfx *gfx, SciGuiText *text) - : _gfx(gfx), _text(text) { +SciGuiControls::SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text) + : _segMan(segMan), _gfx(gfx), _text(text) { init(); } @@ -137,10 +137,10 @@ void SciGuiControls::TexteditSetBlinkTime() { _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); } -void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg_t eventObject) { - uint16 cursorPos = GET_SEL32V(segMan, controlObject, cursor); - uint16 maxChars = GET_SEL32V(segMan, controlObject, max); - reg_t textReference = GET_SEL32(segMan, controlObject, text); +void SciGuiControls::TexteditChange(reg_t controlObject, reg_t eventObject) { + uint16 cursorPos = GET_SEL32V(_segMan, controlObject, cursor); + uint16 maxChars = GET_SEL32V(_segMan, controlObject, max); + reg_t textReference = GET_SEL32(_segMan, controlObject, text); Common::String text; uint16 textSize, eventType, eventKey; bool textChanged = false; @@ -148,18 +148,18 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg if (textReference.isNull()) error("kEditControl called on object that doesnt have a text reference"); - text = segMan->getString(textReference); + text = _segMan->getString(textReference); if (!eventObject.isNull()) { textSize = text.size(); - eventType = GET_SEL32V(segMan, eventObject, type); + eventType = GET_SEL32V(_segMan, eventObject, type); switch (eventType) { case SCI_EVT_MOUSE_PRESS: // TODO: Implement mouse support for cursor change break; case SCI_EVT_KEYBOARD: - eventKey = GET_SEL32V(segMan, eventObject, message); + eventKey = GET_SEL32V(_segMan, eventObject, message); switch (eventKey) { case SCI_K_BACKSPACE: if (cursorPos > 0) { @@ -203,9 +203,9 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg if (textChanged) { GuiResourceId oldFontId = _text->GetFontId(); - GuiResourceId fontId = GET_SEL32V(segMan, controlObject, font); - rect = Common::Rect(GET_SEL32V(segMan, controlObject, nsLeft), GET_SEL32V(segMan, controlObject, nsTop), - GET_SEL32V(segMan, controlObject, nsRight), GET_SEL32V(segMan, controlObject, nsBottom)); + GuiResourceId fontId = GET_SEL32V(_segMan, controlObject, font); + rect = Common::Rect(GET_SEL32V(_segMan, controlObject, nsLeft), GET_SEL32V(_segMan, controlObject, nsTop), + GET_SEL32V(_segMan, controlObject, nsRight), GET_SEL32V(_segMan, controlObject, nsBottom)); TexteditCursorErase(); _gfx->EraseRect(rect); _text->Box(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); @@ -214,7 +214,7 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg TexteditCursorDraw(rect, text.c_str(), cursorPos); _text->SetFont(oldFontId); // Write back string - segMan->strcpy(textReference, text.c_str()); + _segMan->strcpy(textReference, text.c_str()); } else { if (g_system->getMillis() >= _texteditBlinkTime) { _gfx->InvertRect(_texteditCursorRect); @@ -224,7 +224,7 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg } } - PUT_SEL32V(segMan, controlObject, cursor, cursorPos); + PUT_SEL32V(_segMan, controlObject, cursor, cursorPos); } } // End of namespace Sci diff --git a/engines/sci/gui/gui_controls.h b/engines/sci/gui/gui_controls.h index 33b2e54989..a2d027d514 100644 --- a/engines/sci/gui/gui_controls.h +++ b/engines/sci/gui/gui_controls.h @@ -33,18 +33,19 @@ class SciGuiFont; class SciGuiText; class SciGuiControls { public: - SciGuiControls(SciGuiGfx *gfx, SciGuiText *text); + SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text); ~SciGuiControls(); void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); void TexteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos); void TexteditCursorErase(); - void TexteditChange(SegManager *segMan, reg_t controlObject, reg_t eventObject); + void TexteditChange(reg_t controlObject, reg_t eventObject); private: void init(); void TexteditSetBlinkTime(); + SegManager *_segMan; SciGuiGfx *_gfx; SciGuiText *_text; diff --git a/engines/sci/gui/gui_gfx.h b/engines/sci/gui/gui_gfx.h index 516fa5466d..74334e5a39 100644 --- a/engines/sci/gui/gui_gfx.h +++ b/engines/sci/gui/gui_gfx.h @@ -53,8 +53,6 @@ public: void init(SciGuiText *text); - void resetSegMan(SegManager *segMan) { _segMan = segMan; } - byte *GetSegment(byte seg); void ResetScreen(); diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp index 4b67e16f1e..892f66932b 100644 --- a/engines/sci/gui32/gui32.cpp +++ b/engines/sci/gui32/gui32.cpp @@ -408,7 +408,6 @@ void SciGui32::init(bool oldGfxFunctions) { void SciGui32::resetEngineState(EngineState *s) { _s = s; - _gfx->resetSegMan(s->_segMan); } void SciGui32::wait(int16 ticks) { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index cd611ed600..673e96c49e 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -133,8 +133,10 @@ Common::Error SciEngine::run() { _vocabulary = new Vocabulary(_resMan); _audio = new AudioPlayer(_resMan); + SegManager *segMan = new SegManager(_resMan); + // We'll set the GUI below - _gamestate = new EngineState(_resMan, _kernel, _vocabulary, NULL, _audio); + _gamestate = new EngineState(_resMan, _kernel, _vocabulary, segMan, NULL, _audio); if (script_init_engine(_gamestate)) return Common::kUnknownError; @@ -181,15 +183,16 @@ Common::Error SciEngine::run() { } _gamestate->_gui->init(_gamestate->usesOldGfxFunctions()); + _gamestate->_segMan = segMan; 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 segMan; delete cursor; delete palette; delete screen; -- cgit v1.2.3