Actions

SCHG How-to

Difference between revisions of "Add New Monitors"

From Sonic Retro

m (brs instead of bsr)
(Step 6: Adding More monitors)
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= '''''IMPORTANT NOTE: THIS GUIDE IS UNDER CONSTRUCTION! IT DOES NOT WORK PERFECTLY YET!''''' =
+
Let's say you want another monitor. I've given the monitor files a once-over, and found an easy way to free up 10 monitors, the 'S', the Goggles, the Blank, and 7 "invalid" monitors. 2 notes before we begin: This uses the HV build, and I will mention this later, but whenever you want to input more art through SonMapED you HAVE to open up the file Monitors under the folder ''_maps'' and add the label ''map_monitor:'' to the file before the first piece of code.
Let's say you want another monitor. I've given the monitor files a once-over, and found an easy way to free up 10 monitors, the 'S', the Goggles, the Blank, and 7 "invalid" monitors. 2 notes before we begin: This uses the SVN build, and '''there may be errors in unrelated files'''. If there are, then it's probably the amount of branches you have. I used a copy of the DisASM that wasn't clean, so I might tell you to do stupid things that break your own build if I tried to give instructions on how to fix the unrelated errors. If someone could do this tutorial on a fresh build and post fixes for those errors at the end of the guide, I'd be very thankful.
 
  
==Step 1: _incObj\2E Monitor Content Power-Up.asm==
+
==Sonic 1:==
 +
 
 +
===Step 1: _incObj\2E Monitor Content Power-Up.asm===
 
Find the following code:
 
Find the following code:
<asm>Pow_ChkS:
+
<syntaxhighlight lang="asm">Pow_ChkS:
 
cmpi.b #7,d0 ; does monitor contain 'S'?
 
cmpi.b #7,d0 ; does monitor contain 'S'?
 
bne.s Pow_ChkEnd
 
bne.s Pow_ChkEnd
Line 10: Line 11:
  
 
Pow_ChkEnd:
 
Pow_ChkEnd:
rts ; 'S' and goggles monitors do nothing</asm>
+
rts ; 'S' and goggles monitors do nothing</syntaxhighlight>
  
 
Replace it with this template:
 
Replace it with this template:
<asm>Pow_ChkS:
+
<syntaxhighlight lang="asm">Pow_ChkS:
 
cmpi.b #7,d0 ; does monitor contain 'S'?
 
cmpi.b #7,d0 ; does monitor contain 'S'?
 
bne.s Pow_ChkGoggles
 
bne.s Pow_ChkGoggles
Line 85: Line 86:
 
Pow_ChkEnd:
 
Pow_ChkEnd:
 
rts
 
rts
; ===========================================================================</asm>
+
; ===========================================================================</syntaxhighlight>
 +
 
 +
Now you can use the Eggman monitor (before the rest of the monitors in the code), the 'S' monitor, the Goggles monitor, the 7 invalid monitors, and the Blank monitor. There's just a few problems: the invalid monitors havs glitchy graphics, they don't flash like the other ones, AND when we destroy them it shows the "S" monitor instead of the broken one.
 +
 
 +
 
 +
===Step 2: _maps\Monitor.asm===
 +
Now, let's worry about fixing some mapping errors.
 +
 
 +
Delete everything in the file and paste this in.
 +
<syntaxhighlight lang="asm">; --------------------------------------------------------------------------------
 +
; Sprite mappings - output from SonMapEd - Sonic 1 format
 +
; --------------------------------------------------------------------------------
 +
 
 +
SME_TP0l7:
 +
map_monitor:
 +
dc.w SME_TP0l7_1A-SME_TP0l7, SME_TP0l7_20-SME_TP0l7
 +
dc.w SME_TP0l7_2B-SME_TP0l7, SME_TP0l7_36-SME_TP0l7
 +
dc.w SME_TP0l7_41-SME_TP0l7, SME_TP0l7_4C-SME_TP0l7
 +
dc.w SME_TP0l7_57-SME_TP0l7, SME_TP0l7_62-SME_TP0l7
 +
dc.w SME_TP0l7_6D-SME_TP0l7, SME_TP0l7_78-SME_TP0l7
 +
dc.w SME_TP0l7_83-SME_TP0l7, SME_TP0l7_8E-SME_TP0l7
 +
dc.w SME_TP0l7_99-SME_TP0l7
 +
SME_TP0l7_1A: dc.b 1
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_20: dc.b 2
 +
dc.b $F5, 5, 0, $10, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_2B: dc.b 2
 +
dc.b $F5, 5, 0, $14, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_36: dc.b 2
 +
dc.b $F5, 5, 0, $18, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_41: dc.b 2
 +
dc.b $F5, 5, 0, $1C, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_4C: dc.b 2
 +
dc.b $F5, 5, 0, $24, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_57: dc.b 2
 +
dc.b $F5, 5, 0, $28, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_62: dc.b 2
 +
dc.b $F5, 5, 0, $2C, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_6D: dc.b 2
 +
dc.b $F5, 5, 0, $30, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_78: dc.b 2
 +
dc.b $F5, 5, 0, $34, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_83: dc.b 2
 +
dc.b $F5, 5, 0, $20, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_8E: dc.b 2
 +
dc.b $F5, 5, 0, $40, $F8
 +
dc.b $EF, $F, 0, 0, $F0
 +
SME_TP0l7_99: dc.b 1
 +
dc.b $FF, $D, 0, $38, $F0
 +
even</syntaxhighlight>
 +
 
 +
Yeah I know the labels don't look pretty, but at least they work. This adds an extra monitor sprite before the breaking one. You will also need to add some new sprites through SonMapED so you can see it. (or else it will look like a blank monitor)
 +
 
 +
So now we have one new monitor.
 +
 
 +
I want to point out a line of code near the top, the one that says "map_monitor". This links from a lot of over places throughout the ROM and if this label wasn't here it wouldn't know where you go and you would get a build error. So every time you use SonMapED you need to REINSERT THAT LABEL!
 +
 
 +
