mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-01 00:12:59 +00:00
SCI: Fixed bug #3034713 - "ICEMAN Demo: Fails to find base object"
This could happen because objects in scripts can be in the wrong order. Same thing happens in the French and German version of KQ5 (bug #3035396). Removed the scriptObjRemove() method, which is in fact a hack. svn-id: r54510
This commit is contained in:
parent
49afe9ccff
commit
3485d433c5
@ -194,17 +194,23 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
|
|||||||
|
|
||||||
for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) {
|
for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) {
|
||||||
reg_t addr = it->_value.getPos();
|
reg_t addr = it->_value.getPos();
|
||||||
Object *obj = scr->scriptObjInit(addr, false);
|
scr->scriptObjInit(addr, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (getSciVersion() < SCI_VERSION_1_1) {
|
// In SCI0-SCI1, we need to make two passes, as the objects in the
|
||||||
|
// script might be in the wrong order (e.g. in the demo of Iceman).
|
||||||
|
// Refer to bug #3034713
|
||||||
|
if (getSciVersion() < SCI_VERSION_1_1) {
|
||||||
|
for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) {
|
||||||
|
reg_t addr = it->_value.getPos();
|
||||||
|
Object *obj = scr->scriptObjInit(addr, false);
|
||||||
if (!obj->initBaseObject(this, addr, false)) {
|
if (!obj->initBaseObject(this, addr, false)) {
|
||||||
// TODO/FIXME: This should not be happening at all. It might indicate a possible issue
|
error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
|
||||||
// with the garbage collector. It happens for example in LSL5 (German, perhaps English too).
|
//scr->scriptObjRemove(addr);
|
||||||
warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
|
|
||||||
scr->scriptObjRemove(addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,13 +255,6 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::scriptObjRemove(reg_t obj_pos) {
|
|
||||||
if (getSciVersion() < SCI_VERSION_1_1)
|
|
||||||
obj_pos.offset += 8;
|
|
||||||
|
|
||||||
_objects.erase(obj_pos.toUint16());
|
|
||||||
}
|
|
||||||
|
|
||||||
// This helper function is used by Script::relocateLocal and Object::relocate
|
// This helper function is used by Script::relocateLocal and Object::relocate
|
||||||
// Duplicate in segment.cpp and script.cpp
|
// Duplicate in segment.cpp and script.cpp
|
||||||
static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
|
static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
|
||||||
@ -580,41 +573,41 @@ void Script::initialiseClasses(SegManager *segMan) {
|
|||||||
|
|
||||||
void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
|
void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
|
||||||
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
|
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
|
||||||
const byte *seeker = _buf + (oldScriptHeader ? 2 : 0);
|
|
||||||
|
|
||||||
do {
|
// We need to make two passes, as the objects in the script might be in the
|
||||||
uint16 objType = READ_SCI11ENDIAN_UINT16(seeker);
|
// wrong order (e.g. in the demo of Iceman) - refer to bug #3034713
|
||||||
if (!objType)
|
for (int pass = 1; pass <= 2; pass++) {
|
||||||
break;
|
const byte *seeker = _buf + (oldScriptHeader ? 2 : 0);
|
||||||
|
|
||||||
switch (objType) {
|
do {
|
||||||
case SCI_OBJ_OBJECT:
|
uint16 objType = READ_SCI11ENDIAN_UINT16(seeker);
|
||||||
case SCI_OBJ_CLASS:
|
if (!objType)
|
||||||
{
|
break;
|
||||||
reg_t addr = make_reg(segmentId, seeker - _buf + 4);
|
|
||||||
Object *obj = scriptObjInit(addr);
|
|
||||||
obj->initSpecies(segMan, addr);
|
|
||||||
|
|
||||||
if (!obj->initBaseObject(segMan, addr)) {
|
switch (objType) {
|
||||||
if ((_nr == 202 || _nr == 764) && g_sci->getGameId() == GID_KQ5) {
|
case SCI_OBJ_OBJECT:
|
||||||
// WORKAROUND: Script 202 of KQ5 French and German
|
case SCI_OBJ_CLASS:
|
||||||
// (perhaps Spanish too?) has an invalid object.
|
{
|
||||||
// This is non-fatal. Refer to bug #3035396.
|
reg_t addr = make_reg(segmentId, seeker - _buf + 4);
|
||||||
// Same happens with script 764, it seems to contain junk towards its end
|
Object *obj = scriptObjInit(addr);
|
||||||
} else {
|
obj->initSpecies(segMan, addr);
|
||||||
error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
|
|
||||||
|
if (pass == 2) {
|
||||||
|
if (!obj->initBaseObject(segMan, addr)) {
|
||||||
|
error("Failed to locate base object for object at %04X:%04X", PRINT_REG(addr));
|
||||||
|
//scriptObjRemove(addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scriptObjRemove(addr);
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
seeker += READ_SCI11ENDIAN_UINT16(seeker + 2);
|
||||||
break;
|
} while ((uint32)(seeker - _buf) < getScriptSize() - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
seeker += READ_SCI11ENDIAN_UINT16(seeker + 2);
|
|
||||||
} while ((uint32)(seeker - _buf) < getScriptSize() - 2);
|
|
||||||
|
|
||||||
byte *relocationBlock = findBlockSCI0(SCI_OBJ_POINTERS);
|
byte *relocationBlock = findBlockSCI0(SCI_OBJ_POINTERS);
|
||||||
if (relocationBlock)
|
if (relocationBlock)
|
||||||
|
@ -136,12 +136,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true);
|
Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a script object
|
|
||||||
* @param obj_pos Location (segment, offset) of the object.
|
|
||||||
*/
|
|
||||||
void scriptObjRemove(reg_t obj_pos);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the script's local variables
|
* Initializes the script's local variables
|
||||||
* @param segMan A reference to the segment manager
|
* @param segMan A reference to the segment manager
|
||||||
|
Loading…
x
Reference in New Issue
Block a user