Actions

SCHG How-to

Difference between revisions of "Add New Monitors"

From Sonic Retro

m (Step 4: Errors)
(Step 6: Adding More monitors)
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
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 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.
  
==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 9: 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 84: 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 have 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.
+
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==
+
===Step 2: _maps\Monitor.asm===
 
Now, let's worry about fixing some mapping errors.
 
Now, let's worry about fixing some mapping errors.
<asm>; --------------------------------------------------------------------------------
+
 
 +
Delete everything in the file and paste this in.
 +
<syntaxhighlight lang="asm">; --------------------------------------------------------------------------------
 
; Sprite mappings - output from SonMapEd - Sonic 1 format
 
; Sprite mappings - output from SonMapEd - Sonic 1 format
 
; --------------------------------------------------------------------------------
 
; --------------------------------------------------------------------------------
Line 141: Line 145:
 
SME_TP0l7_99: dc.b 1
 
SME_TP0l7_99: dc.b 1
 
dc.b $FF, $D, 0, $38, $F0
 
dc.b $FF, $D, 0, $38, $F0
even</asm>
+
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.  
+
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.  
 
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 REINSERT THAT LABEL!  
+
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==
+
===Step 3: _anim\Monitor.asm===
This is a small file so I want you to take a gander at the beginning, see the labels how the correspond to the labels in a list?
+
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.
+
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.
 
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.
Line 158: Line 162:
 
Now right before "@breaking:" insert this coding:
 
Now right before "@breaking:" insert this coding:
  
<asm>
+
<syntaxhighlight lang="asm">
 
@Invalid_1: 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
</asm>
+
</syntaxhighlight>
  now add to the pointer in the index at the top of the file.
+
   
 
+
Now add to the pointer in the index at the top of the file. Replace this line.
Replace this line.
+
<syntaxhighlight lang="asm">
<asm>
 
 
dc.w  @breaking-Ani_Monitor
 
dc.w  @breaking-Ani_Monitor
</asm>
+
</syntaxhighlight>
 
with this one
 
with this one
<asm>
+
<syntaxhighlight lang="asm">
 
dc.w  @Invalid_1-Ani_Monitor, @breaking-Ani_Monitor
 
dc.w  @Invalid_1-Ani_Monitor, @breaking-Ani_Monitor
</asm>
+
</syntaxhighlight>
 +
 
 +
And then change the ''$B'' to a ''$C'' in the line "@breaking:"
  
 
If you did it right, it should look like this.
 
If you did it right, it should look like this.
  
<asm>; ; ---------------------------------------------------------------------------
+
<syntaxhighlight lang="asm">; ; ---------------------------------------------------------------------------
 
; Animation script - monitors
 
; Animation script - monitors
 
; ---------------------------------------------------------------------------
 
; ---------------------------------------------------------------------------
Line 203: Line 208:
 
even
 
even
 
@breaking: dc.b 2, 0, 1, 2, $C, afBack, 1
 
@breaking: dc.b 2, 0, 1, 2, $C, afBack, 1
even</asm>
+
even</syntaxhighlight>
And now your monitors all work right! Except they look like 'S' monitors when destroyed...
+
 
 +
And now your monitors all work right! Except they look like your new monitor when destroyed...
  
  
==Step 4: Errors==
+
===Step 4: Errors===
  
Now 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.
+
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 monorer and reapproach it....
+
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 <asm> move.b #$B,obFrame(a0) ; use broken monitor frame</asm> and change the B to a C.
+
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''.
  
Now 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.  
  
Let's fix that, 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>
  
This happens at both line 37 and 58
 
  
And you done.
 
  
==Step 5: SonED2 Projects\objdef\s1obj.lst==
+
===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".
 
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==
+
===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)
 
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]]
 
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)
 +
; ---------------------------------------------------------------------------
 +
 +
; ||||||||||||||| 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
 +
</syntaxhighlight>
 +
 +
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. :/