===Step 3: _anim\Monitor.asm===
 +
This is a small file so I want you to take a gander at the beginning, see how the labels correspond to the labels in the list at the top of the file?
 +
 
 +
This is the animation linking (what tells the monitors to flash) notice how "breaking" monitor only has one animation.
  
Now you can use the Eggman monitor (before the rest of the monitors in the code), the 'S' monitor, the Goggles monitor, the 7 invalid monitors, and the Blank monitor. There's just one problem: the invalid monitors have glitchy graphics.
+
Also see how the Eggman monitor is listed 1, 0, 3, 3, 1, 3, 3, 2, 3, 3, and then the Sonic monitor is 1, 0, 4, 4, 1, 4, 4, 2, 4, 4, the shoes are 5, 5, 5, 5, ect.
  
==Step 2: _maps\Monitor.asm==
+
Now right before "@breaking:" insert this coding:
Delete everything in the file and paste this in:
+
 
<asm>; ---------------------------------------------------------------------------
+
<syntaxhighlight lang="asm">
; Sprite mappings - monitors
+
@Invalid_1: dc.b 1, 0, $B, $B, 1, $B, $B, 2, $B, $B, afEnd
; ---------------------------------------------------------------------------
+
even
Map_Monitor: dc.w @static0-Map_Monitor, @static1-Map_Monitor
+
</syntaxhighlight>
dc.w @static2-Map_Monitor, @eggman-Map_Monitor
+
dc.w @sonic-Map_Monitor, @shoes-Map_Monitor
+
Now add to the pointer in the index at the top of the file. Replace this line.
dc.w @shield-Map_Monitor, @invincible-Map_Monitor
+
<syntaxhighlight lang="asm">
dc.w @rings-Map_Monitor, @s-Map_Monitor
+
dc.@breaking-Ani_Monitor
dc.w @goggles-Map_Monitor, @s2-Map_Monitor
+
</syntaxhighlight>
dc.w @s3-Map_Monitor, @s4-Map_Monitor
+
with this one
dc.w @s5-Map_Monitor, @s6-Map_Monitor
+
<syntaxhighlight lang="asm">
dc.w @s7-Map_Monitor, @s8-Map_Monitor
+
dc.@Invalid_1-Ani_Monitor, @breaking-Ani_Monitor
dc.w @broken-Map_Monitor
+
</syntaxhighlight>
@static0: dc.b 1 ; static monitor
+
 
dc.b $EF, $F, 0, 0, $F0
+
And then change the ''$B'' to a ''$C'' in the line "@breaking:"
@static1: dc.b 2 ; static monitor
 
dc.b $F5, 5, 0, $10, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@static2: dc.b 2 ; static monitor
 
dc.b $F5, 5, 0, $14, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@eggman: dc.b 2 ; Eggman monitor
 
dc.b $F5, 5, 0, $18, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@sonic: dc.b 2 ; Sonic monitor
 
dc.b $F5, 5, 0, $1C, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@shoes: dc.b 2 ; speed shoes monitor
 
dc.b $F5, 5, 0, $24, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@shield: dc.b 2 ; shield monitor
 
dc.b $F5, 5, 0, $28, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@invincible: dc.b 2 ; invincibility monitor
 
dc.b $F5, 5, 0, $2C, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@rings: dc.b 2 ; 10 rings monitor
 
dc.b $F5, 5, 0, $30, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s: dc.b 2 ; 'S' monitor
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@goggles: dc.b 2 ; goggles monitor
 
dc.b $F5, 5, 0, $20, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s2: dc.b 2 ; 'S' monitor (2)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s3: dc.b 2 ; 'S' monitor (3)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s4: dc.b 2 ; 'S' monitor (4)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s5: dc.b 2 ; 'S' monitor (5)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s6: dc.b 2 ; 'S' monitor (6)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s7: dc.b 2 ; 'S' monitor (7)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@s8: dc.b 2 ; 'S' monitor (8)
 
dc.b $F5, 5, 0, $34, $F8
 
dc.b $EF, $F, 0, 0, $F0
 
@broken: dc.b 1 ; broken monitor
 
dc.b $FF, $D, 0, $38, $F0
 
even</asm>
 
  
These will be used when the monitor explodes, so that's why the animations file can't just link the the 'S' image. Speaking of the animations file...
+
If you did it right, it should look like this.
  
==Step 3: _anim\Monitor.asm==
+
<syntaxhighlight lang="asm">; ; ---------------------------------------------------------------------------
Delete everything and paste this in:
 
<asm>; ---------------------------------------------------------------------------
 
 
; Animation script - monitors
 
; Animation script - monitors
 
; ---------------------------------------------------------------------------
 
; ---------------------------------------------------------------------------
Line 171: Line 186:
 
dc.w @shoes-Ani_Monitor, @shield-Ani_Monitor, @invincible-Ani_Monitor
 
dc.w @shoes-Ani_Monitor, @shield-Ani_Monitor, @invincible-Ani_Monitor
 
dc.w @rings-Ani_Monitor, @s-Ani_Monitor, @goggles-Ani_Monitor
 
dc.w @rings-Ani_Monitor, @s-Ani_Monitor, @goggles-Ani_Monitor
dc.w @s2-Ani_Monitor, @s3-Ani_Monitor, @s4-Ani_Monitor
+
dc.w @Invalid_1-Ani_Monitor, @breaking-Ani_Monitor
dc.w @s5-Ani_Monitor, @s6-Ani_Monitor, @s7-Ani_Monitor
 
dc.w @s8-Ani_Monitor, @breaking-Ani_Monitor
 
 
@static: dc.b 1, 0, 1, 2, afEnd
 
@static: dc.b 1, 0, 1, 2, afEnd
 
even
 
even
Line 192: Line 205:
 
@goggles: dc.b 1, 0, $A, $A, 1, $A, $A, 2, $A, $A, afEnd
 
@goggles: dc.b 1, 0, $A, $A, 1, $A, $A, 2, $A, $A, afEnd
 
