Hello, all! There is an update to the priority guide. 2 extra steps! These steps are actually bug fixes caused by the new priority manager, and you may want to implement these if you've followed my guide.
Thanks to flamewing for the help and advice on these fixes.
Step 10 update - Fix the priority for when the main character is dead
In my priority guide, for step 10, I explained that when you're dead, all the objects stop moving. And they all jump to "DisplaySprite:" via "RunObjectDisplayOnly:". Because of this, some objects that use priority for different reason will cause the game to crash. The way I showed you was that we had to make all objects use the same priority, so that it wouldn't freeze. Most of the time, this isn't a problem, but then, you'll may notice things like this:
This is because, when you die, all objects jump to the "RunObjectDisplayOnly:". As they're all using the same priority, a newer one will overlap. Take the EHZ boss. His drill gets displayed first, then his wheels (so they overlap), then the cockpit (so they overlap the rest), then finally Eggman (which overlaps all). See what I mean?
To fix this, it's simple, and I should have thought of it before (Sonic 2 Recreation has different coding and doesn't suffer this). Anyway, go to "RunObjectDisplayOnly:", and change from this:
RunObjectDisplayOnly:
moveq #0,d0
move.b (a0),d0 ; get the object's ID
beq.s + ; if it's obj00, skip it
tst.b render_flags(a0) ; should we render it?
bpl.s + ; if not, skip it
move.w #$200,d0
bsr.w DisplaySprite3
+
lea next_object(a0),a0 ; load 0bj address
dbf d7,RunObjectDisplayOnly
rts
; End of function RunObjectDisplayOnly
to this:
RunObjectDisplayOnly:
moveq #0,d0 ; Clear d0 quickly
move.b (a0),d0 ; get the object's ID
beq.s ++ ; if it's obj00, skip it
tst.b render_flags(a0) ; should we render it?
bpl.s ++ ; if not, skip it
move.w priority(a0),d0 ; move object's priority to d0
btst #6,render_flags(a0) ; is the compound sprites flag set?
beq.s + ; if not, branch
move.w #$200,d0 ; move $200 to d0
+
bsr.w DisplaySprite3 ; Display the object with whatever is set at d0
+
lea next_object(a0),a0 ; load 0bj address
dbf d7,RunObjectDisplayOnly
rts
; End of function RunObjectDisplayOnly
So now, when all objects jump here, it will ask first, does it have the compound sprite flag set? If not, branch and continue, and use the object's original priority. If it
IS set, it means that the current object's status table also contains information about other child sprites which need to be drawn using the current object's mappings. In other words, for our sake, it's using priority for something different. Therefore, it will
NOT branch and it will move $200 to d0 instead.
That's it. Done, you'll now get stuff like this:
It was that simple.
Step 13 - Fix the priority for Tails' tails
This bug I only noticed the other day (was also present in S2R). The fix was a bit more involved than I thought.
The problem is, Tails' tail's priority has been affected. Even though Tails' priority is $100, and his tails' priority is $100. Here is an example:
It seems that his tails are not as much as a priority anymore. Anyway, flamewing had a solution, which he uses for his hack; Sonic 2 Heroes.
Anyway, the fix:
First, you're going to have to use some RAM. Only a word. So, go to your list of equates. I used $FFFFF5C0 (it's free whether you use the S1 sound driver or not). Call the RAM "Tails_Tails_ptr"
Tails_Tails_ptr = ramaddr( $FFFFF5C0 )
Our new RAM is ready for use. First, go to "InitPlayers:" and under the line:
move.b #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040
SVN users, yours will say:
move.b #ObjID_Tails,(Sidekick+id).w ; load Obj02 Tails object at $FFFFB040
Insert this:
move.w #Tails_Tails,(Tails_Tails_ptr).w
So you have something like this (
SVN users, reference only):
move.b #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040
move.w #Tails_Tails,(Tails_Tails_ptr).w
move.w (MainCharacter+x_pos).w,(Sidekick+x_pos).w
move.w (MainCharacter+y_pos).w,(Sidekick+y_pos).w
subi.w #$20,(Sidekick+x_pos).w
addi.w #4,(Sidekick+y_pos).w
move.b #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD140
Do the same at label "InitPlayers_TailsAlone:", so you have something like this (
SVN users, reference only):
InitPlayers_TailsAlone:
move.b #2,(MainCharacter).w ; load Obj02 Tails object at $FFFFB000
move.w #Tails_Tails,(Tails_Tails_ptr).w
move.b #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100
addi.w #4,(MainCharacter+y_pos).w
rts
; End of function InitPlayers
Next, go to "loc_A2F2:". This is for when you're at the cutscene at the end of the game.
XenoWhirl users. Change this:
loc_A2F2:
moveq #$E,d0
move.b #2,(a1) ; load Tails object
move.b #$81,$2A(a1)
move.b #5,(Object_RAM+$80).w ; load Obj05 (Tails' tails) at $FFFFB080
move.w a1,(Object_RAM+$80+parent).w
rts
to this:
loc_A2F2:
moveq #$E,d0
move.b #2,(a1) ; load Tails object
move.b #$81,$2A(a1)
move.w #Object_RAM+$80,(Tails_Tails_ptr).w
rts
SVN users, change this:
loc_A2F2:
moveq #$E,d0
move.b #ObjID_Tails,id(a1) ; load Tails object
move.b #$81,obj_control(a1)
move.b #ObjID_TailsTails,(Tails_Tails_Cutscene+id).w ; load Obj05 (Tails' tails) at $FFFFB080
move.w a1,(Tails_Tails_Cutscene+parent).w
rts
to this:
loc_A2F2:
moveq #$E,d0
move.b #ObjID_Tails,id(a1) ; load Tails object
move.b #$81,obj_control(a1)
move.w #Tails_Tails_Cutscene,(Tails_Tails_ptr).w ; Tails' tails at $FFFFB080
rts
Next, go to "Obj02_Init_Continued:", and change the last few lines. Change this:
move.b #5,(Tails_Tails).w ; load Obj05 (Tails' Tails) at $FFFFD000
move.w a0,(Tails_Tails+parent).w ; set its parent object to this
SVN users, yours will say:
move.b #ObjID_TailsTails,(Tails_Tails+id).w ; load Obj05 (Tails' Tails) at $FFFFD000
move.w a0,(Tails_Tails+parent).w ; set its parent object to this
And change it to this:
movea.w (Tails_Tails_ptr).w,a1
move.b #5,0(a1) ; load Obj05 (Tails' Tails) at $FFFFD000
move.w a0,parent(a1) ; set its parent object to this
And change it to this:
movea.w (Tails_Tails_ptr).w,a1
move.b #ObjID_TailsTails,id(a1) ; load Obj05 (Tails' Tails)
move.w a0,parent(a1) ; set its parent object to this
One more step! Go to "Obj02:" See the command
jmp Obj02_States(pc,d1.w) (
jmp Obj02_Index(pc,d1.w))? Change the "jmp" to a "jsr".
And directly underneath it, add this:
movea.w (Tails_Tails_ptr).w,a1
tst.b routine(a1)
beq.s +
jmp (DisplaySprite2).l
+
rts
So you have something like this (
SVN users, reference only):
Obj02:
; a0=character
cmpi.w #2,(Player_mode).w
bne.s +
move.w (Camera_Min_X_pos).w,(Tails_Min_X_pos).w
move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
move.w (Camera_Max_Y_pos_now).w,(Tails_Max_Y_pos).w
+
moveq #0,d0
move.b routine(a0),d0
move.w Obj02_States(pc,d0.w),d1
jsr Obj02_States(pc,d1.w)
movea.w (Tails_Tails_ptr).w,a1
tst.b routine(a1)
beq.s +
jmp (DisplaySprite2).l
+
rts
Done! Tails' tails should now work with the right priority! Tails will now queue his tails for drawing right after himself. Without this, the tails will be queued for drawing after all objects between Tails and the tails that have the same priority. And that's why before, Tails' tails had less priority.
I'll update my first post containing the guide with this information. Any bugs/troubles, reply here. If anyone wants to add this extra bit to the SCHG, feel free.
Cheers,
redhotsonic