don't click here

Multiple Tails tails' bug fixes (Mainly S2, some are S3K)

Discussion in 'Engineering & Reverse Engineering' started by redhotsonic, Sep 8, 2012.

  1. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    INDEX

    - For Tails' tails invulnerable time glitch, read this post

    - For Tails' tails pushing animation error, click here for post

    - For Tails' tails balancing animation addition, click here for post

    - For Tails' tails looking up speed animation glitch, click here for post

    - For Tails' tails priority error glitch (EHZ boss's wheels as example), click here for post





    For Tails' tails invulnerable time glitch

    Here's a quick one for you lot. This isn't a bug as such, more like... a design change. We all know that Tails has another object attached to him half the time; "Tails' Tails". Used for when he's standing, jumping, etc. Sometimes, his tails are drawn within Tails himself, like when he is walking.



    Something that has always bugged me in Sonic 2 is that when he gets hurt, he becomes invulnerable for a couple of seconds, and he flashes, but the object "Tails' tails" does not.


    [​IMG]


    When this object isn't being used (like when Tails is walking and the tails are drawn within him) his tails do flash.


    To me, this looks strange. This happens in both Sonic 2 and Sonic 3 and Knuckles. I'm about to show you how to fix it in both games.






    Sonic 2 fix - Xenowhirl and SVN Disassemblies


    Go to "loc_1D288:" and you should see this:

    Code (ASM):
    1. loc_1D288:
    2.     lea (Obj05AniData).l,a1
    3.     bsr.w   Tails_Animate_Part2
    4.     bsr.w   LoadTailsTailsDynPLC
    5.     jsr (DisplaySprite).l
    6.     rts

    This is where Tails' Tails object gets animated and displayed. Change all this to:

    Code (ASM):
    1. loc_1D288:
    2.     lea (Obj05AniData).l,a1
    3.     bsr.w   Tails_Animate_Part2
    4.     bsr.w   LoadTailsTailsDynPLC
    5.     movea.w parent(a0),a1           ; Move Tails' register to a1
    6.     move.w  invulnerable_time(a1),d0    ; Move Tails' invulnerable time to d0
    7.     beq.s   +               ; Is invulnerable_time 0?  If so, always display his tails
    8.     addq.w  #1,d0               ; Make d0 the same as old invulnerable_time's d0
    9.     lsr.w   #3,d0               ; Shift bits to the right 3 times
    10.     bcs.s   +               ; If the Carry bit is set, branch and display his tails
    11.     rts                 ; Otherwise, do not display Tails' tails
    12. +
    13.     jmp (DisplaySprite).l       ; Display Tails' tails

    Done.



    Sonic 3 and Knuckles fix - SVN Disassembly


    Go to "loc_1615A:" and you should see this:

    Code (ASM):
    1. loc_1615A:
    2.         bsr.w   Tails_Tail_Load_PLC
    3.         jmp (Draw_Sprite).l


    This is where Tails' Tails object gets animated and displayed. Change all this to:

    Code (ASM):
    1. loc_1615A:
    2.         bsr.w   Tails_Tail_Load_PLC
    3.         movea.w $30(a0),a1      ; Move Tails' register to a1
    4.         move.b  $34(a1),d0      ; Move Tails' invulnerable time to d0
    5.         beq.s   +           ; Is invulnerable_time 0?  If so, always display his tails
    6.         addq.b  #1,d0           ; Make d0 the same as old invulnerable_time's d0
    7.         lsr.b   #3,d0           ; Shift bits to the right 3 times
    8.         bcs.s   +           ; If the Carry bit is set, branch and display his tails
    9.         rts             ; Otherwise, do not display Tails' tails
    10. +
    11.         jmp (Draw_Sprite).l     ; Display Tails' tails

    Done.




    You should now end up seeing Tails like this:


    [​IMG]



    Ta-dah!
     
  2. Knucklez

    Knucklez

    I love 2B 'n' ass. Member
    687
    21
    18
    This is what I've wanted to see get fixed for as long as I can remember.. Tiddles really needs to implement this in Sonic 3 Complete. Amazing work as usual, RHS.
     
  3. Rika Chou

    Rika Chou

    Tech Member
    5,276
    169
    43
    I know a bug that I don't think has been fixed with his tails.

    Stand right next to an object, like push against a monitor and then stop. His tails will have his walking/pushing animation while just standing. When you start walking again (or pushing), his tails will have a corrupt frame.

    Nice job with all these fixes, even though I never notice most of them.
     
  4. ICEknight

    ICEknight

    Researcher Researcher
    EDIT: Oops, I swear I started typing this before I saw Rika's post.

    Anyway, visual example of one of the described bugs:
    [​IMG]
     
  5. Mercury

    Mercury

    His Name Is Sonic Tech Member
    1,740
    21
    18
    Location Location
    AeStHete
    Also his tails disappear when he balances on edges.

    And when he rolls up the camera offset uses Sonic's value of 5 pixels even though the change in Tails' collision mask size isn't that great, causing a jerk each time he rolls and unrolls (and this includes jumping).

    And the temporary speed up of the tails animation when he looks up.

    Tails has a lot of little problems it seems.
     
  6. Tiddles

    Tiddles

    Diamond Dust Tech Member
    471
    0
    0
    Leicester, England
    Get in an accident and wake up in 1973
    Nice fix.

    The address of the Tails the tails belong to (what?) is already stored in parent(a0)/$3E(a0) in Sonic 2 and $30(a0) in Sonic 3, and this address is copied to a2 earlier in the object code, so you can probably skip loading and checking a1 and just use the defined a2, unless it's already been overwritten by this point (in which case you could just movea.w it back from the SST again rather than checking the player mode).

    This one at least has been addressed before.
     
  7. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    You mean, this one?
     
  8. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    For Tails' tails pushing animation error


    Are you two talking about this? If so, I've already fixed it a while back (with pictures)

    SCHG guide (has no pictures)






    For Tails' tails balancing animation addition

    I always thought his tails were behind his head, but if you do not like that, then go to "Obj05AniSelection:" and change this bit:

    Code (ASM):
    1.     dc.b    0   ; TailsAni_Balance  -> Blank

    Changing that 0 to a $A looks the best IMO, but you can try a different number to suit.




    For Tails' tails looking up speed animation glitch

    I've already fixed that also. This post actually explains how to enable debug for Tails, but if you look at the bottom of the post, it will tell you how to fix this animation bug.


    Actually, here's a quote:






    Now why didn't I spot that? =P


    Okay, changed the first post. Update everyone!
     
  9. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    Good sir, I ninja'd you.

    And yes... I get it. I'll get to those pictures. :P

    BTW, when you said on the balancing fix to change to 6... I somehow think you meant 7. 7 looks MUCH better. 6, the Tails aren't even attached to him.
    EDIT: And in return you ninja'd me... $A does look better. 7 gives the same look, but with a faster animation... I'd almost prefer 7 in this case... but I guess it's up to the user.

    OH... found one problem. Using the updated fix... Tails' tails will flash whenever he jumps or rolls, regardless of inv. time.
     
  10. Deef

    Deef

    Member
    733
    22
    18
    Wow, the OP fix looks much better; much more like a complete cartoon character. It's funny how it clashes with what I'm used to though.
     
  11. Mercury

    Mercury

    His Name Is Sonic Tech Member
    1,740
    21
    18
    Location Location
    AeStHete
    Yeah, I was basically just idly listing all the Tails glitches I knew about. Not trying to imply that they haven't been fixed before (though some of those guides I had missed before, so thanks).

    But now I guess with all those links this topic is now the go to place for cleaning up Tails' act.
     
  12. FlackoWeasel

    FlackoWeasel

    Blue cheese lover! Member
    I have also seen some bugs about Tails having 4 tails behind him sometimes. I'm not sure is it a bug though. I apologise if it isnt related. I try to remember where such errors have occured.

    E: Found a bug in Sonic 2. When the Emerald Hill 2 boss comes, he drives over Tails' tails.
     
  13. Tiddles

    Tiddles

    Diamond Dust Tech Member
    471
    0
    0
    Leicester, England
    Get in an accident and wake up in 1973
    I implemented it in S3C today and I think the problem is that a2 does get overwritten in the PLC routine, at least in 3. I just cheated and moved the new block to before the PLC load call, which appears to work OK, in this case at least.
     
  14. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber

    It was a school-boy error. I said 6 because in my hack, half the animation indexes are gone (not being used). I wasn't looking at the original Sonic 2. Comparing S2R with S2, 6 = $A. So I changed it to $A =P




    For Tails' tails priority error glitch (EHZ boss's wheels as example)


    When I implemented The S3K manager into S2, I thought it only happened then! Anyway, here is a fix, credit to flamewing for this one (see spoiler for fix, or you can see my old post here)


    Step 13 update (15/07/12) - 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:

    [​IMG]


    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"

    Code (ASM):
    1. Tails_Tails_ptr =       ramaddr( $FFFFF5C0 )

    Our new RAM is ready for use. First, go to "InitPlayers:" and under the line:

    Code (ASM):
    1.     move.b  #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040

    SVN users, yours will say:

    Code (ASM):
    1.     move.b  #ObjID_Tails,(Sidekick+id).w ; load Obj02 Tails object at $FFFFB040

    Insert this:

    Code (ASM):
    1.     move.w  #Tails_Tails,(Tails_Tails_ptr).w

    So you have something like this (SVN users, reference only):

    Code (ASM):
    1.     move.b  #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040
    2.     move.w  #Tails_Tails,(Tails_Tails_ptr).w
    3.     move.w  (MainCharacter+x_pos).w,(Sidekick+x_pos).w
    4.     move.w  (MainCharacter+y_pos).w,(Sidekick+y_pos).w
    5.     subi.w  #$20,(Sidekick+x_pos).w
    6.     addi.w  #4,(Sidekick+y_pos).w
    7.     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):

    Code (ASM):
    1. InitPlayers_TailsAlone:
    2.     move.b  #2,(MainCharacter).w ; load Obj02 Tails object at $FFFFB000
    3.     move.w  #Tails_Tails,(Tails_Tails_ptr).w
    4.     move.b  #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100
    5.     addi.w  #4,(MainCharacter+y_pos).w
    6.     rts
    7. ; 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:

    Code (ASM):
    1. loc_A2F2:
    2.     moveq   #$E,d0
    3.     move.b  #2,(a1) ; load Tails object
    4.     move.b  #$81,$2A(a1)
    5.     move.b  #5,(Object_RAM+$80).w ; load Obj05 (Tails' tails) at $FFFFB080
    6.     move.w  a1,(Object_RAM+$80+parent).w
    7.     rts

    to this:

    Code (ASM):
    1. loc_A2F2:
    2.     moveq   #$E,d0
    3.     move.b  #2,(a1) ; load Tails object
    4.     move.b  #$81,$2A(a1)
    5.     move.w  #Object_RAM+$80,(Tails_Tails_ptr).w
    6.     rts




    SVN users, change this:

    Code (ASM):
    1. loc_A2F2:
    2.     moveq   #$E,d0
    3.     move.b  #ObjID_Tails,id(a1) ; load Tails object
    4.     move.b  #$81,obj_control(a1)
    5.     move.b  #ObjID_TailsTails,(Tails_Tails_Cutscene+id).w ; load Obj05 (Tails' tails) at $FFFFB080
    6.     move.w  a1,(Tails_Tails_Cutscene+parent).w
    7.     rts

    to this:

    Code (ASM):
    1. loc_A2F2:
    2.     moveq   #$E,d0
    3.     move.b  #ObjID_Tails,id(a1) ; load Tails object
    4.     move.b  #$81,obj_control(a1)
    5.     move.w  #Tails_Tails_Cutscene,(Tails_Tails_ptr).w ; Tails' tails at $FFFFB080
    6.     rts





    Next, go to "Obj02_Init_Continued:", and change the last few lines. Change this:

    Code (ASM):
    1.     move.b  #5,(Tails_Tails).w ; load Obj05 (Tails' Tails) at $FFFFD000
    2.     move.w  a0,(Tails_Tails+parent).w ; set its parent object to this

    SVN users, yours will say:

    Code (ASM):
    1.     move.b  #ObjID_TailsTails,(Tails_Tails+id).w ; load Obj05 (Tails' Tails) at $FFFFD000
    2.     move.w  a0,(Tails_Tails+parent).w ; set its parent object to this

    And change it to this:

    Code (ASM):
    1.     movea.w (Tails_Tails_ptr).w,a1
    2.     move.b  #5,0(a1) ; load Obj05 (Tails' Tails) at $FFFFD000
    3.     move.w  a0,parent(a1) ; set its parent object to this

    And change it to this:

    Code (ASM):
    1.     movea.w  (Tails_Tails_ptr).w,a1
    2.     move.b  #ObjID_TailsTails,id(a1) ; load Obj05 (Tails' Tails)
    3.     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:

    Code (ASM):
    1.     movea.w (Tails_Tails_ptr).w,a1
    2.     tst.b   routine(a1)
    3.     beq.s   +
    4.     jmp (DisplaySprite2).l
    5. +
    6.     rts

    So you have something like this (SVN users, reference only):

    Code (ASM):
    1. Obj02:
    2.     ; a0=character
    3.     cmpi.w  #2,(Player_mode).w
    4.     bne.s   +
    5.     move.w  (Camera_Min_X_pos).w,(Tails_Min_X_pos).w
    6.     move.w  (Camera_Max_X_pos).w,(Tails_Max_X_pos).w
    7.     move.w  (Camera_Max_Y_pos_now).w,(Tails_Max_Y_pos).w
    8. +
    9.     moveq   #0,d0
    10.     move.b  routine(a0),d0
    11.     move.w  Obj02_States(pc,d0.w),d1
    12.     jsr Obj02_States(pc,d1.w)
    13.     movea.w (Tails_Tails_ptr).w,a1
    14.     tst.b   routine(a1)
    15.     beq.s   +
    16.     jmp (DisplaySprite2).l
    17. +
    18.     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.



    [​IMG]






    Reverted the original guide back to using a1, just so everyone can understand it better.



    EDIT: Added an index to my first post for quick access and changed the title to the topic.
     
  15. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    Not so much for Sonic 2. The tails will appear garbled. I'd just stick with the original one.
     
  16. Tiddles

    Tiddles

    Diamond Dust Tech Member
    471
    0
    0
    Leicester, England
    Get in an accident and wake up in 1973
    Surely it'd still be better to movea.w parent(a0),a1 (S2) or movea.w $30(a0),a1 (S3), as the object originally did to a2, rather than recalculating it from scratch based on the player mode?
     
  17. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Just tried it, seems to work fine with no side-effects. Saves a bit of time not comparing with the player_mode. Cheers, will change the first post... again =P