Actions

SCHG How-to

Difference between revisions of "Load chunks from ROM in Sonic 1"

From Sonic Retro

m (Using the uncompressed chunk mappings)
m (Text replacement - "</asm>" to "</syntaxhighlight>")
Line 8: Line 8:
 
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:
 
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:
 
<asm>Blk256_GHZ: incbin map256\ghz.bin
 
<asm>Blk256_GHZ: incbin map256\ghz.bin
even</asm>
+
even</syntaxhighlight>
 
with this:
 
with this:
 
<asm>Blk256_GHZ: incbin map256_u\ghz.bin
 
<asm>Blk256_GHZ: incbin map256_u\ghz.bin
even</asm>
+
even</syntaxhighlight>
 
Note that SonED2 will only change the compressed chunk mappings. You will need to update the uncompressed chunk mappings every time you change them. Use the following command at the command prompt or in a batch (.bat) file (which can be build.bat, right after the @echo off line):
 
Note that SonED2 will only change the compressed chunk mappings. You will need to update the uncompressed chunk mappings every time you change them. Use the following command at the command prompt or in a batch (.bat) file (which can be build.bat, right after the @echo off line):
 
<pre>derecmp.exe kd map256 map256_u</pre>
 
<pre>derecmp.exe kd map256 map256_u</pre>
Line 22: Line 22:
 
<asm> lea (Blk256_GHZ).l,a0 ; load GHZ 256x256 mappings
 
<asm> lea (Blk256_GHZ).l,a0 ; load GHZ 256x256 mappings
 
lea ($FF0000).l,a1
 
lea ($FF0000).l,a1
bsr.w KosDec</asm>
+
bsr.w KosDec</syntaxhighlight>
 
Comment them out or delete them.
 
Comment them out or delete them.
  
Line 28: Line 28:
 
In '''MainLoadBlockLoad''', the chunks data, amongst others, is decompressed to RAM. We are going to disable this. Find the following lines:
 
In '''MainLoadBlockLoad''', the chunks data, amongst others, is decompressed to RAM. We are going to disable this. Find the following lines:
 
<asm> lea ($FF0000).l,a1 ; RAM address for 256x256 mappings
 
<asm> lea ($FF0000).l,a1 ; RAM address for 256x256 mappings
bsr.w KosDec</asm>
+
bsr.w KosDec</syntaxhighlight>
 
and replace them with the following:
 
and replace them with the following:
 
<asm> tst.b ($FFFFFE10).w ; are we in Green Hill Zone?
 
<asm> tst.b ($FFFFFE10).w ; are we in Green Hill Zone?
Line 37: Line 37:
 
bsr.w KosDec
 
bsr.w KosDec
  
@no_dec:</asm>
+
@no_dec:</syntaxhighlight>
  
 
==Fixing art==
 
==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 [[SCHG How-to:Port the REV01 Background Effects|this guide]]) and replace the code from
 
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 [[SCHG How-to:Port the REV01 Background Effects|this guide]]) and replace the code from
<asm> moveq #-1,d3</asm>
+
<asm> moveq #-1,d3</syntaxhighlight>
 
to
 
to
<asm> rts </asm>
+
<asm> rts </syntaxhighlight>
 
with the following:
 
with the following:
 
<asm> tst.b ($FFFFFE10).w ; are we in Green Hill Zone?
 
<asm> tst.b ($FFFFFE10).w ; are we in Green Hill Zone?
Line 83: Line 83:
 
LocateBlock_EmptyChunk:
 
LocateBlock_EmptyChunk:
 
addq.w #4,sp ; pop a stack frame to leave a1 pointing at the first tile
 
addq.w #4,sp ; pop a stack frame to leave a1 pointing at the first tile
rts</asm>
+
rts</syntaxhighlight>
  
 
==Fixing collision==
 
==Fixing collision==
Line 165: Line 165:
 
movea.l d1,a1
 
movea.l d1,a1
 
rts
 
rts
; End of function Floor_ChkTile</asm>
+
; End of function Floor_ChkTile</syntaxhighlight>
  
 
{{S1Howtos}}
 
{{S1Howtos}}
 
[[Category:SCHG How-tos|Load chunks from ROM in Sonic 1]]
 
