don't click here

Some changes and fixes for Sonic 2

Discussion in 'Engineering & Reverse Engineering' started by Esrael, Jun 7, 2012.

  1. Esrael

    Esrael

    Neto Tech Member
    304
    257
    63
    Brazil, São Paulo, Guarulhos
    Neto Assembler Editor / Sonic 2 Delta / Neto MD-DOS
    Here is another fix from rev 2.
    Tornado Spindash death.

    Find:
    Code (ASM):
    1.  
    2.   loc_3A7DE:
    3.    ......
    4.  
    5.         bsr.w   JmpTo27_SolidObject
    6.     bsr.w   loc_3AE3A
    7.     move.b  objoff_2E(a0),d0
    8.     move.b  status(a0),d1
    9.     andi.b  #8,d0    ; <---------- Change this line
    10.     andi.b  #8,d1    ; <---------- Change this line
    11.     eor.b   d0,d1
    12.     move.b  d1,objoff_2E(a0)
    13.     lea (MainCharacter).w,a1 ; a1=character
    14.     move.w  x_pos(a1),d1
    15.     move.w  (Camera_X_pos).w,d0
    16.     move.w  d0,(Camera_Min_X_pos).w
    17.  
    18.  
    Change #8 to #1 and you can do spindash in Tornado.

    Code (ASM):
    1.  
    2.   loc_3A7DE:
    3.    ......
    4.  
    5.         bsr.w   JmpTo27_SolidObject
    6.     bsr.w   loc_3AE3A
    7.     move.b  objoff_2E(a0),d0
    8.     move.b  status(a0),d1
    9.     andi.b  #1,d0    ; <---------- Change this line
    10.     andi.b  #1,d1    ; <---------- Change this line
    11.     eor.b   d0,d1
    12.     move.b  d1,objoff_2E(a0)
    13.     lea (MainCharacter).w,a1 ; a1=character
    14.     move.w  x_pos(a1),d1
    15.     move.w  (Camera_X_pos).w,d0
    16.     move.w  d0,(Camera_Min_X_pos).w
    17.  

    And Another bug with Miles in ARZ Boss.
    If you stand in one arrow with Sonic the arrow will fall, but not with Miles.
    How To fix

    Find:
    Code (ASM):
    1.  
    2. loc_30CCC:
    3.         ......
    4.  
    5.         btst    #3,status(a0)
    6.     beq.s   return_30D02
    7.     move.w  #$1F,objoff_30(a0)
    8.  
    9. loc_30CF4:
    10.  
    and change to

    Code (ASM):
    1.  
    2. loc_30CCC:
    3.        ......
    4. ;-------------------------------------------------------------------------------
    5.         btst    #$04, status(A0)
    6.         beq.s   Not_Miles_In_Arrow
    7.         move.w  #$001F, objoff_30(A0)  
    8. Not_Miles_In_Arrow:
    9. ;-------------------------------------------------------------------------------
    10.         btst    #3,status(a0)
    11.     beq.s   return_30D02
    12.     move.w  #$1F,objoff_30(a0)
    13.  
    14. loc_30CF4:
    15.  
    Done.
     
  2. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    I wanna touch back on the CPZ boss for a second. There is a minor bug that occurs when you die against the boss. If you or Tails die against the boss, and are under the solid floor, the character will hit the floor and just drop, instead of the proper behavior. Now, I have no problem with said bug... but just noting that its there.
     
  3. Esrael

    Esrael

    Neto Tech Member
    304
    257
    63
    Brazil, São Paulo, Guarulhos
    Neto Assembler Editor / Sonic 2 Delta / Neto MD-DOS
    This is not a boss error. This effect can occur in any place with solity over Sonic Head like the location in the following picture.

    [​IMG]
    Edit: Using debug and moving left will case the problem reported.

    This is not necessary a bug (I think), but you can use the following code to disable floor detection while dying.
    find:
    Code (ASM):
    1.  
    2. ; loc_1E596:
    3. Floor_ChkTile:
    4.     move.w  d2,d0
    5.         ....
    6.     movea.l d1,a1
    7.     rts
    8. ; ===========================================================================
    9. ; precalculated values for Floor_ChkTile
    10. ; (Sonic 1 calculated it every time instead of using a table)
    11. word_1E5D0:
    12.  
    and insert the following code:

    Code (ASM):
    1.  
    2. ; loc_1E596:
    3. Floor_ChkTile:
    4.     move.w  d2,d0
    5.         ....
    6.     movea.l d1,a1
    7.         cmpi.b  #$06, $0024(A0)  
    8.         bne.s   Player_Not_Death  
    9.  
    10.         cmpi.b  #$01, (A0)          ; Is Sonic  
    11.         beq.s   Player_Death       ;
    12.         cmpi.b  #$02, (A0)          ;  Is Miles
    13.         bne.s   Player_Not_Death ;  
    14. Player_Death:                         ;
    15.  
    16.         move.l  #$FFFF0000, A1                                                                  
    17. Player_Not_Death:
    18.     rts
    19. ; ===========================================================================
    20. ; precalculated values for Floor_ChkTile
    21. ; (Sonic 1 calculated it every time instead of using a table)
    22. word_1E5D0:
    23.  
    This code will point to the first tile in RAM which have no solidity. Since Sonic object can't find solidity will show the dying animation.

    Edit: Correct check. The Current Character is in A0
    Edit: Metal Sonic Fall Bug caused by new code.

    Edit: 28/05/2019 - Fixed broken links

    Best regards:
    ----------------------
    Neto.
     
  4. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    Sweet deal, Esrael! BTW should the address be A0? or a0?
    You have A0 and A1 with capital letters. Shouldn't they be lower case? or it doesn't matter?
     
  5. redhotsonic

    redhotsonic

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

    It's not case-sensitive so it doesn't matter what you put. As long as you get the number right.
     
  6. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    Disable floor collision while dying - Nice add... I must say. I'm gonna go ahead and see if I can be the one to put this in Sonic 1 on my own...

    Going to add more to the wiki today.
     
  7. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I might as well post another



    How to fix monitors' collision



    There's a bug in Sonic 2 that's not in any other game. The monitor's collision. Well, I say collision, but it's actually fine. It's the touch_collision that's actually wrong.


    The thing is, in the original Sonic 2 game, it's very hard to spot this bug. Mainly because the monitors are all placed on a flat floor. But whereas many of us have change the level layout of our hacks, some of you may of placed them on hills or slopes (or at the beginning/end of slopes/hills), the bug may be noticeable.



    The bug? You go straight through the monitors without destroying it. This can be a pain in the ass.

    The bad thing about it is, if you've placed a monitor on a hill but near a wall, there's a great chance you can go through that wall. This isn't meant to happen obviously.



    To demonstrate, I have enabled debug and put a monitor in the air. I have now ran and jumped to it.

    [​IMG]

    [​IMG]



    If you come from either side of the monitor, but Sonic going up, you will go through the monitor. That's why this bug is more common on hills/slopes. If you're rolling up a hill into the side of the monitor, chances are you'll go through it without destroying it.

    [​IMG]



    Code (ASM):
    1. ; loc_3F73C:
    2. Touch_Monitor:
    3.     tst.w   y_vel(a0)   ; is Sonic moving upwards?
    4.     bpl.s   loc_3F768   ; if not, branch
    5.     move.w  y_pos(a0),d0
    6.     subi.w  #$10,d0
    7.     cmp.w   y_pos(a1),d0
    8.     bcs.s   return_3F78A
    9.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion
    10.     move.w  #-$180,y_vel(a1)
    11.     tst.b   routine_secondary(a1)
    12.     bne.s   return_3F78A
    13.     move.b  #4,routine_secondary(a1) ; set the monitor's routine counter
    14.     rts


    It does this because there are checks to see if you've hit the bottom of the monitor and if so, to knock the monitor (hit a monitor directly underneath, you know what I mean). But if you go through the sides, it does this check, and it thinks you've missed the bottom when going up to hit it from underneath. Because of this, it branches to an rts.

    In the code above, it asks if you're moving up and if not, branch away to destroy the monitor. But if moving up, it's doing the check to see if you're going to hit the bottom of the monitor. If you do, it will reverse Sonic's y_vel, and change the routine of the monitor so it can be knocked and fall. BUT, if you miss the bottom, it will branch to "return_3F78A" which is an rts. So, if you're hitting the side of the monitor but in an upwards state, it will branch to the rts; making Sonic go through the monitor and not breaking it. As soon as Sonic's y_vel hits 0 or more (starts to fall down), the monitor will break, because of the very first command.



    So, we need to make the monitor breakable by hitting the side of it but still going up. Here's how. Go to the code I just showed you above, and change it to this:


    Code (ASM):
    1. ; loc_3F73C:
    2. Touch_Monitor:
    3.     tst.w   y_vel(a0)   ; is Sonic moving upwards?
    4.     bpl.s   loc_3F768   ; if not, branch
    5.     move.w  y_pos(a0),d0
    6.     subi.w  #$10,d0
    7.     cmp.w   y_pos(a1),d0
    8.     bcs.s   loc_3F768   ; Changed to loc_3F768 instead of return_3F78A
    9.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion
    10.     move.w  #-$180,y_vel(a1)
    11.     tst.b   routine_secondary(a1)
    12.     bne.s   return_3F78A
    13.     move.b  #4,routine_secondary(a1) ; set the monitor's routine counter
    14.     rts
    All we've done here is changed "return_3F78A" to "loc_3F768". So now, when moving up but hitting the sides of the monitor, instead of it branching to "rts", it branches to the "break monitor" coding!


    [​IMG]

    [​IMG]


    As you can see in the pictures, you will now destroy them. You can still hit the bottom of the monitor and it will knock over. Any other way of hitting the monitor remains unaffected.



    Done.






    Additional step you might want to take


    It's now fixed, but there remains one design flaw (which is actually present in S3K). You know when you hit the monitor, like jumping on it, Sonic's y_vel negates, so he appears to bounce. But with our new fix, if you destroy the monitor from the sides going up, Sonic's y_vel still negates, so he shoots down. It does this in S3K also. To me, this looks unnatural. If you like this, ignore this step. If you don't want Sonic's y_vel to negate when going up, but still to negate when going down, it's simple to do so.


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

    Code (ASM):
    1. loc_3F768:
    2.     cmpa.w  #MainCharacter,a0
    3.     beq.s   +
    4.     tst.w   (Two_player_mode).w
    5.     beq.s   return_3F78A
    6. +
    7.     cmpi.b  #2,anim(a0)
    8.     bne.s   return_3F78A
    9.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion
    10.     move.b  #4,routine(a1)
    11.     move.w  a0,parent(a1)
    12.  
    13. return_3F78A:
    14.     rts
    See that? It's negating Sonic's y_vel no matter what when you destroy the monitor. We don't want it to when we're going up, we want to carry on going up. So, change it to this:

    Code (ASM):
    1. loc_3F768:
    2.     cmpa.w  #MainCharacter,a0
    3.     beq.s   +
    4.     tst.w   (Two_player_mode).w
    5.     beq.s   return_3F78A
    6. +
    7.     cmpi.b  #2,anim(a0)
    8.     bne.s   return_3F78A
    9.     tst.w   y_vel(a0)   ; is Sonic moving upwards?
    10.     blt.s   +       ; if so, branch, we want Sonic to carry on moving up
    11.     ; So, Sonic is moving down instead?
    12.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion, to give him that bounce off the monitor
    13. +
    14.     move.b  #4,routine(a1)
    15.     move.w  a0,parent(a1)
    16.  
    17. return_3F78A:
    18.     rts

    Now, it checks if you're moving up, and if so, do NOT negate Sonic's y_vel. If you're moving down, it won't branch, and negate his y_vel, giving him his bounce.


    All done!




    Cheers,
    redhotsonic





    EDIT: I might as well explain. This bug is only in Sonic 2. In Sonic 1, it branches to a subroutine to make the sides of the monitor completely solid, but you can't destroy the monitor still. In Sonic 3 and Knuckles, the coding for hitting the monitor underneath no longer exists. If you hit it underneath in S3K, it will get destroyed. So no bug there.
     
  8. Tiddles

    Tiddles

    Diamond Dust Tech Member
    471
    0
    0
    Leicester, England
    Get in an accident and wake up in 1973
    Although if you implement it in S3K and keep the code to destroy the monitor from below instead of dropping it, not bouncing back down might look a bit funny.

    My "fix" for this in Sonic 3 Complete is a bit different - if Sonic is on the ground, I use the S&K behaviour, I.e. he can roll through anything regardless of angle. If he's in the air, I use essentially Sonic 1 style behaviour where the sides are treated as solid, because I detest the way you can just jump straight sideways into a monitor in S&K rather than having to go over and land on it. However, I'm not actually too happy with how the solid sides stuff is working, at least my implementation of it (some interesting effects can happen when landing around multiple monitors without rolling), and it may later be reverted to Sonic 2/3A style behaviour in the air, where it's technically possible to jump through - but it's such a rare case in the air that I'm not too troubled by it.

    Incidentally, I'm pretty sure it is possible to have this bug affect you in vanilla Sonic 3, though you are unlikely to see it without special effort. At the start of CNZ2, there are three monitors suspended in a room a long way above the bottom of the first diagonal barber pole thingy. Tails can fly up there and knock them down to the ground below, which will cause them to land on slopes where it's possible to spindash through them.

    A question about one of the previous fixes. For the ARZ arrows, you suggest making the code faster by using a cmpi.b to check for Sonic's ducking animation rather than a cmpi.w to check the real frame, which slightly changes the behaviour in that Sonic additionally becomes immune during his partially-crouched state. My question - and I feel like this is something I should probably know if I have a green badge, but so what - is whether that saves any notable number of cycles in reality, particularly given the tradeoff that it changes the intended behaviour of the game? I would not normally choose such a tradeoff but I might be swayed if the optimisation is genuinely worthwhile.
     
  9. redhotsonic

    redhotsonic

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


    It's entirely your choice which you pick. The off-frame only happens for a split second, and pretty much not noticeable. It DOES save a fair bit of time in reality. Reason why:

    Code (ASM):
    1.         cmpi.b  #9,anim(a0)             ; is Sonic spindashing?
    2.         beq.s   Duckinganddashing       ; if so, branch
    3. ;-------------------------------------------------------------------------------              
    4.         cmpi.b  #$02, (A0)              ; Is Miles?
    5.         bne.s   Touch_Check_Sonic       ; Not goto Sonic routine
    6.         cmpi.b  #$5B, mapping_frame(A0) ; is Miles ducking
    7.         bne.s   Touch_NoDuck                  
    8.         bra.s   Duckinganddashing
    9. Touch_Check_Sonic:
    10. ;-------------------------------------------------------------------------------  
    11.         cmpi.b  #$4D,mapping_frame(a0)  ; is Sonic ducking?
    12.         bne.s   Touch_NoDuck            ; if not, branch
    13. Duckinganddashing:              ; So, Sonic is spindashing or ducking
    14.         addi.w  #$C,d3
    15.         moveq   #$A,d5
    16. ; loc_3F592:
    17. Touch_NoDuck:
    Imagine you're Sonic, and you hold the down button to crouch. Imagine Tails is following you, he copies your controls, so he's also crouching.


    Esrael's way:

    Sonic: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you Tails? Nope, let's branch. Is Sonic ducking? Yes, do not branch.

    Tails: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you Tails? Yes! Continue, is he ducking? Yes! So do not branch. Then branch to the ducking routine.



    This has got to be repeated for both Sonic and Tails every single frame. And that's touch_response only. It's also got to do this again for BOTH Sonic and Tails in the ring code! So, it's doing it 4 times in a frame. Then if you're in CNZ, for the bumpers, it's got to do it again for both of them, that's 6 times every frame! It's got to keep asking if you're Tails, and it's got to do more branches.




    My way:

    Code (ASM):
    1.         cmpi.b  #9,anim(a0)             ; is Sonic spindashing?
    2.         beq.s   Duckinganddashing       ; if so, branch
    3.         cmpi.b  #8,anim(a0)             ; is Sonic ducking?
    4.         bne.s   Touch_NoDuck            ; if not, branch
    5. Duckinganddashing:              ; So, Sonic is spindashing or ducking
    6.         addi.w  #$C,d3
    7.         moveq   #$A,d5
    8. ; loc_3F592:
    9. Touch_NoDuck:

    Again, imagine you're Sonic, and you hold the down button to crouch. Imagine Tails is following you, he copies your controls, so he's also crouching.


    Sonic: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you ducking? Yes, do not branch and do the routine.

    Tails: Exactly the same.



    Basically, mine has saved it from asking if you're Tails all the time and stopping it from branching here and there. It may not look much, but seeming as it has to do this for BOTH Sonic and Tails every single frame, same with rings and if CNZ, the bumpers, my way will save it a fair few cycles.


    [​IMG]

    Seeming as Sonic is like this for only a split second, I think my way is better. In my hack, I've got it set to the coding I've shown. And I've never noticed any difference to what is was like before. But it all depends on preference. If you don't like this fact (or even knowing it), then Esrael's way is the way to go. But it just will take a little tiny bit longer.


    If going Esrael's way, the slowdown probably won't be noticeable unless near water or in it, or when you lose a lot of rings.




    EDIT: In fact, in S3K, this is completely gone from the game. It doesn't bother shortening his y_radius when ducking or spindashing. I guess they've done this to save cycles. And the other reason is because there isn't really any point you would "duck" to avoid anything. I tried placing the shooting arrow (from that head object in Marble Garden Zone) and tried avoiding it by ducking, and when it's about to miss you, it still hurts you. The checks isn't present in the touch_response, the rings collision or the boss (obviously no bumbers from CNZ).
     
  10. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Well, I will now go forth and backport these fixes into my hack. Esrael and RHS, you both have made you way into the Special Thanks section of the credits.
     
  11. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Cool, I know that means I've done well.



    Can I suggest something to any admin or staff? Can this topic be pinned? That way in the future, all members will see this and can spot these bug fixes and apply them, making further Sonic 2 hacks bug-ridden. Just a suggestion.
     
  12. Jayextee

    Jayextee

    Unpopular Opinions™ Member
    3,253
    62
    28
    Atro City
    I DONE MAKED GAMES.
    Don't you mean 'bug-fixed'? ;)
     
  13. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    What I meant was that all future hacks will have got "rid" of all the bugs we've mentioned. Not all hacks in the future will be "ridden" with bugs =P
     
  14. Overlord

    Overlord

    Now playable in Smash Bros Ultimate Moderator
    19,231
    968
    93
    Long-term happiness
    To be fair, this is the sort of thing the SCHG is for...
     
  15. Esrael

    Esrael

    Neto Tech Member
    304
    257
    63
    Brazil, São Paulo, Guarulhos
    Neto Assembler Editor / Sonic 2 Delta / Neto MD-DOS
    While testing and playing I have found a bug with Metal Sonic. He will fall forever since he can't detect the floor, because his initial animation use same id as Sonic and Miles while dying. To fix add the following lines to code:

    Code (ASM):
    1.  
    2. ; loc_1E596:
    3. Floor_ChkTile:
    4.     move.w  d2,d0
    5.         ....
    6.     movea.l d1,a1
    7. ;--------------------------------------
    8.         cmpi.b  #$06, $0024(A0)  
    9.         bne.s   Player_Not_Death  
    10.         cmpi.b  #$01, (A0)          ; Is Sonic  
    11.         beq.s   Player_Death       ;
    12.         cmpi.b  #$02, (A0)          ;  Is Miles
    13.         bne.s   Player_Not_Death ;  
    14. Player_Death:                         ;
    15.         move.l  #$FFFF0000, A1                                                                  
    16. Player_Not_Death:
    17. ;---------------------------------------
    18.     rts
    19. ; ===========================================================================
    20. ; precalculated values for Floor_ChkTile
    21. ; (Sonic 1 calculated it every time instead of using a table)
    22. word_1E5D0:
    23.  
    The following explanation is for Sonic 2 rev 2.
    About Metal Sonic, there is a very well know bug in Sonic 2 rev 2 (see image). But there is another in rev 2 which is not noticed with Grabber enemy legs (see image)
    [​IMG]

    The following code is shared between Metal Sonic and Grabber enemy

    Code from Sonic 2 rev 1
    Code (ASM):
    1.  
    2. loc_367AA:
    3.     move.b  render_flags(a0),d0
    4.     andi.b  #$FC,d0
    5.     move.b  status(a0),d2
    6.     andi.b  #$FC,d2
    7.     move.b  render_flags(a1),d1
    8.     andi.b  #3,d1
    9.     or.b    d1,d0
    10.     or.b    d1,d2
    11.     move.b  d0,render_flags(a0)
    12.     move.b  d2,status(a0)
    13.     rts
    14.  
    Code from Sonic 2 rev 2 which cause Metal Sonic and Grabber enemy legs bug
    Code (ASM):
    1.  
    2. Offset_0x0361D0: ; Usado pelo objeto 0xA7 - Grabber
    3.                 move.b  $0001(A0), D0
    4.                 andi.b  #$FD, D0         ; <----------- #$FC in rev 1
    5.                 move.b  $0022(A0), D2
    6.                 andi.b  #$FD, D2         ; <----------- #$FC in rev 1
    7.                 move.b  $0001(A1), D1
    8.                 andi.b  #$02, D1          ; <----------- #$03 in rev 1
    9.                 or.b    D1, D0
    10.                 or.b    D1, D2
    11.                 move.b  D0, $0001(A0)
    12.                 move.b  D2, $0022(A0)
    13.                 rts
    14.  
    Why this code was changed???

    Edit: 28/05/2019 - Fixed broken links

    Best regards:
    ----------------------
    Neto.
     
  16. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    @redhotsonic. I agree with Overlord. Pinning this defeats the purpose of a SCHG wiki in some respect.
    That being said...

    KingofHarts Page update!
    http://info.sonicret...Z_Tornado_death - I made a small error in the page title... I wanted it to say "Prevent SCZ Tornado spin dash death" If an admin, wiki sysop, or someone could fix that, would be good... or if its not a big deal, then leave it
    http://info.sonicret...ion_while_dying - Added the fix to allow Silver Sonic to land on the floor
    http://info.sonicret...r_collision_bug

    And about this...

    Isn't this to prevent Tails from fucking you over on the boss? I'm not against this fix, but if its to be performed, it should be more of a design choice, and while we are at it... should have some kind of guide that allows Tails to do other stuff... like break monitors, etc. I would think putting that all together into one guide would be sufficient.
     
  17. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    From what I can tell, the bug mentioned only happens when Sonic (or Tails) is on the air and dies due to falling of the bottom of the screen; if I am wrong, please ignore me. This is the only case when there are physics checks (collision, movement) on the same frame as Sonic (or Tails dies) due to the location where it happens in code. So there is a neater fix that also does not cause the problem with Metal Sonic (and who knows how many other problems -- maybe with animals?).

    I will give the labels for the SVN disassembly, and the nearest 2007 label I can find. For Sonic, find this block of code:
    Code (ASM):
    1. Sonic_Boundary_Bottom: ;;
    2.     bra.w   JmpTo_KillCharacter
    3. ; ===========================================================================
    4. ; loc_1A9BA:
    and change it to this:
    Code (ASM):
    1. Sonic_Boundary_Bottom: ;;
    2.     addq.l    #4,sp
    3.     bra.w   JmpTo_KillCharacter
    4. ; ===========================================================================
    5. ; loc_1A9BA:
    For Tails, the relevant code block is this:
    Code (ASM):
    1. Tails_Boundary_Bottom: ;;
    2.     bra.w   JmpTo2_KillCharacter
    3. ; ===========================================================================
    4. ; loc_1C5A0:
    Do the same change as for Sonic.

    These changes will cause Sonic (and Tails) to skip some subroutines for the current control mode; this includes some that move Sonic (or Tails) and either make Sonic/Tails follow the ground or collide with the level. This will only happen during one frame; starting the next frame will work as normal since a different subroutine will be used. Being crushed by objects, drowning and being killed by badniks don't need to be changed because they all happen after the physics updates, and will only make effect on the next frame.
     
  18. Esrael

    Esrael

    Neto Tech Member
    304
    257
    63
    Brazil, São Paulo, Guarulhos
    Neto Assembler Editor / Sonic 2 Delta / Neto MD-DOS

    For Miles breaking Monitors do the following changes:

    Find and delete:

    Code (ASM):
    1.  
    2. ; sub_12768:
    3. SolidObject_Monitor_Tails:
    4.     btst    d6,status(a0)
    5.     bne.s   loc_12782
    6.     tst.w   (Two_player_mode).w    ; <--- Comment or delete this line
    7.     beq.w   loc_199F0              ; <--- Comment or delete this line
    8.     cmpi.b  #2,anim(a1)
    9.     bne.w   loc_199F0
    10.     rts
    11. ; End of function SolidObject_Monitor_Tails
    12.  
    13. ; ---------------------------------------------------------------------------
    14.  
    15.  
    as result
    Code (ASM):
    1.  
    2. ; sub_12768:
    3. SolidObject_Monitor_Tails:
    4.     btst    d6,status(a0)
    5.     bne.s   loc_12782
    6.     cmpi.b  #2,anim(a1)
    7.     bne.w   loc_199F0
    8.     rts
    9. ; End of function SolidObject_Monitor_Tails
    10.  
    11. ; ---------------------------------------------------------------------------
    12.  
    13.  
    and find:
    Code (ASM):
    1.  
    2. loc_3F768:
    3.     cmpa.w  #MainCharacter,a0      ; <--- Comment or delete this line
    4.     beq.s   +                      ; <--- Comment or delete this line
    5.     tst.w   (Two_player_mode).w    ; <--- Comment or delete this line
    6.     beq.s   return_3F78A           ; <--- Comment or delete this line
    7. +                                      ; <--- Comment or delete this line
    8.     cmpi.b  #2,anim(a0)
    9.     bne.s   return_3F78A
    10.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion
    11.     move.b  #4,routine(a1)
    12.     move.w  a0,parent(a1)
    13.  
    14. return_3F78A:
    15.     rts
    16.  
    as result
    Code (ASM):
    1.  
    2. loc_3F768:
    3.     cmpi.b  #2,anim(a0)
    4.     bne.s   return_3F78A
    5.     neg.w   y_vel(a0)   ; reverse Sonic's y-motion
    6.     move.b  #4,routine(a1)
    7.     move.w  a0,parent(a1)
    8.  
    9. return_3F78A:
    10.     rts
    11.  
    This will allow Miles breaking monitors, but now Miles will be awarded with Monitor contents.
    If you don't want Miles getting monitors rewards you will need do some changes code as example Super Rings:

    Find:
    Code (ASM):
    1.  
    2. super_ring:
    3.     addq.w  #1,(a2)
    4.     lea (Ring_count).w,a2
    5.     lea (Update_HUD_rings).w,a3
    6.     lea (Extra_life_flags).w,a4
    7.     lea ($FFFFFEF0).w,a5
    8.     cmpa.w  #MainCharacter,a1
    9.     beq.s   loc_12992
    10.     lea (Ring_count_2P).w,a2
    11.     lea (Update_HUD_rings_2P).w,a3
    12.     lea (Extra_life_flags_2P).w,a4
    13.     lea ($FFFFFEF2).w,a5
    14.  
    15. loc_12992:
    16.  
    and add the following lines
    Code (ASM):
    1.  
    2. super_ring:
    3.     addq.w  #1,(a2)
    4.     lea (Ring_count).w,a2
    5.     lea (Update_HUD_rings).w,a3
    6.     lea (Extra_life_flags).w,a4
    7.     lea ($FFFFFEF0).w,a5
    8.     cmpa.w  #MainCharacter,a1
    9.     beq.s   loc_12992
    10.         tst.w   (Two_player_mode).w    ; Add this line
    11.     beq.s   loc_12992              ; Add this line
    12.     lea (Ring_count_2P).w,a2
    13.     lea (Update_HUD_rings_2P).w,a3
    14.     lea (Extra_life_flags_2P).w,a4
    15.     lea ($FFFFFEF2).w,a5
    16.  
    17. loc_12992:
    18.  
    This will be necessary for all items which you want Main player to be rewarded.
     
  19. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    That's true. Thought I'd suggest =P




    Anyway, another bug fix:




    How to fix the CPZ pipes bug



    So here's the demonstration of the glitch from another user on YouTube. This only happens when you've got hurt and land straight into the pipe's entrance. To be honest, this is very rare that you'll pull this bug off. But if you want to fix it anyway, it's extremely simple to.



    Go to "loc_225FC:" and look for these commands:

    Code (ASM):
    1.     moveq   #0,d3
    2.     cmpi.w  #$A0,d2
    3.     beq.s   +

    Just above the "moveq #0,d3", add this line:

    Code (ASM):
    1.     move.b  #2,routine(a1)  ; In case character was hurt, make him okay again, fixes bug

    So, you end up with this:

    Code (ASM):
    1. loc_225FC:
    2.     tst.w   (Debug_placement_mode).w
    3.     bne.w   return_22718
    4.     move.w  objoff_2A(a0),d2
    5.     move.w  x_pos(a1),d0
    6.     sub.w   x_pos(a0),d0
    7.     cmp.w   d2,d0
    8.     bcc.w   return_22718
    9.     move.w  y_pos(a1),d1
    10.     sub.w   y_pos(a0),d1
    11.     cmpi.w  #$80,d1
    12.     bcc.w   return_22718
    13.     cmpi.b  #$20,anim(a1)
    14.     beq.w   return_22718
    15.  
    16.     move.b  #2,routine(a1)  ; In case character was hurt, make him okay again, fixes bug
    17.     moveq   #0,d3
    18.     cmpi.w  #$A0,d2
    19.     beq.s   +
    20.     moveq   #8,d3
    21.     cmpi.w  #$120,d2
    22.     beq.s   +
    23.     moveq   #4,d3
    24.     neg.w   d0
    25.     addi.w  #$100,d0
    26. +

    Done! You should now end up with this:




    Cheers,
    redhotsonic



    EDIT: Forgot to mention, this will also fix it for the sidekick.
     
  20. MoDule

    MoDule

    Tech Member
    327
    24
    18
    Procrastinating from writing bug-fix guides
    I've had that one lying around for a while, too. Only difference is I put the fix here:
    Code (ASM):
    1. loc_22688:
    2.     move.b  d2,1(a4)
    3.     add.w   d3,d2
    4.     add.w   d2,d2
    5.     andi.w  #$1E,d2
    6.     lea off_22980(pc),a2
    7.     adda.w  (a2,d2.w),a2
    8.     move.w  (a2)+,4(a4)
    9.     subq.w  #4,4(a4)
    10.     move.w  (a2)+,d4
    11.     add.w   x_pos(a0),d4
    12.     move.w  d4,x_pos(a1)
    13.     move.w  (a2)+,d5
    14.     add.w   y_pos(a0),d5
    15.     move.w  d5,y_pos(a1)
    16.     move.l  a2,6(a4)
    17.     move.w  (a2)+,d4
    18.     add.w   x_pos(a0),d4
    19.     move.w  (a2)+,d5
    20.     add.w   y_pos(a0),d5
    21.     addq.b  #2,(a4)
    22.  
    23.     move.b  #2,routine(a1)  ; <---
    24.  
    25.     move.b  #$81,obj_control(a1)
    26.     move.b  #AniIDSonAni_Roll,anim(a1)
    27.     move.w  #$800,inertia(a1)
    But as far as I can tell, it doesn't make a difference.

    I'll contribute one:
    Fix Tails interacting with forced roll switchers while flying bug

    Most commonly seen in CNZ, when you lose Tails and he starts flying after you, sometimes he'll be stuck in an odd animation and when he lands will be in forced rolling mode.

    So, to fix this, first we go to Obj84_MainY (loc_212F6) and we'll see this:
    Code (ASM):
    1. ; loc_212F6:
    2. Obj84_MainY:
    3.  
    4.     tst.w   (Debug_placement_mode).w
    5.     bne.s   return_21350
    6.     move.w  y_pos(a0),d1
    7.     lea objoff_34(a0),a2 ; a2=object
    8.     lea (MainCharacter).w,a1 ; a1=character
    9.     bsr.s   +
    10.     lea (Sidekick).w,a1 ; a1=character
    11. +
    12.     tst.b   (a2)+
    13.     bne.s   Obj84_MainY_Alt
    14.     cmp.w   y_pos(a1),d1
    15.     bhi.s   return_21350
    16.     move.b  #1,-1(a2)
    17.     move.w  x_pos(a0),d2
    18.     move.w  d2,d3
    19.     move.w  objoff_32(a0),d4
    20.     sub.w   d4,d2
    21.     add.w   d4,d3
    22.     move.w  x_pos(a1),d4
    23.     cmp.w   d2,d4
    24.     blo.s   return_21350
    25.     cmp.w   d3,d4
    26.     bhs.s   return_21350
    27.     btst    #0,render_flags(a0)
    28.     bne.s   +
    29.     move.b  #1,spindash_flag(a1)
    30.     bra.w   loc_212C4
    31. ; ---------------------------------------------------------------------------
    32. +   move.b  #0,spindash_flag(a1)
    33.  
    34. return_21350:
    35.     rts
    Now, after the line
    Code (ASM):
    1.     lea (Sidekick).w,a1 ; a1=character
    add this:
    Code (ASM):
    1.     cmpi.w  #4,(Tails_CPU_routine).w    ; TailsCPU_Flying
    2.     beq.s   return_21350
    which should leave us with this:
    Code (ASM):
    1. ; loc_212F6:
    2. Obj84_MainY:
    3.  
    4.     tst.w   (Debug_placement_mode).w
    5.     bne.s   return_21350
    6.     move.w  y_pos(a0),d1
    7.     lea objoff_34(a0),a2 ; a2=object
    8.     lea (MainCharacter).w,a1 ; a1=character
    9.     bsr.s   +
    10.     lea (Sidekick).w,a1 ; a1=character
    11.  
    12.     cmpi.w  #4,(Tails_CPU_routine).w    ; TailsCPU_Flying
    13.     beq.s   return_21350
    14.  
    15. +
    16.     (...)
    Done.

    What we're doing here is simply skipping the collision check with the pinball mode switcher object for the second player if he's currently flying.