even
 
even
@s2: dc.b 1, 0, $B, $B, 1, $B, $B, 2, $B, $B, afEnd
+
@Invalid_1: dc.b 1, 0, $B, $B, 1, $B, $B, 2, $B, $B, afEnd
even
+
even
@s3: dc.b 1, 0, $C, $C, 1, $C, $C, 2, $C, $C, afEnd
+
@breaking: dc.b 2, 0, 1, 2, $C, afBack, 1
even
+
even</syntaxhighlight>
@s4: dc.b 1, 0, $D, $D, 1, $D, $D, 2, $D, $D, afEnd
+
 
even
+
And now your monitors all work right! Except they look like your new monitor when destroyed...
@s5: dc.b 1, 0, $E, $E, 1, $E, $E, 2, $E, $E, afEnd
+
 
even
 
@s6: dc.b 1, 0, $F, $F, 1, $F, $F, 2, $F, $F, afEnd
 
even
 
@s7: dc.b 1, 0, 10, 10, 1, 10, 10, 2, 10, 10, afEnd
 
even
 
@s8: dc.b 1, 0, 11, 11, 1, 11, 11, 2, 11, 11, afEnd
 
even
 
@breaking: dc.b 2, 0, 1, 2, $D, afBack, 1
 
even</asm>
 
And now your monitors should all work right! Except they look like 'S' monitors when destroyed...
 
  
==Step 4: _incObj\26 Monitor.asm==
+
===Step 4: Errors===
Now for a final tweak. Search for "move.b #9,obAnim(a0)" and replace it with "move.b #12,obAnim(a0)". Now your monitors will display the correct mappings after being destroyed.
 
  
'''NOTE:''' ''It always displays the 'S' monitor instead of the broken monitor. I have 12 above because it worked before I added 3-7, but now it doesn't and I can't find the right value.''
+
Open up ''26 Monitor.asm'' under the folder _incObj Search for "move.b #9,obAnim(a0)" and replace it with "move.b #10,obAnim(a0)". Now your monitors will display the correct mappings after being destroyed. We had 9 monitors to begin with + 1 new one = 10, simple.
  
==Step 5: SonED2 Projects\objdef\s1obj.lst==
+
But when we get to far away from the monitor and re-approach it....
You now have 10 new monitors. But when you try and place them in SonED 2, you notice that all the "invalid" monitors are labeled "Invalid". How do you know which one's which? You could remember how many times you've pressed the 1 key, or or could have it tell you.Search for "  Description: Monitor". Now scroll down until you see "      Desc  9: Invalid". Now change that to Invalid 1, the one below to Invalid 2, etc... Now you can tell which monitor is which. Of course, if you have a function for that monitor, you can actually just type it's function, such as "Infinte Speed Shoes" or "50 Rings".
 
  
==Step 6: Misc Errors==
+
It shows our new sprite instead of the broken one. To fix this, find the line <syntaxhighlight lang="asm"> move.b #$B,obFrame(a0) ; use broken monitor frame</syntaxhighlight> and change the ''$B'' to a ''$C''.
  
First of all assemble the code and... oh noes! The code doesn't work and the ROM refuses to assemble.
+
Now assemble the code and...what? The code doesn't work and the ROM refuses to assemble.
  
 
It's because of the added code. Now Some branches are now to far away to work.  
 
It's because of the added code. Now Some branches are now to far away to work.  
  
Never fear, open up ''Sub SolidObject'' in the _incObj folder and change  
+
Let's fix that. Open up ''Sub SolidObject'' in the ''_incObj'' folder and change all the instances of
  
<asm>bsr.w MvSonicOnPtfm</asm>
+
<syntaxhighlight lang="asm">bsr.w MvSonicOnPtfm</syntaxhighlight>
 
to
 
to
<asm>jsr    MvSonicOnPtfm</asm>
+
<syntaxhighlight lang="asm">jsr    MvSonicOnPtfm</syntaxhighlight>
  
  
Then open up ''89 Ending Sequence STH'' in the same folder and change
+
Then open up ''89 Ending Sequence STH'' in the same folder and change all the instances of
<asm>bra.w    DisplaySprite</asm>
+
<syntaxhighlight lang="asm">bra.w    DisplaySprite</syntaxhighlight>
 
to
 
to
<asm>jmp    DisplaySprite</asm>
+
<syntaxhighlight lang="asm">jmp    DisplaySprite</syntaxhighlight>
 +
 
 +
 
 +
 
 +
===Step 5: SonED2 Projects\objdef\s1obj.lst===
 +
You now have 1 new monitor. But when you try and place them in SonED 2, you notice that all the "invalid" monitors are labeled "Invalid". How do you know which one's which? You could remember how many times you've pressed the 1 key, or or could have it tell you.Search for "  Description: Monitor". Now scroll down until you see "      Desc  9: Invalid". Now change that to Invalid 1, the one below to Invalid 2, etc... Now you can tell which monitor is which. Of course, if you have a function for that monitor, you can actually just type it's function, such as "Infinite Speed Shoes" or "50 Rings".
 +
 
 +
===Step 6: Adding More monitors===
 +
 
 +
So we added one monitor. To add more, do the same as above starting form step 3 BUT you need to pay attention to the animations script. you NEED to add 1 to the digit before "afBack" on the line with "@breaking:" and insert your monitor code BEFORE the "@breaking:" and add another label to the index. (you can only have up to three labels per line so you might need to add a new line)
 +
 
 +
Also to add the Sprites, use [[SonMapEd]]
 +
 
 +
And if you're adding the spindash to you're hack I recommend you add A checkpoint monitor.
 +
 
 +
==Sonic 2 INCOMPLETE!:==
 +
 
 +
by [[Bombchu Link]]
 +
===Step 1:===
 +
 
 +
Open up s2.asm and search for ''off_12924:''
 +
 
 +
You should see this.
 +
 
 +
<syntaxhighlight lang="asm">
 +
; ============== RELATIVE POINTER LIST    ==================================
 +