[[Category:SCHG How-tos|Load chunks from ROM in Sonic 1]]

Revision as of 21:31, 20 December 2015

(Original guide by FraGag)

In Sonic 1, the chunks (metatiles) are larger than in the sequels: 256x256 instead of 128x128. This makes them take up a lot more space and there is a limit to how much you can put in RAM. The game limits itself to $52 chunks (plus one empty chunk), and this takes up more than half of the RAM already. If you were to have $80 chunks, you would take up the whole RAM! If you desperately need more than $52 chunks, you can load them from ROM directly. However, the chunks data is usually compressed in the ROM, so to use the chunks data from ROM, you will need to store them uncompressed, which takes a lot more space (6 KB to 10 KB compressed, compared to at least 41 KB uncompressed — 512 bytes per chunk).

This guide will allow you to continue using chunks loaded to RAM for some zones, while also allowing chunks to be read from ROM for other zones.

Using the uncompressed chunk mappings

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: <asm>Blk256_GHZ: incbin map256\ghz.bin even</syntaxhighlight> with this: <asm>Blk256_GHZ: incbin map256_u\ghz.bin even</syntaxhighlight> Note that SonED2 will only change the compressed chunk mappings. You will need to update the uncompressed chunk mappings every time you change them. Use the following command at the command prompt or in a batch (.bat) file (which can be build.bat, right after the @echo off line):

derecmp.exe kd map256 map256_u
If you're using SonLVL, and want all levels to load chunks from ROM, open S1LVL.ini and add the line:
chunk256cmp=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 "chunk256=../map256/" with "chunk256=../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: <asm> lea (Blk256_GHZ).l,a0 ; load GHZ 256x256 mappings lea ($FF0000).l,a1 bsr.w KosDec</syntaxhighlight> 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: <asm> lea ($FF0000).l,a1 ; RAM address for 256x256 mappings bsr.w KosDec</syntaxhighlight> and replace them with the following: <asm> 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:</syntaxhighlight>

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 <asm> moveq #-1,d3</syntaxhighlight> to <asm> rts </syntaxhighlight> with the following: <asm> 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</syntaxhighlight>

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: <asm>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</syntaxhighlight>
SCHG How-To Guide: Sonic the Hedgehog (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix the SEGA Sound | Display the Press Start Button Text | Fix the Level Select Menu | Fix the Hidden Points Bug | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix the Walk-Jump Bug | Correct Drowning Bugs | Fix the Death Boundary Bug | Fix the Camera Follow Bug | Fix Song Restoration Bugs | Fix the HUD Blinking | Fix the Level Select Graphics Bug | Fix a remember sprite related bug
Changing Design Choices
Change Spike Behavior | Collide with Water After Being Hurt | Fix Special Stage Jumping Physics | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Remove the Speed Cap | Port the REV01 Background Effects | Port Sonic 2's Level Art Loader | Retain Rings Between Acts | Add Sonic 2 (Simon Wai Prototype) Level Select | Improve ObjectMove Subroutines | Port Sonic 2 Level Select
Adding Features
Add Spin Dash ( Part 1 / Part 2 / Part 3 / Part 4 ) | Add Eggman Monitor | Add Super Sonic | Add the Air Roll
Sound Features
Expand the Sound Index | Play Different Songs Per Act | Port Sonic 2 Final Sound Driver | Port Sonic 3's Sound Driver | Port Flamewing's Sonic 3 & Knuckles Sound Driver | Change The SEGA Sound
Extending the Game
Load Chunks From ROM | Add Extra Characters | Make an Alternative Title Screen | Use Dynamic Tilesets | Make GHZ Load Alternate Art | Make Ending Load Alternate Art | Add a New Zone | Set Up the Goggle Monitor | Add New Moves | Add a Dynamic Collision System | Dynamic Special Stage Walls System | Extend Sprite Mappings and Art Limit | Enigma Credits | Use Dynamic Palettes
Miscellaneous
Convert the Hivebrain 2005 Disassembly to ASM68K
Split Disassembly Guides
Set Up a Split Disassembly | Basic Level Editing | Basic Art Editing | Basic ASM Editing (Spin Dash)