diff options
Diffstat (limited to 'engines/sci/engine/kmovement.cpp')
-rw-r--r-- | engines/sci/engine/kmovement.cpp | 58 |
1 files changed, 26 insertions, 32 deletions
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 3c516f63f2..49d2900835 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -166,17 +166,6 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// TODO/FIXME: There is a notable regression with the new kInitBresed/kDoBresen -// functions below in a death scene of LB1 - the shower scene, room 215 (bug -// #3122075). There is a hack to get around this bug by modifying the actor's -// position for that scene in kScriptID. The actual bug should be found, but -// since only this death scene has an issue, it's not really worth the effort. -// The new kInitBresen/kDoBresen functions have been enabled in r52467. The -// old ones are based on observations, so there are many differences in the -// way that they behave. Check the hack in kScriptID for more info. Note that -// the actual issue might not be with kInitBresen/kDoBresen, and there might -// be another underlying problem here. - reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) { SegManager *segMan = s->_segMan; reg_t mover = argv[0]; @@ -275,7 +264,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { bool completed = false; bool handleMoveCount = g_sci->_features->handleMoveCount(); - if (getSciVersion() >= SCI_VERSION_1_EGA) { + if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) { uint client_signal = readSelectorValue(segMan, client, SELECTOR(signal)); writeSelectorValue(segMan, client, SELECTOR(signal), client_signal & ~kSignalHitObstacle); } @@ -292,8 +281,6 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { mover_moveCnt = 0; int16 client_x = readSelectorValue(segMan, client, SELECTOR(x)); int16 client_y = readSelectorValue(segMan, client, SELECTOR(y)); - int16 client_org_x = client_x; - int16 client_org_y = client_y; int16 mover_x = readSelectorValue(segMan, mover, SELECTOR(x)); int16 mover_y = readSelectorValue(segMan, mover, SELECTOR(y)); int16 mover_xAxis = readSelectorValue(segMan, mover, SELECTOR(b_xAxis)); @@ -307,12 +294,19 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { int16 mover_org_i2 = mover_i2; int16 mover_org_di = mover_di; - if ((getSciVersion() >= SCI_VERSION_1_EGA)) { + if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) { // save current position into mover writeSelectorValue(segMan, mover, SELECTOR(xLast), client_x); writeSelectorValue(segMan, mover, SELECTOR(yLast), client_y); } - // sierra sci saves full client selector variables here + + // Store backups of all client selector variables. We will restore them + // in case of a collision. + Object* clientObject = segMan->getObject(client); + uint clientVarNum = clientObject->getVarCount(); + reg_t* clientBackup = new reg_t[clientVarNum]; + for (uint i = 0; i < clientVarNum; ++i) + clientBackup[i] = clientObject->getVariable(i); if (mover_xAxis) { if (ABS(mover_x - client_x) < ABS(mover_dx)) @@ -360,9 +354,10 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { } if (collision) { - // sierra restores full client variables here, seems that restoring x/y is enough - writeSelectorValue(segMan, client, SELECTOR(x), client_org_x); - writeSelectorValue(segMan, client, SELECTOR(y), client_org_y); + // We restore the backup of the client variables + for (uint i = 0; i < clientVarNum; ++i) + clientObject->getVariableRef(i) = clientBackup[i]; + mover_i1 = mover_org_i1; mover_i2 = mover_org_i2; mover_di = mover_org_di; @@ -370,30 +365,29 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { uint16 client_signal = readSelectorValue(segMan, client, SELECTOR(signal)); writeSelectorValue(segMan, client, SELECTOR(signal), client_signal | kSignalHitObstacle); } + delete[] clientBackup; + writeSelectorValue(segMan, mover, SELECTOR(b_i1), mover_i1); writeSelectorValue(segMan, mover, SELECTOR(b_i2), mover_i2); writeSelectorValue(segMan, mover, SELECTOR(b_di), mover_di); - if ((getSciVersion() >= SCI_VERSION_1_EGA)) { - // this calling code here was right before the last return in - // sci1ega and got changed to this position since sci1early - // this was an uninitialized issue in sierra sci - if ((handleMoveCount) && (getSciVersion() >= SCI_VERSION_1_EARLY)) + if (getSciVersion() >= SCI_VERSION_1_EGA_ONLY) { + // In sci1egaonly this block of code was outside of the main if, + // but client_x/client_y aren't set there, so it was an + // uninitialized read in SSCI. (This issue was fixed in sci1early.) + if (handleMoveCount) writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt); // We need to compare directly in here, complete may have happened during // the current move if ((client_x == mover_x) && (client_y == mover_y)) invokeSelector(s, mover, SELECTOR(moveDone), argc, argv); - if (getSciVersion() >= SCI_VERSION_1_EARLY) - return s->r_acc; + return s->r_acc; } } - if (handleMoveCount) { - if (getSciVersion() <= SCI_VERSION_1_EGA) - writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt); - else - writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), client_moveSpeed); - } + + if (handleMoveCount) + writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt); + return s->r_acc; } |