off_12924:
 +
dc.w robotnik_monitor-off_12924 ; 0 - Static
 +
dc.w sonic_1up-off_12924 ; 1 - Sonic 1-up
 +
dc.w tails_1up-off_12924 ; 2 - Tails 1-up
 +
dc.w robotnik_monitor-off_12924 ; 3 - Robotnik
 +
dc.w super_ring-off_12924 ; 4 - Super Ring
 +
dc.w super_shoes-off_12924 ; 5 - Speed Shoes
 +
dc.w shield_monitor-off_12924 ; 6 - Shield
 +
dc.w invincible_monitor-off_12924; 7 - Invincibility
 +
dc.w loc_12AA6-off_12924 ; 8 - Teleport
 +
dc.w qmark_monitor-off_12924 ; 9 - Question mark
 +
</syntaxhighlight>
 +
 
 +
at the end add this line.
 +
<syntaxhighlight lang="asm">
 +
dc.w Invalid_1-off_12924 ; A - Invalid 1
 +
</syntaxhighlight>
 +
 
 +
now scroll down until you see this line.
 +
 
 +
<syntaxhighlight lang="asm">
 +
; ===========================================================================
 +
 
 +
qmark_monitor:
 +
addq.w #1,(a2)
 +
rts
 +
; ===========================================================================
 +
</syntaxhighlight>
 +
 
 +
Now below it add these lines.
 +
 
 +
<syntaxhighlight lang="asm">
 +
Invalid_1:
 +
 
 +
nop  ;insert your code here
 +
rts
 +
</syntaxhighlight>
 +
 
 +
This adds the monitor, but it does nothing. let's use [[SCHG_How-to:Create_Insta-kill_and_High_Jump_Monitors|Hayate's Insta Kill monitor]] instead.
 +
 
 +
<syntaxhighlight lang="asm">
 +
Invalid_1:                  ; made by Hayate
 +
        addq.w    #1,(a2)
 +
movea.l    a0,a1
 +
lea    ($FFFFB000).w,a0
 +
jsr    (KillCharacter).l
 +
movea.l    a1,a0
 +
rts
 +
</syntaxhighlight>
 +
 
 +
Save and assemble the code and oh dear...
 +
 
 +
[picture_1.png]
 +
 
 +
It's showing a broken monitor instead of a full one... and it doesn't flash either... but at least it kills sonic when he hits it.
 +
 
 +
Now unless you plan to implement some cruel joke in your mod, we need to give the monitor a new sprite.
 +
 
 +
Open [[SonMapEd]] and insert a sprite right before the broken monitor with the icon on the face that you want. (Be sure to add your new art to the END of the tileset.)
 +
 
 +
Now save your mapping and art and assemble.
 +
 
 +
[picture_2.png]
 +
 
 +
What the?!
 +
 
 +
Now the rings are messed up!
 +
 
 +
Anyway, just go over and look at your monitor, it should show your new graphic.
 +
 
 +
[picture_3]
 +
 
 +
success.
 +
 
 +
But wait, when we destroy other monitors it shows out new monitor instead of the broken one.
 +
 
 +
What ever shall we do?!
 +
 
 +
First thing first, fix the error when we destroy a monitor and get the wrong sprite.
 +
 
 +
--Sorry, this guide isn't complete yet, hopefully I'll make this step really soon.--
 +
 
 +
There is also another error. When we approach the monitor after destroying it, our new monitor returns to haunt us.
 +
To fix this jump to ''obj_26_sub_0:'' in s2.asm and look at this nibble of code near the end of the function
 +
 
 +
<syntaxhighlight lang="asm">
 +
move.b #8,routine(a0)
 +
        move.b #$B,mapping_frame(a0)
 +
</syntaxhighlight>
 +
 
 +
change it to this
 +
 
 +
<syntaxhighlight lang="asm">
 +
move.b #8,routine(a0)
 +
        move.b #$C,mapping_frame(a0)
 +
</syntaxhighlight>
 +
 
 +
We increased the mapping frame by one because we inserted a frame before the broken monitor.
 +
 
 +
 
 +
Now let's make the monitor actually flash like all the others.
 +
 
 +
In s2.asm jump to ''Ani_obj26:'' and look at the following code.
 +
 
 +
<syntaxhighlight lang="asm">
 +
; animation script
 +
; off_12CCE:
 +
Ani_obj26:
 +
dc.w byte_12CE4-Ani_obj26; frame 0
 +
dc.w byte_12CE8-Ani_obj26; 1
 +
dc.w byte_12CF0-Ani_obj26; 2
 +
dc.w byte_12CF8-Ani_obj26; 3
 +
dc.w byte_12D00-Ani_obj26; 4
 +
dc.w byte_12D08-Ani_obj26; 5
 +
dc.w byte_12D10-Ani_obj26; 6
 +
dc.w byte_12D18-Ani_obj26; 7
 +
dc.w byte_12D20-Ani_obj26; 8
 +
dc.w byte_12D28-Ani_obj26; 9
 +
dc.w byte_12D30-Ani_obj26; 10
 +
 
 +
byte_12CE4:
 +
dc.b $01 ; duration
 +
dc.b $00 ; frame number (which sprite table to use)
 +
dc.b $01 ; frame number
 +
dc.b $FF ; terminator
 +
byte_12CE8: dc.b  1,  0,  2,  2,  1,  2,  2,$FF
 +
byte_12CF0: dc.b  1,  0,  3,  3,  1,  3,  3,$FF
 +
byte_12CF8: dc.b  1,  0,  4,  4,  1,  4,  4,$FF
 +
byte_12D00: dc.b  1,  0,  5,  5,  1,  5,  5,$FF
 +
byte_12D08: dc.b  1,  0,  6,  6,  1,  6,  6,$FF
 +
byte_12D10: dc.b  1,  0,  7,  7,  1,  7,  7,$FF
 +
byte_12D18: dc.b  1,  0,  8,  8,  1,  8,  8,$FF
 +
