mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 17:29:11 +00:00
Made the script initialization/uninitialization methods part of the segment manager
svn-id: r50402
This commit is contained in:
parent
456265f8fa
commit
4a60ff4090
@ -239,7 +239,7 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) {
|
||||
scr->setLockers(1);
|
||||
}
|
||||
|
||||
script_uninstantiate(s->_segMan, script);
|
||||
s->_segMan->uninstantiateScript(script);
|
||||
|
||||
if (argc != 2) {
|
||||
return s->r_acc;
|
||||
|
@ -519,109 +519,4 @@ void Script::initialiseObjectsSci11(SegManager *segMan) {
|
||||
}
|
||||
}
|
||||
|
||||
int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) {
|
||||
SegmentId segmentId = segMan->getScriptSegment(scriptNum);
|
||||
Script *scr = segMan->getScriptIfLoaded(segmentId);
|
||||
if (scr) {
|
||||
if (!scr->isMarkedAsDeleted()) {
|
||||
scr->incrementLockers();
|
||||
return segmentId;
|
||||
} else {
|
||||
scr->freeScript();
|
||||
}
|
||||
} else {
|
||||
scr = segMan->allocateScript(scriptNum, &segmentId);
|
||||
}
|
||||
|
||||
scr->init(scriptNum, resMan);
|
||||
scr->load(resMan);
|
||||
scr->initialiseLocals(segMan);
|
||||
scr->initialiseClasses(segMan);
|
||||
|
||||
if (getSciVersion() >= SCI_VERSION_1_1) {
|
||||
scr->initialiseObjectsSci11(segMan);
|
||||
scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart)));
|
||||
} else {
|
||||
scr->initialiseObjectsSci0(segMan);
|
||||
byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS);
|
||||
if (relocationBlock)
|
||||
scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4));
|
||||
}
|
||||
|
||||
return segmentId;
|
||||
}
|
||||
|
||||
void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) {
|
||||
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
|
||||
reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);
|
||||
int objType, objLength = 0;
|
||||
Script *scr = segMan->getScript(seg);
|
||||
|
||||
// Make a pass over the object in order uninstantiate all superclasses
|
||||
|
||||
do {
|
||||
reg.offset += objLength; // Step over the last checked object
|
||||
|
||||
objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset);
|
||||
if (!objType)
|
||||
break;
|
||||
objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2);
|
||||
|
||||
reg.offset += 4; // Step over header
|
||||
|
||||
if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class?
|
||||
reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
|
||||
int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2);
|
||||
|
||||
if (superclass >= 0) {
|
||||
int superclass_script = segMan->getClass(superclass).script;
|
||||
|
||||
if (superclass_script == script_nr) {
|
||||
if (scr->getLockers())
|
||||
scr->decrementLockers(); // Decrease lockers if this is us ourselves
|
||||
} else
|
||||
script_uninstantiate(segMan, superclass_script);
|
||||
// Recurse to assure that the superclass lockers number gets decreased
|
||||
}
|
||||
|
||||
reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
|
||||
} // if object or class
|
||||
|
||||
reg.offset -= 4; // Step back on header
|
||||
|
||||
} while (objType != 0);
|
||||
}
|
||||
|
||||
void script_uninstantiate(SegManager *segMan, int script_nr) {
|
||||
SegmentId segment = segMan->getScriptSegment(script_nr);
|
||||
Script *scr = segMan->getScriptIfLoaded(segment);
|
||||
|
||||
if (!scr) { // Is it already loaded?
|
||||
//warning("unloading script 0x%x requested although not loaded", script_nr);
|
||||
// This is perfectly valid SCI behaviour
|
||||
return;
|
||||
}
|
||||
|
||||
scr->decrementLockers(); // One less locker
|
||||
|
||||
if (scr->getLockers() > 0)
|
||||
return;
|
||||
|
||||
// Free all classtable references to this script
|
||||
for (uint i = 0; i < segMan->classTableSize(); i++)
|
||||
if (segMan->getClass(i).reg.segment == segment)
|
||||
segMan->setClassOffset(i, NULL_REG);
|
||||
|
||||
if (getSciVersion() < SCI_VERSION_1_1)
|
||||
script_uninstantiate_sci0(segMan, script_nr, segment);
|
||||
// FIXME: Add proper script uninstantiation for SCI 1.1
|
||||
|
||||
if (!scr->getLockers()) {
|
||||
// The actual script deletion seems to be done by SCI scripts themselves
|
||||
scr->markDeleted();
|
||||
debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Sci
|
||||
|
@ -250,30 +250,6 @@ public:
|
||||
byte *findBlock(int type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes sure that a script and its superclasses get loaded to the heap.
|
||||
* If the script already has been loaded, only the number of lockers is
|
||||
* increased. All scripts containing superclasses of this script are loaded
|
||||
* recursively as well, unless 'recursive' is set to zero. The
|
||||
* complementary function is "script_uninstantiate()" below.
|
||||
* @param[in] resMan The resource manager
|
||||
* @param[in] segMan The segment manager
|
||||
* @param[in] script_nr The script number to load
|
||||
* @return The script's segment ID or 0 if out of heap
|
||||
*/
|
||||
int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr);
|
||||
|
||||
/**
|
||||
* Decreases the numer of lockers of a script and unloads it if that number
|
||||
* reaches zero.
|
||||
* This function will recursively unload scripts containing its
|
||||
* superclasses, if those aren't locked by other scripts as well.
|
||||
* @param[in] segMan The segment manager
|
||||
* @param[in] version The SCI version to use
|
||||
* @param[in] script_nr The script number that is requestet to be unloaded
|
||||
*/
|
||||
void script_uninstantiate(SegManager *segMan, int script_nr);
|
||||
|
||||
} // End of namespace Sci
|
||||
|
||||
#endif // SCI_ENGINE_SCRIPT_H
|
||||
|
@ -361,7 +361,7 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) {
|
||||
SegmentId segment;
|
||||
|
||||
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
|
||||
script_instantiate(_resMan, this, script_nr);
|
||||
instantiateScript(script_nr);
|
||||
|
||||
segment = getScriptSegment(script_nr);
|
||||
|
||||
@ -991,4 +991,110 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller
|
||||
return the_class->reg;
|
||||
}
|
||||
}
|
||||
|
||||
int SegManager::instantiateScript(int scriptNum) {
|
||||
SegmentId segmentId = getScriptSegment(scriptNum);
|
||||
Script *scr = getScriptIfLoaded(segmentId);
|
||||
if (scr) {
|
||||
if (!scr->isMarkedAsDeleted()) {
|
||||
scr->incrementLockers();
|
||||
return segmentId;
|
||||
} else {
|
||||
scr->freeScript();
|
||||
}
|
||||
} else {
|
||||
scr = allocateScript(scriptNum, &segmentId);
|
||||
}
|
||||
|
||||
scr->init(scriptNum, _resMan);
|
||||
scr->load(_resMan);
|
||||
scr->initialiseLocals(this);
|
||||
scr->initialiseClasses(this);
|
||||
|
||||
if (getSciVersion() >= SCI_VERSION_1_1) {
|
||||
scr->initialiseObjectsSci11(this);
|
||||
scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart)));
|
||||
} else {
|
||||
scr->initialiseObjectsSci0(this);
|
||||
byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS);
|
||||
if (relocationBlock)
|
||||
scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4));
|
||||
}
|
||||
|
||||
return segmentId;
|
||||
}
|
||||
|
||||
void SegManager::uninstantiateScript(int script_nr) {
|
||||
SegmentId segmentId = getScriptSegment(script_nr);
|
||||
Script *scr = getScriptIfLoaded(segmentId);
|
||||
|
||||
if (!scr) { // Is it already unloaded?
|
||||
//warning("unloading script 0x%x requested although not loaded", script_nr);
|
||||
// This is perfectly valid SCI behaviour
|
||||
return;
|
||||
}
|
||||
|
||||
scr->decrementLockers(); // One less locker
|
||||
|
||||
if (scr->getLockers() > 0)
|
||||
return;
|
||||
|
||||
// Free all classtable references to this script
|
||||
for (uint i = 0; i < classTableSize(); i++)
|
||||
if (getClass(i).reg.segment == segmentId)
|
||||
setClassOffset(i, NULL_REG);
|
||||
|
||||
if (getSciVersion() < SCI_VERSION_1_1)
|
||||
uninstantiateScriptSci0(script_nr);
|
||||
// FIXME: Add proper script uninstantiation for SCI 1.1
|
||||
|
||||
if (!scr->getLockers()) {
|
||||
// The actual script deletion seems to be done by SCI scripts themselves
|
||||
scr->markDeleted();
|
||||
debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
|
||||
}
|
||||
}
|
||||
|
||||
void SegManager::uninstantiateScriptSci0(int script_nr) {
|
||||
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
|
||||
SegmentId segmentId = getScriptSegment(script_nr);
|
||||
Script *scr = getScript(segmentId);
|
||||
reg_t reg = make_reg(segmentId, oldScriptHeader ? 2 : 0);
|
||||
int objType, objLength = 0;
|
||||
|
||||
// Make a pass over the object in order uninstantiate all superclasses
|
||||
|
||||
do {
|
||||
reg.offset += objLength; // Step over the last checked object
|
||||
|
||||
objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset);
|
||||
if (!objType)
|
||||
break;
|
||||
objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2);
|
||||
|
||||
reg.offset += 4; // Step over header
|
||||
|
||||
if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class?
|
||||
reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
|
||||
int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2);
|
||||
|
||||
if (superclass >= 0) {
|
||||
int superclass_script = getClass(superclass).script;
|
||||
|
||||
if (superclass_script == script_nr) {
|
||||
if (scr->getLockers())
|
||||
scr->decrementLockers(); // Decrease lockers if this is us ourselves
|
||||
} else
|
||||
uninstantiateScript(superclass_script);
|
||||
// Recurse to assure that the superclass lockers number gets decreased
|
||||
}
|
||||
|
||||
reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
|
||||
} // if object or class
|
||||
|
||||
reg.offset -= 4; // Step back on header
|
||||
|
||||
} while (objType != 0);
|
||||
}
|
||||
|
||||
} // End of namespace Sci
|
||||
|
@ -117,6 +117,30 @@ public:
|
||||
*/
|
||||
SegmentId getScriptSegment(int script_nr, ScriptLoadType load);
|
||||
|
||||
/**
|
||||
* Makes sure that a script and its superclasses get loaded to the heap.
|
||||
* If the script already has been loaded, only the number of lockers is
|
||||
* increased. All scripts containing superclasses of this script are loaded
|
||||
* recursively as well, unless 'recursive' is set to zero. The
|
||||
* complementary function is "uninstantiateScript()" below.
|
||||
* @param[in] script_nr The script number to load
|
||||
* @return The script's segment ID or 0 if out of heap
|
||||
*/
|
||||
int instantiateScript(int script_nr);
|
||||
|
||||
/**
|
||||
* Decreases the numer of lockers of a script and unloads it if that number
|
||||
* reaches zero.
|
||||
* This function will recursively unload scripts containing its
|
||||
* superclasses, if those aren't locked by other scripts as well.
|
||||
* @param[in] script_nr The script number that is requestet to be unloaded
|
||||
*/
|
||||
void uninstantiateScript(int script_nr);
|
||||
|
||||
private:
|
||||
void uninstantiateScriptSci0(int script_nr);
|
||||
|
||||
public:
|
||||
// TODO: document this
|
||||
reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller);
|
||||
|
||||
|
@ -420,7 +420,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
|
||||
Script *scr = s->_segMan->getScriptIfLoaded(seg);
|
||||
|
||||
if (!scr || scr->isMarkedAsDeleted()) { // Script not present yet?
|
||||
seg = script_instantiate(g_sci->getResMan(), s->_segMan, script);
|
||||
seg = s->_segMan->instantiateScript(script);
|
||||
scr = s->_segMan->getScript(seg);
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,7 @@ bool SciEngine::initGame() {
|
||||
_gamestate->stack_base = stack->_entries;
|
||||
_gamestate->stack_top = stack->_entries + stack->_capacity;
|
||||
|
||||
if (!script_instantiate(_resMan, _gamestate->_segMan, 0)) {
|
||||
if (!_gamestate->_segMan->instantiateScript(0)) {
|
||||
error("initGame(): Could not instantiate script 0");
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user