aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2010-08-30 14:06:18 +0000
committerMartin Kiewitz2010-08-30 14:06:18 +0000
commitd02628a0dcbade4419c6c653cb65899b98c9cb86 (patch)
treeeea456a5d5c3076585e25609960f1d7d7e3cf992
parent80b405ecb47c2bc088ce90453d888aaf22fe7d22 (diff)
downloadscummvm-rg350-d02628a0dcbade4419c6c653cb65899b98c9cb86.tar.gz
scummvm-rg350-d02628a0dcbade4419c6c653cb65899b98c9cb86.tar.bz2
scummvm-rg350-d02628a0dcbade4419c6c653cb65899b98c9cb86.zip
SCI: freshly reversed kDoBresen/kInitBresen
fixes qfg2 walking against wall, etc. BUT its currently disabled by default. You need to comment out the #define USE_OLD_BRESEN line in kmovement.cpp svn-id: r52453
-rw-r--r--engines/sci/engine/kmovement.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index 2ef1dce671..0bac90886d 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -166,6 +166,9 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+#define USE_OLD_BRESEN 1
+
+#ifdef USE_OLD_BRESEN
#define _K_BRESEN_AXIS_X 0
#define _K_BRESEN_AXIS_Y 1
@@ -229,7 +232,216 @@ reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+#endif
+
+#ifndef USE_OLD_BRESEN
+reg_t kInitBresen(EngineState *s, int argc, reg_t *argv) {
+ SegManager *segMan = s->_segMan;
+ reg_t mover = argv[0];
+ reg_t client = readSelector(segMan, mover, SELECTOR(client));
+ int16 stepFactor = (argc >= 2) ? argv[1].toUint16() : 1;
+ int16 mover_x = readSelectorValue(segMan, mover, SELECTOR(x));
+ int16 mover_y = readSelectorValue(segMan, mover, SELECTOR(y));
+ int16 client_xStep = readSelectorValue(segMan, client, SELECTOR(xStep)) * stepFactor;
+ int16 client_yStep = readSelectorValue(segMan, client, SELECTOR(yStep)) * stepFactor;
+
+ int16 client_step;
+ if (client_xStep < client_yStep)
+ client_step = client_yStep * 2;
+ else
+ client_step = client_xStep * 2;
+
+ int16 deltaX = mover_x - readSelectorValue(segMan, client, SELECTOR(x));
+ int16 deltaY = mover_y - readSelectorValue(segMan, client, SELECTOR(y));
+ int16 mover_dx = 0;
+ int16 mover_dy = 0;
+ int16 mover_i1 = 0;
+ int16 mover_i2 = 0;
+ int16 mover_di = 0;
+ int16 mover_incr = 0;
+ int16 mover_xAxis = 0;
+
+ while (1) {
+ mover_dx = client_xStep;
+ mover_dy = client_yStep;
+ mover_incr = 1;
+
+ if (ABS(deltaX) >= ABS(deltaY)) {
+ mover_xAxis = 1;
+ if (deltaX < 0)
+ mover_dx = -mover_dx;
+ mover_dy = deltaX ? mover_dx * deltaY / deltaX : 0;
+ mover_i1 = ((mover_dx * deltaY) - (mover_dy * deltaX)) * 2;
+ if (deltaY < 0) {
+ mover_incr = -1;
+ mover_i1 = -mover_i1;
+ }
+ mover_i2 = mover_i1 - (deltaX * 2);
+ mover_di = mover_i1 - deltaX;
+ if (deltaX < 0) {
+ mover_i1 = -mover_i1;
+ mover_i2 = -mover_i2;
+ mover_di = -mover_di;
+ }
+ } else {
+ mover_xAxis = 0;
+ if (deltaY < 0)
+ mover_dy = -mover_dy;
+ mover_dx = deltaY ? mover_dy * deltaX / deltaY : 0;
+ mover_i1 = ((mover_dy * deltaX) - (mover_dx * deltaY)) * 2;
+ if (deltaX < 0) {
+ mover_incr = -1;
+ mover_i1 = -mover_i1;
+ }
+ mover_i2 = mover_i1 - (deltaY * 2);
+ mover_di = mover_i1 - deltaY;
+ if (deltaY < 0) {
+ mover_i1 = -mover_i1;
+ mover_i2 = -mover_i2;
+ mover_di = -mover_di;
+ }
+ break;
+ }
+ if (client_xStep <= client_yStep)
+ break;
+ if (!client_xStep)
+ break;
+ if (client_yStep >= ABS(mover_dy + mover_incr))
+ break;
+
+ client_step--;
+ if (!client_step)
+ error("kInitBresen failed");
+ client_xStep--;
+ }
+
+ // set mover
+ writeSelectorValue(segMan, mover, SELECTOR(dx), mover_dx);
+ writeSelectorValue(segMan, mover, SELECTOR(dy), mover_dy);
+ writeSelectorValue(segMan, mover, SELECTOR(b_i1), mover_i1);
+ writeSelectorValue(segMan, mover, SELECTOR(b_i2), mover_i2);
+ writeSelectorValue(segMan, mover, SELECTOR(b_di), mover_di);
+ writeSelectorValue(segMan, mover, SELECTOR(b_incr), mover_incr);
+ writeSelectorValue(segMan, mover, SELECTOR(b_xAxis), mover_xAxis);
+ return s->r_acc;
+}
+#endif
+
+#ifndef USE_OLD_BRESEN
+reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
+ SegManager *segMan = s->_segMan;
+ reg_t mover = argv[0];
+ reg_t client = readSelector(segMan, mover, SELECTOR(client));
+ bool completed = false;
+
+ if (getSciVersion() >= SCI_VERSION_1_EGA) {
+ uint client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
+ writeSelectorValue(segMan, client, SELECTOR(signal), client_signal & ~kSignalHitObstacle);
+ }
+
+ int16 mover_moveCnt = readSelectorValue(segMan, mover, SELECTOR(b_movCnt));
+ int16 client_moveSpeed = readSelectorValue(segMan, client, SELECTOR(moveSpeed));
+
+ mover_moveCnt++;
+ if (client_moveSpeed < mover_moveCnt) {
+ 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));
+ int16 mover_dx = readSelectorValue(segMan, mover, SELECTOR(dx));
+ int16 mover_dy = readSelectorValue(segMan, mover, SELECTOR(dy));
+ int16 mover_incr = readSelectorValue(segMan, mover, SELECTOR(b_incr));
+ int16 mover_i1 = readSelectorValue(segMan, mover, SELECTOR(b_i1));
+ int16 mover_i2 = readSelectorValue(segMan, mover, SELECTOR(b_i2));
+ int16 mover_di = readSelectorValue(segMan, mover, SELECTOR(b_di));
+ int16 mover_org_i1 = mover_i1;
+ int16 mover_org_i2 = mover_i2;
+ int16 mover_org_di = mover_di;
+
+ if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
+ // 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
+
+ if (mover_xAxis) {
+ if (ABS(mover_x - client_x) < ABS(mover_dx))
+ completed = true;
+ } else {
+ if (ABS(mover_y - client_y) < ABS(mover_dy))
+ completed = true;
+ }
+ if (completed) {
+ client_x = mover_x;
+ client_y = mover_y;
+ } else {
+ client_x += mover_dx;
+ client_y += mover_dy;
+ if (mover_di < 0) {
+ mover_di += mover_i1;
+ } else {
+ mover_di += mover_i2;
+ if (mover_xAxis == 0) {
+ client_x += mover_incr;
+ } else {
+ client_y += mover_incr;
+ }
+ }
+ }
+ writeSelectorValue(segMan, client, SELECTOR(x), client_x);
+ writeSelectorValue(segMan, client, SELECTOR(y), client_y);
+
+ // Now call client::canBeHere/client::cantBehere to check for collisions
+ bool collision = false;
+ reg_t cantBeHere = NULL_REG;
+
+ if (SELECTOR(cantBeHere) != -1) {
+ // adding this here for hoyle 3 to get happy. CantBeHere is a dummy in hoyle 3 and acc is != 0 so we would
+ // get a collision otherwise
+ s->r_acc = NULL_REG;
+ invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv);
+ if (!s->r_acc.isNull())
+ collision = true;
+ cantBeHere = s->r_acc;
+ } else {
+ invokeSelector(s, client, SELECTOR(canBeHere), argc, argv);
+ if (s->r_acc.isNull())
+ collision = true;
+ }
+
+ 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);
+ mover_i1 = mover_org_i1;
+ mover_i2 = mover_org_i2;
+ mover_di = mover_org_di;
+
+ uint16 client_signal = readSelectorValue(segMan, client, SELECTOR(signal));
+ writeSelectorValue(segMan, client, SELECTOR(signal), client_signal | kSignalHitObstacle);
+ }
+ writeSelectorValue(segMan, mover, SELECTOR(b_i1), mover_i1);
+ writeSelectorValue(segMan, mover, SELECTOR(b_i2), mover_i2);
+ writeSelectorValue(segMan, mover, SELECTOR(b_di), mover_di);
+ }
+ writeSelectorValue(segMan, mover, SELECTOR(b_movCnt), mover_moveCnt);
+ if ((getSciVersion() >= SCI_VERSION_1_EGA)) {
+ // Sierra SCI compared client_x&mover_x and client_y&mover_y
+ // those variables were not initialized in case the moveSpeed
+ // compare failed
+ if (completed)
+ invokeSelector(s, mover, SELECTOR(moveDone), argc, argv);
+ }
+ return s->r_acc;
+}
+#endif
+#ifdef USE_OLD_BRESEN
#define MOVING_ON_X (((axis == _K_BRESEN_AXIS_X)&&bi1) || dx)
#define MOVING_ON_Y (((axis == _K_BRESEN_AXIS_Y)&&bi1) || dy)
@@ -357,6 +569,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
return cantBeHere;
return make_reg(0, completed);
}
+#endif
extern void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int argc, reg_t *argv);