byte_12D20: dc.b  1,  0,  9,  9,  1,  9,  9,$FF
 +
byte_12D28: dc.b  1,  0, $A, $A,  1, $A, $A,$FF
 +
byte_12D30: dc.b  2,  0,  1, $B,$FE,  1
 +
even
 +
</syntaxhighlight>
 +
 
 +
replace it with this.
 +
<syntaxhighlight lang="asm">
 +
; animation script
 +
; off_12CCE:
 +
Ani_obj26:
 +
dc.w byte_12CE4-Ani_obj26; frame 0
 +
dc.w byte_12CE8-Ani_obj26; 1
 +
dc.w byte_12CF0-Ani_obj26; 2
 +
dc.w byte_12CF8-Ani_obj26; 3
 +
dc.w byte_12D00-Ani_obj26; 4
 +
dc.w byte_12D08-Ani_obj26; 5
 +
dc.w byte_12D10-Ani_obj26; 6
 +
dc.w byte_12D18-Ani_obj26; 7
 +
dc.w byte_12D20-Ani_obj26; 8
 +
dc.w byte_12D28-Ani_obj26; 9
 +
dc.w byte_12D30-Ani_obj26; 10
 +
dc.w byte_12D32-Ani_obj26; 11
 +
byte_12CE4:
 +
dc.b $01 ; duration
 +
dc.b $00 ; frame number (which sprite table to use)
 +
dc.b $01 ; frame number
 +
dc.b $FF ; terminator
 +
byte_12CE8: dc.b  1,  0,  2,  2,  1,  2,  2,$FF
 +
byte_12CF0: dc.b  1,  0,  3,  3,  1,  3,  3,$FF
 +
byte_12CF8: dc.b  1,  0,  4,  4,  1,  4,  4,$FF
 +
byte_12D00: dc.b  1,  0,  5,  5,  1,  5,  5,$FF
 +
byte_12D08: dc.b  1,  0,  6,  6,  1,  6,  6,$FF
 +
byte_12D10: dc.b  1,  0,  7,  7,  1,  7,  7,$FF
 +
byte_12D18: dc.b  1,  0,  8,  8,  1,  8,  8,$FF
 +
byte_12D20: dc.b  1,  0,  9,  9,  1,  9,  9,$FF
 +
byte_12D28: dc.b  1,  0, $A, $A,  1, $A, $A,$FF
 +
byte_12D30: dc.b  1,  0, $B, $B,  1, $B, $B,$FF
 +
byte_12D32: dc.b  2,  0,  1, $C,$FE,  1
 +
even
 +
</syntaxhighlight>
 +
 
 +
 
 +
Now let's fix that nasty ring error now. in s2.asm search for ''ChangeRingFrame:'' and you should see this.
 +
 
 +
<syntaxhighlight lang="asm">
 +
 
 +
; ---------------------------------------------------------------------------
 +
; Subroutine to change global object animation variables (like rings)
 +
; ---------------------------------------------------------------------------
  
This happens at both line 37 and 58 (If My memory is any good)
+
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
  
have fun with your new monitors !
+
; sub_4B64:
 +
ChangeRingFrame:
 +
subq.b #1,(Logspike_anim_counter).w
 +
bpl.s +
 +
move.b #$B,(Logspike_anim_counter).w
 +
subq.b #1,(Logspike_anim_frame).w ; animate unused log spikes
 +
andi.b #7,(Logspike_anim_frame).w
 +
+
 +
subq.b #1,(Rings_anim_counter).w
 +
bpl.s +
 +
move.b #7,(Rings_anim_counter).w
 +
addq.b #1,(Rings_anim_frame).w ; animate rings in the level (obj25)
 +
andi.b #3,(Rings_anim_frame).w
 +
+
 +
subq.b #1,(Unknown_anim_counter).w
 +
bpl.s +
 +
move.b #7,(Unknown_anim_counter).w
 +
addq.b #1,(Unknown_anim_frame).w ; animate nothing (deleted special stage object is my best guess)
 +
cmpi.b #6,(Unknown_anim_frame).w
 +
bcs.s +
 +
move.b #0,(Unknown_anim_frame).w
 +
+
 +
tst.b (Ring_spill_anim_counter).w
 +
beq.s + ; rts
 +
moveq #0,d0
 +
move.b (Ring_spill_anim_counter).w,d0
 +
add.w (Ring_spill_anim_accum).w,d0
 +
move.w d0,(Ring_spill_anim_accum).w
 +
rol.w #7,d0
 +
andi.w #3,d0
 +
move.b d0,(Ring_spill_anim_frame).w ; animate scattered rings (obj37)
 +
subq.b #1,(Ring_spill_anim_counter).w
 +
+
 +
rts
 +
; End of function ChangeRingFrame
 +
</syntaxhighlight>
  
<b>NOTE:</b> this still doesn't fix the wonky graphic errors.
+
sorry, but this part of the guide isn't finished yet. :/
  
 
[[Category:SCHG How-tos|{{PAGENAME}}]]
 
[[Category:SCHG How-tos|{{PAGENAME}}]]

Latest revision as of 03:43, 13 March 2018

Let's say you want another monitor. I've given the monitor files a once-over, and found an easy way to free up 10 monitors, the 'S', the Goggles, the Blank, and 7 "invalid" monitors. 2 notes before we begin: This uses the HV build, and I will mention this later, but whenever you want to input more art through SonMapED you HAVE to open up the file Monitors under the folder _maps and add the label map_monitor: to the file before the first piece of code.

Sonic 1:

Step 1: _incObj\2E Monitor Content Power-Up.asm

Find the following code:

Pow_ChkS:
		cmpi.b	#7,d0		; does monitor contain 'S'?
		bne.s	Pow_ChkEnd
		nop	

Pow_ChkEnd:
		rts			; 'S' and goggles monitors do nothing

Replace it with this template:

Pow_ChkS:
		cmpi.b	#7,d0		; does monitor contain 'S'?
		bne.s	Pow_ChkGoggles

		nop ;Insert code here.
