Lives Over Underflow Fix - RetroKoH/S1Fixed GitHub Wiki

(Original guide by Mercury)
Source: ReadySonic
Commit: 7c4f8bc

Throughout the game, Sonic can earn extra lives through various means. That's great, because he can also lose lives in many ways as well. In the case of the latter, it's to be expected that when Sonic hits zero (0) lives, it means Game Over, and that's that. However, there are a few rare instances where that's not the case, and the lives counter can underflow to 255 lives, allowing continued play with an insane number of lives. If this happens, and you gain another extra life, expect the counter to tick back up to 0, due to an overflow. Ideally, we want to clamp the lives count to a range of 0-99, where death with 0 lives remaining means Game Over, and numbers above 99 are unobtainable (due to the lives counter only supporting 2 digits). There are a few places in the game's code where Sonic can gain extra lives. We need to go to each of these and ensure that this clamp is put in place at each instance.

Collecting 100/200 Rings (Overflow Fix)

Go to _incObj/25 & 37 Rings.asm and find label .got100:.
The changes we make here will be much the same as the ones we make everywhere else in the ROM, and they look like such:

.got100:
+	cmpi.b	#99,(v_lives).w		; are lives at max?
+	beq.s	.playbgm
	addq.b	#1,(v_lives).w		; add 1 to number of lives
	addq.b	#1,(f_lifecount).w	; update the lives counter
+.playbgm:
	move.w	#bgm_ExtraLife,d0	; play extra life music

.playsnd:
	jmp	(PlaySound_Special).l

Hitting 1-Up Monitors (Overflow Fix)

Go to _incObj/2E Monitor Content Power-Up.asm and find label ExtraLife:.

ExtraLife:
+	cmpi.b	#99,(v_lives).w		; are lives at max?
+	beq.s	.playbgm
	addq.b	#1,(v_lives).w		; add 1 to number of lives
	addq.b	#1,(f_lifecount).w	; update the lives counter
+.playbgm:
	move.w	#bgm_ExtraLife,d0	; play extra life music
	jmp	(PlaySound).l

Gaining 50000 points (Overflow Fix)

Go to sonic.asm and find label AddPoints:. Go down to where you see an increase to v_scorelife.

	addi.l  #5000,(v_scorelife).w	; increase requirement by 50000
	tst.b   (v_megadrive).w
	bmi.s   .noextralife		; branch if Mega Drive is Japanese

+	cmpi.b	#99,(v_lives).w		; are lives at max?
+	beq.s	.playbgm
	addq.b	#1,(v_lives).w		; add 1 to number of lives
	addq.b	#1,(f_lifecount).w	; update the lives counter

+.playbgm:
	move.w	#bgm_ExtraLife,d0
	jmp	(PlaySound).l

Special Stage 1-Up Icon (Overflow Fix)

This one probably isn't necessary unless you plan on using the 1-Up icon. Go to _incObj/09 Sonic in Special Stage.asm and find the label Obj09_Get1Up:. We're making a similar change here too.

ExtraLife:
+	cmpi.b	#99,(v_lives).w		; are lives at max?
+	beq.s	.playbgm
	addq.b	#1,(v_lives).w		; add 1 to number of lives
	addq.b	#1,(f_lifecount).w	; update the lives counter

+.playbgm:
	move.w	#bgm_ExtraLife,d0
	jsr	(PlaySound).l		; play extra life music
	moveq	#0,d4
	rts

Losing a Life (Underflow Fix)

Go to _incObj/Sonic (part 2).asm and go to the label GameOver:. We'll add a similar check to see if we are at 0 lives before taking a life away.

GameOver:
		move.w	(v_screenposy).w,d0	; Mercury Game/Time Over Timing Fix
		addi.w	#$100,d0
		cmp.w	obY(a0),d0
		bge.w	locret_13900		; Mercury Game/Time Over Timing Fix
		move.w	#-$38,obVelY(a0)
		addq.b	#2,obRoutine(a0)
		clr.b	(f_timecount).w		; stop time counter

+		tst.b	(v_lives).w		; are lives at min?
+		beq.s	.skip
		addq.b	#1,(f_lifecount).w	; update lives counter
		subq.b	#1,(v_lives).w		; subtract 1 from number of lives
		bne.s	loc_138D4
+.skip:
		clr.w	objoff_3A(a0)
		move.b	#id_GameOverCard,(v_gameovertext1).w ; load GAME object
		move.b	#id_GameOverCard,(v_gameovertext2).w ; load OVER object