RAM Clearing Fixes - RetroKoH/S1Fixed GitHub Wiki

(Original guide; Original PSB Fix by Quickman)
Sources: s1disasm, SCHG Page
Commits: b61e13a, 68f00fc, 67a52f2
(NOTE: This fix is handled in Sonic Retro's s1disasm by FixBugs)

In various parts of Sonic 1, RAM needs to be cleared for future use. Unfortunately, it's not always cleared properly, due to either too much or too little RAM being cleared, which can sometimes lead to errors. It's not known why RAM wasn't properly cleared in these instances, but we can fix these issues without too much effort.

NOTE: Throughout the modern disassembly, mass RAM clearing is handled by a macro called clearRAM. The syntax of this macros is as follows:

	clearRAM	startAddress,endAddress

Use of this macro results in the following code being placed into that section of the ROM:

	lea	(startAddress).w,a1	; load target RAM to be cleared to a1
	moveq	#0,d0			; clear register d0
	move.w	#.length/4-1,d1		; load (number of longwords)-1 to d1

.loop:
	move.l	d0,(a1)+		; clear a longword (4 bytes) of target RAM
	dbf	d1,.loop		; repeat for total number of longwords

	if (endAddress-startAddress)&2
		move.w	d0,(a1)+	; if a word (2 bytes) remains, clear it
	endif

	if (endAddress-startAddress)&1
		move.b	d0,(a1)+	; if a single byte remains, clear it
	endif

Now that we know what the macro is, all we need to do is make sure that for each macro call, the startAddress and endAddress given are correct.

ClearScreen

Open sonic.asm and go to ClearScreen. We will find our macro called twice. There is a +4 tacked on to the end of the endAddress, because the original Sonic 1 ROM cleared 4 extra bytes of RAM. All we need to do is remove those +4s.

PRESS START BUTTON

In the same file, move down to Tit_LoadText and search for the following macro call:

clearRAM v_sonicteam,v_sonicteam+object_size/2

All we need to do is remove the /2. This particular edit fixes the PRESS START BUTTON object, allowing it to appear.

S1 Object Manager Bug

This particular fix doesn't make use of the the clearRAM macro, unlike the others. Also, this fix applies to the Objects Manager of the original Sonic 1. If you updated the Objects Manager to Sonic 2 or Sonic 3K, this probably won't apply.

OPL_Main:
	addq.b	#2,(v_opl_routine).w
	move.w	(v_zone).w,d0
	lsl.b	#6,d0
	lsr.w	#4,d0
	lea	(ObjPos_Index).l,a0
	movea.l	a0,a1
	adda.w	(a0,d0.w),a0
	move.l	a0,(v_opl_data).w
	move.l	a0,(v_opl_data+4).w
	adda.w	2(a1,d0.w),a1
	move.l	a1,(v_opl_data+8).w
	move.l	a1,(v_opl_data+$C).w
	lea	(v_objstate).w,a2
	move.w	#$101,(a2)+
!	move.w	#(v_objstate_end-v_objstate-2)/4-1,d0	; Clear $BE bytes instead of $17C.

OPL_ClrList:
	clr.l	(a2)+
	dbf	d0,OPL_ClrList	; clear	pre-destroyed object list
		
+	if (v_objstate_end-v_objstate-2)&2
+		clr.w	(a2)+	; Clear the last word, since the above loop only does longwords.
+	endif

Adding the lines in green (which FixBugs already does for you) prevents OPL_ClrList from clearing too much RAM. The problem here was that the actual clear code cleared RAM in longwords (4 bytes), but the count loaded to d0 treated it as though it was clearing words (2 bytes) instead of longwords.