diff options
| author | Martin Kiewitz | 2010-08-30 14:06:18 +0000 | 
|---|---|---|
| committer | Martin Kiewitz | 2010-08-30 14:06:18 +0000 | 
| commit | d02628a0dcbade4419c6c653cb65899b98c9cb86 (patch) | |
| tree | eea456a5d5c3076585e25609960f1d7d7e3cf992 | |
| parent | 80b405ecb47c2bc088ce90453d888aaf22fe7d22 (diff) | |
| download | scummvm-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.cpp | 213 | 
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); | 
