- 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
This commit is contained in:
Filippos Karapetis 2009-11-04 14:22:17 +00:00
parent f83d7c6339
commit c8fbac1517
14 changed files with 62 additions and 83 deletions

View file

@ -304,7 +304,6 @@ int game_init_sound(EngineState *s, int sound_flags) {
// Architectural stuff: Init/Unintialize engine // Architectural stuff: Init/Unintialize engine
int script_init_engine(EngineState *s) { int script_init_engine(EngineState *s) {
s->_segMan = new SegManager(s->resMan);
s->_msgState = new MessageState(s->_segMan); s->_msgState = new MessageState(s->_segMan);
s->gc_countdown = GC_INTERVAL - 1; s->gc_countdown = GC_INTERVAL - 1;
@ -350,23 +349,6 @@ int script_init_engine(EngineState *s) {
return 0; 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) { void script_free_breakpoints(EngineState *s) {
Breakpoint *bp, *bp_next; Breakpoint *bp, *bp_next;
@ -451,11 +433,11 @@ int game_exit(EngineState *s) {
game_init_sound(s, SFX_STATE_FLAG_NOSOUND); game_init_sound(s, SFX_STATE_FLAG_NOSOUND);
} }
s->_segMan->_classtable.clear(); // Note: It's a bad idea to delete the segment manager here.
delete s->_segMan; // This function is called right after a game is loaded, and
s->_segMan = 0; // the segment manager has already been initialized from the
// save game. Deleting or resetting it here will result in
debug(2, "Freeing miscellaneous data..."); // invalidating the loaded save state
// TODO Free parser segment here // TODO Free parser segment here
@ -465,6 +447,10 @@ int game_exit(EngineState *s) {
_free_graphics_input(s); _free_graphics_input(s);
// Close all opened file handles
s->_fileHandles.clear();
s->_fileHandles.resize(5);
return 0; return 0;
} }

View file

@ -257,11 +257,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
static void sync_SegManagerPtr(Common::Serializer &s, ResourceManager *&resMan, SegManager *&obj) { 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 s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not
if (s.isLoading()) { if (s.isLoading())
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch. obj->resetSegMan();
delete obj;
obj = new SegManager(resMan);
}
obj->saveLoadWithSerializer(s); 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. // 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 // Copy some old data
retval->gfx_state = s->gfx_state; retval->gfx_state = s->gfx_state;

View file

@ -57,21 +57,34 @@ SegManager::SegManager(ResourceManager *resMan) {
_exportsAreWide = false; _exportsAreWide = false;
_resMan = resMan; _resMan = resMan;
int result = 0; createClassTable();
result = createClassTable();
if (result)
error("SegManager: Failed to initialize class table");
} }
// Destroy the object, free the memorys if allocated before // Destroy the object, free the memorys if allocated before
SegManager::~SegManager() { SegManager::~SegManager() {
resetSegMan();
}
void SegManager::resetSegMan() {
// Free memory // Free memory
for (uint i = 0; i < _heap.size(); i++) { for (uint i = 0; i < _heap.size(); i++) {
if (_heap[i]) if (_heap[i])
deallocate(i, false); 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 { SegmentId SegManager::findFreeSegment() const {
@ -1218,7 +1231,7 @@ int SegManager::freeDynmem(reg_t addr) {
return 0; // OK return 0; // OK
} }
int SegManager::createClassTable() { void SegManager::createClassTable() {
Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1);
if (!vocab996) if (!vocab996)
@ -1235,8 +1248,6 @@ int SegManager::createClassTable() {
} }
_resMan->unlockResource(vocab996); _resMan->unlockResource(vocab996);
return 0;
} }
} // End of namespace Sci } // End of namespace Sci

View file

@ -58,6 +58,8 @@ public:
*/ */
~SegManager(); ~SegManager();
void resetSegMan();
virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void saveLoadWithSerializer(Common::Serializer &ser);
// 1. Scripts // 1. Scripts
@ -456,7 +458,7 @@ private:
SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid); SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid);
LocalVariables *allocLocalsSegment(Script *scr, int count); LocalVariables *allocLocalsSegment(Script *scr, int count);
int deallocate(SegmentId seg, bool recursive); int deallocate(SegmentId seg, bool recursive);
int createClassTable(); void createClassTable();
SegmentId findFreeSegment() const; SegmentId findFreeSegment() const;

View file

@ -32,8 +32,8 @@
namespace Sci { namespace Sci {
EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SciGui *gui, AudioPlayer *audio) EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc, SegManager *segMan, SciGui *gui, AudioPlayer *audio)
: resMan(res), _kernel(kernel), _voc(voc), _gui(gui), _audio(audio), _dirseeker(this) { : resMan(res), _kernel(kernel), _voc(voc), _segMan(segMan), _gui(gui), _audio(audio), _dirseeker(this) {
gfx_state = 0; gfx_state = 0;
@ -96,7 +96,6 @@ EngineState::EngineState(ResourceManager *res, Kernel *kernel, Vocabulary *voc,
_gameObj = NULL_REG; _gameObj = NULL_REG;
_segMan = 0;
gc_countdown = 0; gc_countdown = 0;
successor = 0; successor = 0;

View file

@ -116,7 +116,7 @@ public:
struct EngineState : public Common::Serializable { struct EngineState : public Common::Serializable {
public: 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 ~EngineState();
virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void saveLoadWithSerializer(Common::Serializer &ser);

View file

@ -1796,7 +1796,6 @@ static EngineState *_game_run(EngineState *&s, int restoring) {
s->_executionStackPosChanged = false; s->_executionStackPosChanged = false;
game_exit(s); game_exit(s);
script_free_engine(s);
script_init_engine(s); script_init_engine(s);
game_init(s); game_init(s);
s->_sound.sfx_reset_player(); s->_sound.sfx_reset_player();
@ -1811,7 +1810,6 @@ static EngineState *_game_run(EngineState *&s, int restoring) {
successor = s->successor; successor = s->successor;
if (successor) { if (successor) {
game_exit(s); game_exit(s);
script_free_vm_memory(s);
delete s; delete s;
s = successor; s = successor;

View file

@ -419,20 +419,6 @@ void script_debug(EngineState *s, bool bp);
*/ */
int script_init_engine(EngineState *); 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 * 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. * varindex is written to iff it is non-NULL and the selector indicates a property of the object.

View file

@ -61,7 +61,7 @@ SciGui::SciGui(EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette,
_animate = new SciGuiAnimate(_s, _gfx, _screen, _palette); _animate = new SciGuiAnimate(_s, _gfx, _screen, _palette);
_text = new SciGuiText(_s->resMan, _gfx, _screen); _text = new SciGuiText(_s->resMan, _gfx, _screen);
_windowMgr = new SciGuiWindowMgr(this, _screen, _gfx, _text); _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); _menu = new SciGuiMenu(_gfx, _text, _screen);
// _gui32 = new SciGui32(_s, _screen, _palette, _cursor); // for debug purposes // _gui32 = new SciGui32(_s, _screen, _palette, _cursor); // for debug purposes
} }
@ -81,7 +81,6 @@ SciGui::~SciGui() {
void SciGui::resetEngineState(EngineState *s) { void SciGui::resetEngineState(EngineState *s) {
_s = s; _s = s;
_gfx->resetSegMan(s->_segMan);
_animate->resetEngineState(s); _animate->resetEngineState(s);
} }
@ -443,7 +442,7 @@ void SciGui::editControl(reg_t controlObject, reg_t eventObject) {
switch (controlType) { switch (controlType) {
case SCI_CONTROLS_TYPE_TEXTEDIT: case SCI_CONTROLS_TYPE_TEXTEDIT:
// Only process textedit controls in here // Only process textedit controls in here
_controls->TexteditChange(_s->_segMan, controlObject, eventObject); _controls->TexteditChange(controlObject, eventObject);
return; return;
} }
} }

View file

@ -36,8 +36,8 @@
namespace Sci { namespace Sci {
SciGuiControls::SciGuiControls(SciGuiGfx *gfx, SciGuiText *text) SciGuiControls::SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text)
: _gfx(gfx), _text(text) { : _segMan(segMan), _gfx(gfx), _text(text) {
init(); init();
} }
@ -137,10 +137,10 @@ void SciGuiControls::TexteditSetBlinkTime() {
_texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60);
} }
void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg_t eventObject) { void SciGuiControls::TexteditChange(reg_t controlObject, reg_t eventObject) {
uint16 cursorPos = GET_SEL32V(segMan, controlObject, cursor); uint16 cursorPos = GET_SEL32V(_segMan, controlObject, cursor);
uint16 maxChars = GET_SEL32V(segMan, controlObject, max); uint16 maxChars = GET_SEL32V(_segMan, controlObject, max);
reg_t textReference = GET_SEL32(segMan, controlObject, text); reg_t textReference = GET_SEL32(_segMan, controlObject, text);
Common::String text; Common::String text;
uint16 textSize, eventType, eventKey; uint16 textSize, eventType, eventKey;
bool textChanged = false; bool textChanged = false;
@ -148,18 +148,18 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg
if (textReference.isNull()) if (textReference.isNull())
error("kEditControl called on object that doesnt have a text reference"); error("kEditControl called on object that doesnt have a text reference");
text = segMan->getString(textReference); text = _segMan->getString(textReference);
if (!eventObject.isNull()) { if (!eventObject.isNull()) {
textSize = text.size(); textSize = text.size();
eventType = GET_SEL32V(segMan, eventObject, type); eventType = GET_SEL32V(_segMan, eventObject, type);
switch (eventType) { switch (eventType) {
case SCI_EVT_MOUSE_PRESS: case SCI_EVT_MOUSE_PRESS:
// TODO: Implement mouse support for cursor change // TODO: Implement mouse support for cursor change
break; break;
case SCI_EVT_KEYBOARD: case SCI_EVT_KEYBOARD:
eventKey = GET_SEL32V(segMan, eventObject, message); eventKey = GET_SEL32V(_segMan, eventObject, message);
switch (eventKey) { switch (eventKey) {
case SCI_K_BACKSPACE: case SCI_K_BACKSPACE:
if (cursorPos > 0) { if (cursorPos > 0) {
@ -203,9 +203,9 @@ void SciGuiControls::TexteditChange(SegManager *segMan, reg_t controlObject, reg
if (textChanged) { if (textChanged) {
GuiResourceId oldFontId = _text->GetFontId(); GuiResourceId oldFontId = _text->GetFontId();
GuiResourceId fontId = GET_SEL32V(segMan, controlObject, font); GuiResourceId fontId = GET_SEL32V(_segMan, controlObject, font);
rect = Common::Rect(GET_SEL32V(segMan, controlObject, nsLeft), GET_SEL32V(segMan, controlObject, nsTop), rect = Common::Rect(GET_SEL32V(_segMan, controlObject, nsLeft), GET_SEL32V(_segMan, controlObject, nsTop),
GET_SEL32V(segMan, controlObject, nsRight), GET_SEL32V(segMan, controlObject, nsBottom)); GET_SEL32V(_segMan, controlObject, nsRight), GET_SEL32V(_segMan, controlObject, nsBottom));
TexteditCursorErase(); TexteditCursorErase();
_gfx->EraseRect(rect); _gfx->EraseRect(rect);
_text->Box(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); _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); TexteditCursorDraw(rect, text.c_str(), cursorPos);
_text->SetFont(oldFontId); _text->SetFont(oldFontId);
// Write back string // Write back string
segMan->strcpy(textReference, text.c_str()); _segMan->strcpy(textReference, text.c_str());
} else { } else {
if (g_system->getMillis() >= _texteditBlinkTime) { if (g_system->getMillis() >= _texteditBlinkTime) {
_gfx->InvertRect(_texteditCursorRect); _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 } // End of namespace Sci

View file

@ -33,18 +33,19 @@ class SciGuiFont;
class SciGuiText; class SciGuiText;
class SciGuiControls { class SciGuiControls {
public: public:
SciGuiControls(SciGuiGfx *gfx, SciGuiText *text); SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text);
~SciGuiControls(); ~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 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 TexteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos);
void TexteditCursorErase(); void TexteditCursorErase();
void TexteditChange(SegManager *segMan, reg_t controlObject, reg_t eventObject); void TexteditChange(reg_t controlObject, reg_t eventObject);
private: private:
void init(); void init();
void TexteditSetBlinkTime(); void TexteditSetBlinkTime();
SegManager *_segMan;
SciGuiGfx *_gfx; SciGuiGfx *_gfx;
SciGuiText *_text; SciGuiText *_text;

View file

@ -53,8 +53,6 @@ public:
void init(SciGuiText *text); void init(SciGuiText *text);
void resetSegMan(SegManager *segMan) { _segMan = segMan; }
byte *GetSegment(byte seg); byte *GetSegment(byte seg);
void ResetScreen(); void ResetScreen();

View file

@ -408,7 +408,6 @@ void SciGui32::init(bool oldGfxFunctions) {
void SciGui32::resetEngineState(EngineState *s) { void SciGui32::resetEngineState(EngineState *s) {
_s = s; _s = s;
_gfx->resetSegMan(s->_segMan);
} }
void SciGui32::wait(int16 ticks) { void SciGui32::wait(int16 ticks) {

View file

@ -133,8 +133,10 @@ Common::Error SciEngine::run() {
_vocabulary = new Vocabulary(_resMan); _vocabulary = new Vocabulary(_resMan);
_audio = new AudioPlayer(_resMan); _audio = new AudioPlayer(_resMan);
SegManager *segMan = new SegManager(_resMan);
// We'll set the GUI below // 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)) if (script_init_engine(_gamestate))
return Common::kUnknownError; return Common::kUnknownError;
@ -181,15 +183,16 @@ Common::Error SciEngine::run() {
} }
_gamestate->_gui->init(_gamestate->usesOldGfxFunctions()); _gamestate->_gui->init(_gamestate->usesOldGfxFunctions());
_gamestate->_segMan = segMan;
debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str()); debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str());
game_run(&_gamestate); // Run the game game_run(&_gamestate); // Run the game
game_exit(_gamestate); game_exit(_gamestate);
script_free_engine(_gamestate); // Uninitialize game state
script_free_breakpoints(_gamestate); script_free_breakpoints(_gamestate);
delete segMan;
delete cursor; delete cursor;
delete palette; delete palette;
delete screen; delete screen;