; ===========================================================================

Pow_ChkGoggles: ;The Goggles monitor still does nothing.
		cmpi.b	#8,d0		; does monitor contain goggles?
		bne.s	Pow_ChkInvalid1

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid1:
		cmpi.b	#9,d0		; Is this the 1st invalid monitor?
		bne.s	Pow_ChkInvalid2

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid2:
		cmpi.b	#$A,d0		; Is this the 2nd invalid monitor?
		bne.s	Pow_ChkInvalid3

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid3:
		cmpi.b	#$B,d0		; Is this the 3rd invalid monitor?
		bne.s	Pow_ChkInvalid4

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid4:
		cmpi.b	#$C,d0		; Is this the 4th invalid monitor?
		bne.s	Pow_ChkInvalid5

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid5:
		cmpi.b	#$D,d0		; Is this the 5th invalid monitor?
		bne.s	Pow_ChkInvalid6

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid6:
		cmpi.b	#$E,d0		; Is this the 6th invalid monitor?
		bne.s	Pow_ChkInvalid7

		nop ;Insert code here.
; ==========================================================================

Pow_ChkInvalid7:
		cmpi.b	#$F,d0		; Is this the 7th invalid monitor?
		bne.s	Pow_ChkBlank

		nop ;Insert code here.
; ==========================================================================

Pow_ChkBlank:
		cmpi.b	#0,d0		; Is this the blank monitor?
		bne.s	Pow_ChkEnd

		nop ;Insert code here.
; ==========================================================================

Pow_ChkEnd:
		rts
; ===========================================================================

Now you can use the Eggman monitor (before the rest of the monitors in the code), the 'S' monitor, the Goggles monitor, the 7 invalid monitors, and the Blank monitor. There's just a few problems: the invalid monitors havs glitchy graphics, they don't flash like the other ones, AND when we destroy them it shows the "S" monitor instead of the broken one.


Step 2: _maps\Monitor.asm

Now, let's worry about fixing some mapping errors.

Delete everything in the file and paste this in.

; --------------------------------------------------------------------------------
; Sprite mappings - output from SonMapEd - Sonic 1 format
; --------------------------------------------------------------------------------

SME_TP0l7:	
map_monitor:
		dc.w SME_TP0l7_1A-SME_TP0l7, SME_TP0l7_20-SME_TP0l7	
		dc.w SME_TP0l7_2B-SME_TP0l7, SME_TP0l7_36-SME_TP0l7	
		dc.w SME_TP0l7_41-SME_TP0l7, SME_TP0l7_4C-SME_TP0l7	
		dc.w SME_TP0l7_57-SME_TP0l7, SME_TP0l7_62-SME_TP0l7	
		dc.w SME_TP0l7_6D-SME_TP0l7, SME_TP0l7_78-SME_TP0l7	
		dc.w SME_TP0l7_83-SME_TP0l7, SME_TP0l7_8E-SME_TP0l7	
		dc.w SME_TP0l7_99-SME_TP0l7	
SME_TP0l7_1A:	dc.b 1	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_20:	dc.b 2	
		dc.b $F5, 5, 0, $10, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_2B:	dc.b 2	
		dc.b $F5, 5, 0, $14, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_36:	dc.b 2	
		dc.b $F5, 5, 0, $18, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_41:	dc.b 2	
		dc.b $F5, 5, 0, $1C, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_4C:	dc.b 2	
		dc.b $F5, 5, 0, $24, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_57:	dc.b 2	
		dc.b $F5, 5, 0, $28, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_62:	dc.b 2	
		dc.b $F5, 5, 0, $2C, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_6D:	dc.b 2	
		dc.b $F5, 5, 0, $30, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_78:	dc.b 2	
		dc.b $F5, 5, 0, $34, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_83:	dc.b 2	
		dc.b $F5, 5, 0, $20, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_8E:	dc.b 2	
		dc.b $F5, 5, 0, $40, $F8	
		dc.b $EF, $F, 0, 0, $F0	
SME_TP0l7_99:	dc.b 1	
		dc.b $FF, $D, 0, $38, $F0	
		even

Yeah I know the labels don't look pretty, but at least they work. This adds an extra monitor sprite before the breaking one. You will also need to add some new sprites through SonMapED so you can see it. (or else it will look like a blank monitor)

So now we have one new monitor.

I want to point out a line of code near the top, the one that says "map_monitor". This links from a lot of over places throughout the ROM and if this label wasn't here it wouldn't know where you go and you would get a build error. So every time you use SonMapED you need to REINSERT THAT LABEL!

Step 3: _anim\Monitor.asm

This is a small file so I want you to take a gander at the beginning, see how the labels correspond to the labels in the list at the top of the file?

This is the animation linking (what tells the monitors to flash) notice how "breaking" monitor only has one animation.

Also see how the Eggman monitor is listed 1, 0, 3, 3, 1, 3, 3, 2, 3, 3, and then the Sonic monitor is 1, 0, 4, 4, 1, 4, 4, 2, 4, 4, the shoes are 5, 5, 5, 5, ect.

Now right before "@breaking:" insert this coding:

@Invalid_1:	dc.b 1,	0, $B, $B, 1, $B, $B, 2, $B, $B, afEnd
		even

Now add to the pointer in the index at the top of the file. Replace this line.

dc.w   @breaking-Ani_Monitor

with this one

dc.w  @Invalid_1-Ani_Monitor, @breaking-Ani_Monitor

And then change the $B to a $C in the line "@breaking:"

If you did it right, it should look like this.

; ; ---------------------------------------------------------------------------
; Animation script - monitors
; ---------------------------------------------------------------------------
Ani_Monitor:	dc.w @static-Ani_Monitor, @eggman-Ani_Monitor, @sonic-Ani_Monitor
		dc.w @shoes-Ani_Monitor, @shield-Ani_Monitor, @invincible-Ani_Monitor
		dc.w @rings-Ani_Monitor, @s-Ani_Monitor, @goggles-Ani_Monitor
		dc.w @Invalid_1-Ani_Monitor, @breaking-Ani_Monitor
