SCI: created a workaround table for uninitialized reads, removing old commented out workarounds for pharkas and laura bow 2

svn-id: r50214
This commit is contained in:
Martin Kiewitz 2010-06-24 13:17:45 +00:00
parent 898c9165d9
commit e45ffc68a3
3 changed files with 41 additions and 38 deletions

View File

@ -639,7 +639,6 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
// This here is needed to make Pharkas work
reg_t kPalVary(EngineState *s, int argc, reg_t *argv) {
uint16 operation = argv[0].toUint16();
@ -1041,26 +1040,6 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) {
bool hiresMode = (argc > 7) ? true : false;
reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG;
#if 0
if (g_sci->getGameId() == "freddypharkas") {
// WORKAROUND
// Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that
// is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would
// get 0 here resulting in broken menus.
if ((viewId == 995) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // game menu
priority = 15;
if ((viewId == 992) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // quit game
priority = 15;
}
if (g_sci->getGameId() == "laurabow2") {
// WORKAROUND
// see the one above
if ((viewId == 995) && (priority == 0))
priority = 15;
}
#endif
g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle);
return s->r_acc;

View File

@ -183,16 +183,21 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in
return true;
}
static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = {
{ "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu
{ "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu
{ "islandbrain", 140, "piece", "init", 3, 0 }, // currently unknown, new value is not right
{ "", -1, "", "", 0, 0 }
};
static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) {
if (validate_variable(r, stack_base, type, max, index, line)) {
if (type == VAR_TEMP && r[index].segment == 0xffff) {
// Uninitialized read on a temp
// We need to find correct replacements for each situation manually
// FIXME: this should use a table which contains workarounds for gameId, scriptnumber and temp index and
// a replacement value
EngineState *engine = g_sci->getEngineState();
Script *local_script = engine->_segMan->getScriptIfLoaded(engine->xs->local_segment);
int currentScriptNr = local_script->_nr;
int curScriptNr = local_script->_nr;
Common::List<ExecStack>::iterator callIterator = engine->_executionStack.begin();
ExecStack call = *callIterator;
@ -201,24 +206,34 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i
callIterator++;
}
const char *objName = engine->_segMan->getObjectName(call.sendp);
const char *selectorName = "";
const char *curObjectName = engine->_segMan->getObjectName(call.sendp);
const char *curMethodName = "";
if (call.type == EXEC_STACK_TYPE_CALL) {
selectorName = g_sci->getKernel()->getSelectorName(call.selector).c_str();
curMethodName = g_sci->getKernel()->getSelectorName(call.selector).c_str();
}
warning("uninitialized read for temp %d from method %s::%s (script %d)", index, objName, selectorName, currentScriptNr);
warning("uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName, curMethodName, curScriptNr);
Common::String gameId = g_sci->getGameId();
if ((gameId == "laurabow2") && (currentScriptNr == 24) && (index == 5))
return make_reg(0, 0xf); // priority replacement for menu - gcWin::open
if ((gameId == "freddypharkas") && (currentScriptNr == 24) && (index == 5))
return make_reg(0, 0xf); // priority replacement for menu - gcWin::open
if ((gameId == "islandbrain") && (currentScriptNr == 140) && (index == 3)) {
// piece::init
//r[index] = make_reg(0, 255);
//return r[index];
const char *gameId = g_sci->getGameId().c_str();
// Search if this is a known uninitialized read
const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds;
while (workaround->gameId) {
if (strcmp(workaround->gameId, gameId) == 0) {
if (workaround->scriptNr == curScriptNr) {
if (strcmp(workaround->objectName, curObjectName) == 0) {
if (strcmp(workaround->methodName, curMethodName) == 0) {
if (workaround->index == index) {
// Workaround found
r[index] = make_reg(0, workaround->newValue);
return r[index];
}
}
}
}
}
workaround++;
}
error("uninitialized read!");
error("unknown uninitialized read!");
}
return r[index];
} else

View File

@ -109,6 +109,15 @@ struct ExecStack {
reg_t* getVarPointer(SegManager *segMan) const;
};
struct UninitializedReadWorkaround {
const char *gameId;
int scriptNr;
const char *objectName;
const char *methodName;
int index;
uint16 newValue;
};
enum {
VAR_GLOBAL = 0,
VAR_LOCAL = 1,