Actions

SCHG How-to

Free Up Ram In Sonic 1

From Sonic Retro

In Sonic 1, free ram isn't hard to come by but if you are planning to add Sonic 3's object manager or other stuff this guide is for you!

Method 1 Using Uncompressed Chunks

Free RAM After $0000-$A3FF

Since the game normally stores compressed data, we need to change it to store uncompressed data instead. For example, for Green Hill Zone, replace this:

Blk256_GHZ:	incbin	map256\ghz.bin
		even

with this:

Blk256_GHZ:	incbin	map256_u\ghz.bin
		even

Note that if you're using SonED2 you'll have to change this.

Metatile Compression:  1


Change it to 0.

If you're using SonLVL, and want all levels to load chunks from ROM, open SonLVL.ini and add the line:
chunkcmp=Uncompressed
before the first level's section. If you only want to change specific levels, add that line in the sections for each act of the level(s).

Then replace each instance of "chunks=../map256/" with "chunks=../map256_u/" in each level you want to load chunks from ROM.

Skipping loading chunks to RAM (title screen)

If you decide to read the chunks from ROM for Green Hill Zone and you still use the Green Hill Zone data for your title screen, you should skip decompressing the chunks to avoid overwriting other data in RAM. Go to Title_LoadText and find the following lines:

		lea	(Blk256_GHZ).l,a0 ; load GHZ 256x256 mappings
		lea	($FF0000).l,a1
		bsr.w	KosDec

Comment them out or delete them.

Skipping loading chunks to RAM (levels and ending sequence)

In MainLoadBlockLoad, the chunks data, amongst others, is decompressed to RAM. We are going to disable this. Find the following lines:

		lea	($FF0000).l,a1	; RAM address for 256x256 mappings
		bsr.w	KosDec

and replace them with the following:

		tst.b	($FFFFFE10).w	; are we in Green Hill Zone?
		beq.s	@no_dec		; if yes, branch
		cmpi.b	#6,($FFFFFE10).w ; are we in the ending sequence?
		beq.s	@no_dec		; if yes, branch
		lea	($FF0000).l,a1	; RAM address for 256x256 mappings
		bsr.w	KosDec

@no_dec:

Fixing art

The chunks are composed of blocks, which contain art tiles. Since the chunks are not in RAM anymore, you will get empty levels. Go to sub_6BD6 (loc_712C if you followed this guide) and replace the code from

		moveq	#-1,d3

to

		rts

with the following:

		tst.b	($FFFFFE10).w	; are we in Green Hill Zone?
		beq.s	@ghz		; if yes, branch
		cmpi.b	#6,($FFFFFE10).w ; are we in the ending sequence?
		beq.s	@ghz		; if yes, branch
		moveq	#-1,d3		; load chunks from RAM
		bsr.s	LocateBlock
		bra.s	@continue

@ghz:
		moveq	#0,d3
		bsr.s	LocateBlock
		add.l	#Blk256_GHZ,d3

@continue:
		movea.l	d3,a0
		move.w	(a0),d3
		andi.w	#$3FF,d3
		lsl.w	#3,d3
		adda.w	d3,a1
		rts	
; ---------------------------------------------------------------------------

LocateBlock:
		move.b	(a4,d0.w),d3	; load chunk ID in d3
		beq.s	LocateBlock_EmptyChunk
		subq.b	#1,d3
		andi.w	#$7F,d3	; '?'
		ror.w	#7,d3
		add.w	d4,d4
		andi.w	#$1E0,d4
		andi.w	#$1E,d5
		add.w	d4,d3
		add.w	d5,d3
		rts
; ---------------------------------------------------------------------------

LocateBlock_EmptyChunk:
		addq.w	#4,sp	; pop a stack frame to leave a1 pointing at the first tile
		rts

Fixing collision

The chunks also contain collision information, so now we need to tell the game that the data is loaded elsewhere. Find the Floor_ChkTile subroutine and replace it with the following code:

Floor_ChkTile_LocateBlock:
		lea	($FFFFA400).w,a1
		move.b	(a1,d0.w),d1
		beq.s	Floor_ChkTile_EmptyChunk	; if the chunk ID is 0 (empty chunk), branch
		bmi.s	loc_1499A
		subq.b	#1,d1		; the empty chunk is not included in the chunk mappings, subtract 1 to read the correct data
		ext.w	d1
		ror.w	#7,d1
		move.w	d2,d0
		add.w	d0,d0
		andi.w	#$1E0,d0
		add.w	d0,d1
		move.w	d3,d0
		lsr.w	#3,d0
		andi.w	#$1E,d0
		add.w	d0,d1
		rts	
; ---------------------------------------------------------------------------

loc_1499A:
		andi.w	#$7F,d1
		btst	#6,1(a0)
		beq.s	loc_149B2
		addq.w	#1,d1
		cmpi.w	#$29,d1
		bne.s	loc_149B2
		move.w	#$51,d1

loc_149B2:
		subq.b	#1,d1
		ror.w	#7,d1
		move.w	d2,d0
		add.w	d0,d0
		andi.w	#$1E0,d0
		add.w	d0,d1
		move.w	d3,d0
		lsr.w	#3,d0
		andi.w	#$1E,d0
		add.w	d0,d1
		rts	
; ---------------------------------------------------------------------------

Floor_ChkTile_EmptyChunk:
		lea	($FFFFFF00).w,a1	; override a1
		addq.w	#4,sp			; pop a stack frame to avoid adding the address of the chunk mappings to a1
		rts	

; ---------------------------------------------------------------------------
; Subroutine to	find which tile	the object is standing on
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


Floor_ChkTile:				; XREF: FindFloor; et al
		move.w	d2,d0
		lsr.w	#1,d0
		andi.w	#$380,d0
		move.w	d3,d1
		lsr.w	#8,d1
		andi.w	#$7F,d1
		add.w	d1,d0
		tst.b	($FFFFFE10).w	; are we in Green Hill Zone?
		beq.s	@ghz		; if yes, branch
		cmpi.b	#6,($FFFFFE10).w ; are we in the ending sequence?
		beq.s	@ghz		; if yes, branch
		moveq	#-1,d1
		bsr.w	Floor_ChkTile_LocateBlock
		movea.l	d1,a1
		rts	
; ---------------------------------------------------------------------------

@ghz:
		moveq	#0,d1
		bsr.w	Floor_ChkTile_LocateBlock
		add.l	#Blk256_GHZ,d1
		movea.l	d1,a1
		rts	
; End of function Floor_ChkTile

Method 2 Using 128x128 Chunks

Free RAM After $8000-$A3FF

MarkeyJesters two eight

Method 3 Using a Z80 SoundDriver

Free RAM After $F000-$F5BF

Coming Soon