@static:	dc.b 1,	0, 1, 2, afEnd
		even
@eggman:	dc.b 1,	0, 3, 3, 1, 3, 3, 2, 3,	3, afEnd
		even
@sonic:		dc.b 1,	0, 4, 4, 1, 4, 4, 2, 4,	4, afEnd
		even
@shoes:		dc.b 1,	0, 5, 5, 1, 5, 5, 2, 5,	5, afEnd
		even
@shield:	dc.b 1,	0, 6, 6, 1, 6, 6, 2, 6,	6, afEnd
		even
@invincible:	dc.b 1,	0, 7, 7, 1, 7, 7, 2, 7,	7, afEnd
		even
@rings:		dc.b 1,	0, 8, 8, 1, 8, 8, 2, 8,	8, afEnd
		even
@s:		dc.b 1,	0, 9, 9, 1, 9, 9, 2, 9,	9, afEnd
		even
@goggles:	dc.b 1,	0, $A, $A, 1, $A, $A, 2, $A, $A, afEnd
		even
@Invalid_1:	dc.b 1,	0, $B, $B, 1, $B, $B, 2, $B, $B, afEnd
		even			
@breaking:	dc.b 2,	0, 1, 2, $C, afBack, 1
		even

And now your monitors all work right! Except they look like your new monitor when destroyed...


Step 4: Errors

Open up 26 Monitor.asm under the folder _incObj Search for "move.b #9,obAnim(a0)" and replace it with "move.b #10,obAnim(a0)". Now your monitors will display the correct mappings after being destroyed. We had 9 monitors to begin with + 1 new one = 10, simple.

But when we get to far away from the monitor and re-approach it....

It shows our new sprite instead of the broken one. To fix this, find the line
	move.b	#$B,obFrame(a0)	; use broken monitor frame
and change the $B to a $C.

Now assemble the code and...what? The code doesn't work and the ROM refuses to assemble.

It's because of the added code. Now Some branches are now to far away to work.

Let's fix that. Open up Sub SolidObject in the _incObj folder and change all the instances of

bsr.w MvSonicOnPtfm

to

jsr    MvSonicOnPtfm


Then open up 89 Ending Sequence STH in the same folder and change all the instances of

bra.w     DisplaySprite

to

jmp     DisplaySprite


Step 5: SonED2 Projects\objdef\s1obj.lst

You now have 1 new monitor. But when you try and place them in SonED 2, you notice that all the "invalid" monitors are labeled "Invalid". How do you know which one's which? You could remember how many times you've pressed the 1 key, or or could have it tell you.Search for " Description: Monitor". Now scroll down until you see " Desc 9: Invalid". Now change that to Invalid 1, the one below to Invalid 2, etc... Now you can tell which monitor is which. Of course, if you have a function for that monitor, you can actually just type it's function, such as "Infinite Speed Shoes" or "50 Rings".

Step 6: Adding More monitors

So we added one monitor. To add more, do the same as above starting form step 3 BUT you need to pay attention to the animations script. you NEED to add 1 to the digit before "afBack" on the line with "@breaking:" and insert your monitor code BEFORE the "@breaking:" and add another label to the index. (you can only have up to three labels per line so you might need to add a new line)

Also to add the Sprites, use SonMapEd

And if you're adding the spindash to you're hack I recommend you add A checkpoint monitor.

Sonic 2 INCOMPLETE!:

by Bombchu Link

Step 1:

Open up s2.asm and search for off_12924:

You should see this.

; ============== RELATIVE POINTER LIST     ==================================
off_12924:
	dc.w robotnik_monitor-off_12924	; 0 - Static
	dc.w sonic_1up-off_12924	; 1 - Sonic 1-up
	dc.w tails_1up-off_12924	; 2 - Tails 1-up
	dc.w robotnik_monitor-off_12924	; 3 - Robotnik
	dc.w super_ring-off_12924	; 4 - Super Ring
	dc.w super_shoes-off_12924	; 5 - Speed Shoes
	dc.w shield_monitor-off_12924	; 6 - Shield
	dc.w invincible_monitor-off_12924; 7 - Invincibility
	dc.w loc_12AA6-off_12924	; 8 - Teleport
	dc.w qmark_monitor-off_12924	; 9 - Question mark

at the end add this line.

dc.w Invalid_1-off_12924	; A - Invalid 1

now scroll down until you see this line.

; ===========================================================================

qmark_monitor:
	addq.w	#1,(a2)
	rts
; ===========================================================================

Now below it add these lines.

Invalid_1:

nop  ;insert your code here
rts

This adds the monitor, but it does nothing. let's use Hayate's Insta Kill monitor instead.

Invalid_1:                  ; made by Hayate
        addq.w    #1,(a2)
	movea.l    a0,a1
	lea    ($FFFFB000).w,a0
	jsr    (KillCharacter).l
	movea.l    a1,a0
	rts

Save and assemble the code and oh dear...

[picture_1.png]

It's showing a broken monitor instead of a full one... and it doesn't flash either... but at least it kills sonic when he hits it.

Now unless you plan to implement some cruel joke in your mod, we need to give the monitor a new sprite.

Open SonMapEd and insert a sprite right before the broken monitor with the icon on the face that you want. (Be sure to add your new art to the END of the tileset.)

Now save your mapping and art and assemble.

[picture_2.png]

What the?!

Now the rings are messed up!

Anyway, just go over and look at your monitor, it should show your new graphic.

[picture_3]

success.

But wait, when we destroy other monitors it shows out new monitor instead of the broken one.

What ever shall we do?!

First thing first, fix the error when we destroy a monitor and get the wrong sprite.

--Sorry, this guide isn't complete yet, hopefully I'll make this step really soon.--

There is also another error. When we approach the monitor after destroying it, our new monitor returns to haunt us. To fix this jump to obj_26_sub_0: in s2.asm and look at this nibble of code near the end of the function

	move.b	#8,routine(a0)
        move.b	#$B,mapping_frame(a0)

