Spring Direction Fix - RetroKoH/S1Fixed GitHub Wiki

(Original guide by RetroKoH)
Source: Sonic Retro post
Original Commit: 9680c59
Updated Commit: af48d27

There is a very obscure bug that exists in Sonic 1 involving the Horizontal Spring. If you walk backwards into a horizontal spring, it will still launch you in the correct direction, but you'll face away from where you are running. This bug is fixed in Sonic 2 onward, so let's fix it here. There are two nearly identical ways to fix it. I'm going to show you how Sonic 2 fixes it, then I'm going to show you how I originally fixed it when I first observed this bug. I highly recommend the Sonic 2 method, as it is cleaner and more efficient, but both fixes yield the exact same result. Either way, we're opening _incObj\41 Springs.asm, and going to the Spring_BounceLR: label.

Sonic 2 Fix

Sonic 2 fixes this minor bug by adding two lines like so:

Spring_BounceLR:
	addq.b	#2,obRoutine(a0)
	move.w	spring_pow(a0),obVelX(a1)	; move Sonic to the left
	addq.w	#8,obX(a1)
+	bset	#staFacing,obStatus(a1)		; set Sonic facing to the left
	btst	#staFlipX,obStatus(a0)		; is object flipped?
	bne.s	Spring_Flipped			; if yes, branch
+	bclr	#staFacing,obStatus(a1)		; set Sonic facing to the right
	subi.w	#$10,obX(a1)
	neg.w	obVelX(a1)			; move Sonic to	the right

Spring_Flipped:
	move.w	#$F,obLRLock(a1)
	move.w	obVelX(a1),obInertia(a1)
-	bchg	#staFacing,obStatus(a1)		; remove this line

This is a fairly simple fix, because the code already checks to see if the spring is facing right or left, and sets Sonic's speed accordingly. All we did was set Sonic to face the same direction that he's set to run in. The line we removed under Spring_Flipped: would simply change the facing bit, regardless of which way the spring meant to send Sonic in. This is why the bug existed in the first place.

RetroKoH Fix

So, when I first observed this bug, I went right to the bchg instruction, and changed code there. At the time, I hadn't thought to inspect Sonic 2's code and just threw together a quick fix. Here's what I did in the original commit. It's not recommended to use this fix, as this is far less efficient than the method noted above.

Spring_Flipped:
	move.w	#$F,obLRLock(a1)
	move.w	obVelX(a1),obInertia(a1)
+	tst.w	obVelX(a1)
+	bmi.s	Face_Left			; if Sonic is running left, branch
+	bclr	#staFacing,obStatus(a1)		; set Sonic facing to the right
+	bra.s	Face_Cont
-	bchg	#staFacing,obStatus(a1)		; Removed this
+Face_Left:
+	bset	#staFacing,obStatus(a1)		; set Sonic facing to the left
+Face_Cont: