Difference between revisions of "Dynamic Special Stage Walls system"
From Sonic Retro
KingofHarts (talk | contribs) (Early Sonic 1 guide taken from ReadySonic by Mercury.) |
m (Text replacement - "\[\[Category:SCHG How-tos.*" to "") |
||
(5 intermediate revisions by 3 users not shown) | |||
Line 5: | Line 5: | ||
==Part 1: Fixing Wall Sprites== | ==Part 1: Fixing Wall Sprites== | ||
So the very first thing we will do, aside from backing up our disassembly, is decompress the Special Stage wall art. Now, you could simply decompress the art, and that's that, right? Wrong! Because we are using uncompressed animated art, we will be changing how the art is mapped together. The absolute easiest way to do this is to have all of the wall sprites under ONE single mapping frame. So, that means that for every possible wall frame, we will want 16 tiles. This requires some slight editing of the wall art to make every possible wall frame centered within a 32x32 pixel image. This shouldn't be too hard to do, as it really only requires fixing up the tiles for the first frame. A visual reference will be provided in the near future, to aid you. After this is done, you will want to save this art uncompressed, and relocate it to the artunc folder. With that finished, we want the asm pointing to the new art location. In '''sonic.asm''', search for the following pointer: | So the very first thing we will do, aside from backing up our disassembly, is decompress the Special Stage wall art. Now, you could simply decompress the art, and that's that, right? Wrong! Because we are using uncompressed animated art, we will be changing how the art is mapped together. The absolute easiest way to do this is to have all of the wall sprites under ONE single mapping frame. So, that means that for every possible wall frame, we will want 16 tiles. This requires some slight editing of the wall art to make every possible wall frame centered within a 32x32 pixel image. This shouldn't be too hard to do, as it really only requires fixing up the tiles for the first frame. A visual reference will be provided in the near future, to aid you. After this is done, you will want to save this art uncompressed, and relocate it to the artunc folder. With that finished, we want the asm pointing to the new art location. In '''sonic.asm''', search for the following pointer: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
Nem_SSWalls: incbin "artnem\Special Walls.bin" ; special stage walls | Nem_SSWalls: incbin "artnem\Special Walls.bin" ; special stage walls | ||
even | even | ||
− | </ | + | </syntaxhighlight> |
and replace it with this: | and replace it with this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
Art_SSWalls: incbin "artunc\Special Walls.bin" ; special stage walls | Art_SSWalls: incbin "artunc\Special Walls.bin" ; special stage walls | ||
even | even | ||
− | </ | + | </syntaxhighlight> |
You don't need to change the pointer to "Art_SSWalls", but if you do, just know that you will need to perform a "Find & Replace" to correct any possible errors. | You don't need to change the pointer to "Art_SSWalls", but if you do, just know that you will need to perform a "Find & Replace" to correct any possible errors. | ||
Now, we are going to change the mappings for the wall art. They currently look something like this: | Now, we are going to change the mappings for the wall art. They currently look something like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
; --------------------------------------------------------------------------- | ; --------------------------------------------------------------------------- | ||
; Sprite mappings - walls of the special stage | ; Sprite mappings - walls of the special stage | ||
Line 62: | Line 62: | ||
dc.b $F0, $F, 0, $E9, $F0 | dc.b $F0, $F, 0, $E9, $F0 | ||
even | even | ||
− | </ | + | </syntaxhighlight> |
These are mappings for 16 frames. All of them but the first one are 4 tiles x 4 tiles, with the first frame being a 3x3 frame. This requires 249 ($F9) tiles loaded into VRAM to work. What we are going to do is consolidate this down to one single mapping. It will look like this: | These are mappings for 16 frames. All of them but the first one are 4 tiles x 4 tiles, with the first frame being a 3x3 frame. This requires 249 ($F9) tiles loaded into VRAM to work. What we are going to do is consolidate this down to one single mapping. It will look like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
; --------------------------------------------------------------------------- | ; --------------------------------------------------------------------------- | ||
; Sprite mappings - walls of the special stage | ; Sprite mappings - walls of the special stage | ||
Line 72: | Line 72: | ||
dc.b $F0, $F, 0, 0, $F0 | dc.b $F0, $F, 0, 0, $F0 | ||
even | even | ||
− | </ | + | </syntaxhighlight> |
Now every frame can be created with one single mapping. Each one will be a 4x4 sprite, and will only require 16 tiles to be loaded into VRAM to make it happen. As the frame change is needed, the game simply needs to change the 16 tiles that are loaded into VRAM, and because EVERY wall tile will always be on the same frame at the same time, that's that! Now let's get the game to do just that! | Now every frame can be created with one single mapping. Each one will be a 4x4 sprite, and will only require 16 tiles to be loaded into VRAM to make it happen. As the frame change is needed, the game simply needs to change the 16 tiles that are loaded into VRAM, and because EVERY wall tile will always be on the same frame at the same time, that's that! Now let's get the game to do just that! | ||
==Part 2: Code Tweaking== | ==Part 2: Code Tweaking== | ||
Next, we need to make some tweaks to the code. Go to ''VBla_0A:'' and find ''@nochg:''. Just below it, insert this code: | Next, we need to make some tweaks to the code. Go to ''VBla_0A:'' and find ''@nochg:''. Just below it, insert this code: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
cmpi.b #96,(v_hbla_line).w | cmpi.b #96,(v_hbla_line).w | ||
bcc.s @update | bcc.s @update | ||
Line 84: | Line 84: | ||
@update: | @update: | ||
jsr SS_LoadWalls | jsr SS_LoadWalls | ||
− | </ | + | </syntaxhighlight> |
Now let's go to ''VBla_16:'', and, again, find ''@nochg:''. Just below it, insert the same code block as above. | Now let's go to ''VBla_16:'', and, again, find ''@nochg:''. Just below it, insert the same code block as above. | ||
Now we need to go to ''GM_Special:'' and find ''SS_ClrNemRam:''. You will see this chunk of code. | Now we need to go to ''GM_Special:'' and find ''SS_ClrNemRam:''. You will see this chunk of code. | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
SS_ClrNemRam: | SS_ClrNemRam: | ||
move.l d0,(a1)+ | move.l d0,(a1)+ | ||
Line 103: | Line 103: | ||
bsr.w PalCycle_SS | bsr.w PalCycle_SS | ||
clr.w (v_ssangle).w ; set stage angle to "upright" | clr.w (v_ssangle).w ; set stage angle to "upright" | ||
− | </ | + | </syntaxhighlight> |
Just below the line that loads Special Stage Sonic, add this line: | Just below the line that loads Special Stage Sonic, add this line: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.b #$FF,(v_ssangleprev).w ; fill previous angle with obviously false value to force an update | move.b #$FF,(v_ssangleprev).w ; fill previous angle with obviously false value to force an update | ||
− | </ | + | </syntaxhighlight> |
This '''v_ssangleprev''' is a new RAM variable, so we are going to need to add an equate for it. In '''Variables.asm''', add it wherever you have a free byte of RAM. | This '''v_ssangleprev''' is a new RAM variable, so we are going to need to add an equate for it. In '''Variables.asm''', add it wherever you have a free byte of RAM. | ||
Next we are going to ''SS_AniWallsRings:'' to change how the walls are animated. Remove the following chunk right at the start of the section: | Next we are going to ''SS_AniWallsRings:'' to change how the walls are animated. Remove the following chunk right at the start of the section: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
lea ($FF400C).l,a1 | lea ($FF400C).l,a1 | ||
moveq #0,d0 | moveq #0,d0 | ||
Line 124: | Line 124: | ||
addq.w #8,a1 | addq.w #8,a1 | ||
dbf d1,loc_1B2A4 | dbf d1,loc_1B2A4 | ||
− | </ | + | </syntaxhighlight> |
Next, go to the end of the section where you will find a data table that looks like this: | Next, go to the end of the section where you will find a data table that looks like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
; =========================================================================== | ; =========================================================================== | ||
SS_WaRiVramSet: dc.w $142, $6142, $142, $142, $142, $142, $142, $6142 | SS_WaRiVramSet: dc.w $142, $6142, $142, $142, $142, $142, $142, $6142 | ||
dc.w $142, $6142, $142, $142, $142, $142, $142, $6142 | dc.w $142, $6142, $142, $142, $142, $142, $142, $6142 | ||
... | ... | ||
− | </ | + | </syntaxhighlight> |
Just above that, we are going to create a new subroutine to load the wall art dynamically. Insert this code above the table: | Just above that, we are going to create a new subroutine to load the wall art dynamically. Insert this code above the table: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
SS_LoadWalls: | SS_LoadWalls: | ||
moveq #0,d0 | moveq #0,d0 | ||
Line 159: | Line 159: | ||
@return: | @return: | ||
rts | rts | ||
− | </ | + | </syntaxhighlight> |
''SS_LoadWalls'' uses the new RAM variable to determine when new tiles are loaded into VRAM. Every time tiles are loaded, $10 tiles will be loaded to VRAM at address $2840. You can find this in a Regen VRAM dump at location 142, the same location that the tileset was previously loaded to. The big difference now, is that you have room for an additional 233 ($E9) tiles for use. You can use that for plenty of things, most notably a HUD! Now there is one final thing we need to do. We still have a Pattern Loading Cue for Special Stage walls to be loaded in this same spot... Having this means that all 256 tiles will be loaded to VRAM, meaning that not only will we not have the desired free VRAM, but even worse, the Bumper art will be overwritten! To fix this, simply go to inc\Pattern Load Cues.asm and at ''PLC_SpecialStage:'', remove the following line: | ''SS_LoadWalls'' uses the new RAM variable to determine when new tiles are loaded into VRAM. Every time tiles are loaded, $10 tiles will be loaded to VRAM at address $2840. You can find this in a Regen VRAM dump at location 142, the same location that the tileset was previously loaded to. The big difference now, is that you have room for an additional 233 ($E9) tiles for use. You can use that for plenty of things, most notably a HUD! Now there is one final thing we need to do. We still have a Pattern Loading Cue for Special Stage walls to be loaded in this same spot... Having this means that all 256 tiles will be loaded to VRAM, meaning that not only will we not have the desired free VRAM, but even worse, the Bumper art will be overwritten! To fix this, simply go to inc\Pattern Load Cues.asm and at ''PLC_SpecialStage:'', remove the following line: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
plcm Nem_SSWalls, $2840 ; walls | plcm Nem_SSWalls, $2840 ; walls | ||
− | </ | + | </syntaxhighlight> |
− | That should be it! Enjoy the freed VRAM! Also note that another advantage to this method is that you can freely add more art to make more in-between frames to make the rotation even smoother! ( | + | That should be it! Enjoy the freed VRAM! Also note that another advantage to this method is that you can freely add more art to make more in-between frames to make the rotation even smoother! |
+ | |||
+ | ''(Additional fix by [[User:Cinossu|Cinossu]])''<br> | ||
+ | Speaking of smoother rotation, you may also want to implement this change as well. Go to ''SS_ShowLayout:'' and take out this line: | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | andi.b #$FC,d0 | ||
+ | </syntaxhighlight> | ||
{{S1Howtos}} | {{S1Howtos}} | ||
− | + | |Dynamic Special Stage Walls system in Sonic 1]] |
Latest revision as of 11:10, 25 August 2018
(Original guide by Mercury)
This guide allows you to have dynamically loaded wall art in the Special Stages. Visually, this makes little to no difference when playing the Special Stage, but it will free VRAM, leaving A LOT of room for other things, like the HUD, or new blocks/objects! This guide follows the current HG disassembly version of Sonic 1.
Part 1: Fixing Wall Sprites
So the very first thing we will do, aside from backing up our disassembly, is decompress the Special Stage wall art. Now, you could simply decompress the art, and that's that, right? Wrong! Because we are using uncompressed animated art, we will be changing how the art is mapped together. The absolute easiest way to do this is to have all of the wall sprites under ONE single mapping frame. So, that means that for every possible wall frame, we will want 16 tiles. This requires some slight editing of the wall art to make every possible wall frame centered within a 32x32 pixel image. This shouldn't be too hard to do, as it really only requires fixing up the tiles for the first frame. A visual reference will be provided in the near future, to aid you. After this is done, you will want to save this art uncompressed, and relocate it to the artunc folder. With that finished, we want the asm pointing to the new art location. In sonic.asm, search for the following pointer:
Nem_SSWalls: incbin "artnem\Special Walls.bin" ; special stage walls
even
and replace it with this:
Art_SSWalls: incbin "artunc\Special Walls.bin" ; special stage walls
even
You don't need to change the pointer to "Art_SSWalls", but if you do, just know that you will need to perform a "Find & Replace" to correct any possible errors.
Now, we are going to change the mappings for the wall art. They currently look something like this:
; ---------------------------------------------------------------------------
; Sprite mappings - walls of the special stage
; ---------------------------------------------------------------------------
Map_SSWalls: dc.w byte_2C584-Map_SSWalls, byte_2C58A-Map_SSWalls
dc.w byte_2C590-Map_SSWalls, byte_2C596-Map_SSWalls
dc.w byte_2C59C-Map_SSWalls, byte_2C5A2-Map_SSWalls
dc.w byte_2C5A8-Map_SSWalls, byte_2C5AE-Map_SSWalls
dc.w byte_2C5B4-Map_SSWalls, byte_2C5BA-Map_SSWalls
dc.w byte_2C5C0-Map_SSWalls, byte_2C5C6-Map_SSWalls
dc.w byte_2C5CC-Map_SSWalls, byte_2C5D2-Map_SSWalls
dc.w byte_2C5D8-Map_SSWalls, byte_2C5DE-Map_SSWalls
byte_2C584: dc.b 1
dc.b $F4, $A, 0, 0, $F4
byte_2C58A: dc.b 1
dc.b $F0, $F, 0, 9, $F0
byte_2C590: dc.b 1
dc.b $F0, $F, 0, $19, $F0
byte_2C596: dc.b 1
dc.b $F0, $F, 0, $29, $F0
byte_2C59C: dc.b 1
dc.b $F0, $F, 0, $39, $F0
byte_2C5A2: dc.b 1
dc.b $F0, $F, 0, $49, $F0
byte_2C5A8: dc.b 1
dc.b $F0, $F, 0, $59, $F0
byte_2C5AE: dc.b 1
dc.b $F0, $F, 0, $69, $F0
byte_2C5B4: dc.b 1
dc.b $F0, $F, 0, $79, $F0
byte_2C5BA: dc.b 1
dc.b $F0, $F, 0, $89, $F0
byte_2C5C0: dc.b 1
dc.b $F0, $F, 0, $99, $F0
byte_2C5C6: dc.b 1
dc.b $F0, $F, 0, $A9, $F0
byte_2C5CC: dc.b 1
dc.b $F0, $F, 0, $B9, $F0
byte_2C5D2: dc.b 1
dc.b $F0, $F, 0, $C9, $F0
byte_2C5D8: dc.b 1
dc.b $F0, $F, 0, $D9, $F0
byte_2C5DE: dc.b 1
dc.b $F0, $F, 0, $E9, $F0
even
These are mappings for 16 frames. All of them but the first one are 4 tiles x 4 tiles, with the first frame being a 3x3 frame. This requires 249 ($F9) tiles loaded into VRAM to work. What we are going to do is consolidate this down to one single mapping. It will look like this:
; ---------------------------------------------------------------------------
; Sprite mappings - walls of the special stage
; ---------------------------------------------------------------------------
Map_SSWalls: dc.w byte_2C584-Map_SSWalls
byte_2C584: dc.b 1
dc.b $F0, $F, 0, 0, $F0
even
Now every frame can be created with one single mapping. Each one will be a 4x4 sprite, and will only require 16 tiles to be loaded into VRAM to make it happen. As the frame change is needed, the game simply needs to change the 16 tiles that are loaded into VRAM, and because EVERY wall tile will always be on the same frame at the same time, that's that! Now let's get the game to do just that!
Part 2: Code Tweaking
Next, we need to make some tweaks to the code. Go to VBla_0A: and find @nochg:. Just below it, insert this code:
cmpi.b #96,(v_hbla_line).w
bcc.s @update
bra.w @end
@update:
jsr SS_LoadWalls
Now let's go to VBla_16:, and, again, find @nochg:. Just below it, insert the same code block as above.
Now we need to go to GM_Special: and find SS_ClrNemRam:. You will see this chunk of code.
SS_ClrNemRam:
move.l d0,(a1)+
dbf d1,SS_ClrNemRam ; clear Nemesis buffer
clr.b (f_wtr_state).w
clr.w (f_restart).w
moveq #palid_Special,d0
bsr.w PalLoad1 ; load special stage palette
jsr SS_Load ; load SS layout data
move.l #0,(v_screenposx).w
move.l #0,(v_screenposy).w
move.b #9,(v_objspace).w ; load special stage Sonic object
bsr.w PalCycle_SS
clr.w (v_ssangle).w ; set stage angle to "upright"
Just below the line that loads Special Stage Sonic, add this line:
move.b #$FF,(v_ssangleprev).w ; fill previous angle with obviously false value to force an update
This v_ssangleprev is a new RAM variable, so we are going to need to add an equate for it. In Variables.asm, add it wherever you have a free byte of RAM.
Next we are going to SS_AniWallsRings: to change how the walls are animated. Remove the following chunk right at the start of the section:
lea ($FF400C).l,a1
moveq #0,d0
move.b (v_ssangle).w,d0
lsr.b #2,d0
andi.w #$F,d0
moveq #$23,d1
loc_1B2A4:
move.w d0,(a1)
addq.w #8,a1
dbf d1,loc_1B2A4
Next, go to the end of the section where you will find a data table that looks like this:
; ===========================================================================
SS_WaRiVramSet: dc.w $142, $6142, $142, $142, $142, $142, $142, $6142
dc.w $142, $6142, $142, $142, $142, $142, $142, $6142
...
Just above that, we are going to create a new subroutine to load the wall art dynamically. Insert this code above the table:
SS_LoadWalls:
moveq #0,d0
move.b (v_ssangle).w,d0 ; get the Special Stage angle
lsr.b #2,d0 ; modify so it can be used as a frame ID
andi.w #$F,d0
cmp.b (v_ssangleprev).w,d0 ; does the modified angle match the recorded value?
beq.s @return ; if so, branch
lea ($C00000).l,a6
lea (Nem_SSWalls).l,a1 ; load wall art
move.w d0,d1
lsl.w #8,d1
add.w d1,d1
add.w d1,a1
locVRAM $2840 ; VRAM address
move.w #$F,d1 ; number of 8x8 tiles
jsr LoadTiles
move.b d0,(v_ssangleprev).w ; record the modified angle for comparison
@return:
rts
SS_LoadWalls uses the new RAM variable to determine when new tiles are loaded into VRAM. Every time tiles are loaded, $10 tiles will be loaded to VRAM at address $2840. You can find this in a Regen VRAM dump at location 142, the same location that the tileset was previously loaded to. The big difference now, is that you have room for an additional 233 ($E9) tiles for use. You can use that for plenty of things, most notably a HUD! Now there is one final thing we need to do. We still have a Pattern Loading Cue for Special Stage walls to be loaded in this same spot... Having this means that all 256 tiles will be loaded to VRAM, meaning that not only will we not have the desired free VRAM, but even worse, the Bumper art will be overwritten! To fix this, simply go to inc\Pattern Load Cues.asm and at PLC_SpecialStage:, remove the following line:
plcm Nem_SSWalls, $2840 ; walls
That should be it! Enjoy the freed VRAM! Also note that another advantage to this method is that you can freely add more art to make more in-between frames to make the rotation even smoother!
(Additional fix by Cinossu)
Speaking of smoother rotation, you may also want to implement this change as well. Go to SS_ShowLayout: and take out this line:
andi.b #$FC,d0
|Dynamic Special Stage Walls system in Sonic 1]]