change it to this

	move.b	#8,routine(a0)
        move.b	#$C,mapping_frame(a0)

We increased the mapping frame by one because we inserted a frame before the broken monitor.


Now let's make the monitor actually flash like all the others.

In s2.asm jump to Ani_obj26: and look at the following code.

; animation script
; off_12CCE:
Ani_obj26:
	dc.w byte_12CE4-Ani_obj26; frame 0
	dc.w byte_12CE8-Ani_obj26; 1
	dc.w byte_12CF0-Ani_obj26; 2
	dc.w byte_12CF8-Ani_obj26; 3
	dc.w byte_12D00-Ani_obj26; 4
	dc.w byte_12D08-Ani_obj26; 5
	dc.w byte_12D10-Ani_obj26; 6
	dc.w byte_12D18-Ani_obj26; 7
	dc.w byte_12D20-Ani_obj26; 8
	dc.w byte_12D28-Ani_obj26; 9
	dc.w byte_12D30-Ani_obj26; 10

byte_12CE4:
	dc.b	$01	; duration
	dc.b	$00	; frame number (which sprite table to use)
	dc.b	$01	; frame number
	dc.b	$FF	; terminator
byte_12CE8:	dc.b   1,  0,  2,  2,  1,  2,  2,$FF
byte_12CF0:	dc.b   1,  0,  3,  3,  1,  3,  3,$FF
byte_12CF8:	dc.b   1,  0,  4,  4,  1,  4,  4,$FF
byte_12D00:	dc.b   1,  0,  5,  5,  1,  5,  5,$FF
byte_12D08:	dc.b   1,  0,  6,  6,  1,  6,  6,$FF
byte_12D10:	dc.b   1,  0,  7,  7,  1,  7,  7,$FF
byte_12D18:	dc.b   1,  0,  8,  8,  1,  8,  8,$FF
byte_12D20:	dc.b   1,  0,  9,  9,  1,  9,  9,$FF
byte_12D28:	dc.b   1,  0, $A, $A,  1, $A, $A,$FF
byte_12D30:	dc.b   2,  0,  1, $B,$FE,  1
	even

replace it with this.

; animation script
; off_12CCE:
Ani_obj26:
	dc.w byte_12CE4-Ani_obj26; frame 0
	dc.w byte_12CE8-Ani_obj26; 1
	dc.w byte_12CF0-Ani_obj26; 2
	dc.w byte_12CF8-Ani_obj26; 3
	dc.w byte_12D00-Ani_obj26; 4
	dc.w byte_12D08-Ani_obj26; 5
	dc.w byte_12D10-Ani_obj26; 6
	dc.w byte_12D18-Ani_obj26; 7
	dc.w byte_12D20-Ani_obj26; 8
	dc.w byte_12D28-Ani_obj26; 9
	dc.w byte_12D30-Ani_obj26; 10
	dc.w byte_12D32-Ani_obj26; 11
byte_12CE4:
	dc.b	$01	; duration
	dc.b	$00	; frame number (which sprite table to use)
	dc.b	$01	; frame number
	dc.b	$FF	; terminator
byte_12CE8:	dc.b   1,  0,  2,  2,  1,  2,  2,$FF
byte_12CF0:	dc.b   1,  0,  3,  3,  1,  3,  3,$FF
byte_12CF8:	dc.b   1,  0,  4,  4,  1,  4,  4,$FF
byte_12D00:	dc.b   1,  0,  5,  5,  1,  5,  5,$FF
byte_12D08:	dc.b   1,  0,  6,  6,  1,  6,  6,$FF
byte_12D10:	dc.b   1,  0,  7,  7,  1,  7,  7,$FF
byte_12D18:	dc.b   1,  0,  8,  8,  1,  8,  8,$FF
byte_12D20:	dc.b   1,  0,  9,  9,  1,  9,  9,$FF
byte_12D28:	dc.b   1,  0, $A, $A,  1, $A, $A,$FF
byte_12D30:	dc.b   1,  0, $B, $B,  1, $B, $B,$FF
byte_12D32:	dc.b   2,  0,  1, $C,$FE,  1
	even


Now let's fix that nasty ring error now. in s2.asm search for ChangeRingFrame: and you should see this.

; ---------------------------------------------------------------------------
; Subroutine to change global object animation variables (like rings)
; ---------------------------------------------------------------------------

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

; sub_4B64:
ChangeRingFrame:
	subq.b	#1,(Logspike_anim_counter).w
	bpl.s	+
	move.b	#$B,(Logspike_anim_counter).w
	subq.b	#1,(Logspike_anim_frame).w ; animate unused log spikes
	andi.b	#7,(Logspike_anim_frame).w
+
	subq.b	#1,(Rings_anim_counter).w
	bpl.s	+
	move.b	#7,(Rings_anim_counter).w
	addq.b	#1,(Rings_anim_frame).w ; animate rings in the level (obj25)
	andi.b	#3,(Rings_anim_frame).w
+
	subq.b	#1,(Unknown_anim_counter).w
	bpl.s	+
	move.b	#7,(Unknown_anim_counter).w
	addq.b	#1,(Unknown_anim_frame).w ; animate nothing (deleted special stage object is my best guess)
	cmpi.b	#6,(Unknown_anim_frame).w
	bcs.s	+
	move.b	#0,(Unknown_anim_frame).w
+
	tst.b	(Ring_spill_anim_counter).w
	beq.s	+	; rts
	moveq	#0,d0
	move.b	(Ring_spill_anim_counter).w,d0
	add.w	(Ring_spill_anim_accum).w,d0
	move.w	d0,(Ring_spill_anim_accum).w
	rol.w	#7,d0
	andi.w	#3,d0
	move.b	d0,(Ring_spill_anim_frame).w ; animate scattered rings (obj37)
	subq.b	#1,(Ring_spill_anim_counter).w
+
	rts
; End of function ChangeRingFrame

sorry, but this part of the guide isn't finished yet. :/