don't click here

How to fix the scattered rings underwater

Discussion in 'Engineering & Reverse Engineering' started by redhotsonic, Mar 24, 2012.

  1. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Any bugs, let me know!


    For a Sonic 2 guide, keep reading this post.

    For a Sonic 1 guide, read this post.

    For a Sonic 3 and Knuckles guide, read this post.




    (This isn't actually a bug as such, it's a design change. This guide is for Sonic 2)


    [​IMG]

    Ah, the scattered rings when you get hurt. It can cause slowdown to your game, and even mess up the under water palette. Now, when Sonic is underwater, his movement and his gravity is changed so he moves slower to act like he's in water. But when he is hurt under water, isn't it funny that the scattered rings still act the same as if you weren't in water?

    [​IMG]

    In this very short tutorial, I will tell you how to make the rings act correctly under water. I am using Xenowhirl's Disassembly. For other disassemblies, it must be extremely similar to this so I'm sure you won't have a problem if you follow this guide. Remember, always back up your disassembly first before following guides. I will not be held responsible if anything goes wrong.


    First, go to "loc_120BA:" (part of the scattered rings object code) and find this bit of coding:

    Code (ASM):
    1.   bsr.w JmpTo4_CalcSine
    2.   move.w d4,d2
    3.   lsr.w #8,d2
    Just underneath, paste this:

    Code (ASM):
    1.     tst.b   (Water_flag).w      ; Does the level have water?
    2.     beq.s   +           ; If not, branch and skip underwater checks
    3.     move.w  (Water_Level_2).w,d6    ; Move water level to d6
    4.     cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.     bgt.s   +           ; If not, branch and skip underwater commands
    6.     asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    7.     asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    8. +

    So, you should end up with something looking like this:

    Code (ASM):
    1. loc_120BA:
    2.     _move.b #$37,0(a1) ; load obj37
    3.     addq.b  #2,routine(a1)
    4.     move.b  #8,y_radius(a1)
    5.     move.b  #8,x_radius(a1)
    6.     move.w  x_pos(a0),x_pos(a1)
    7.     move.w  y_pos(a0),y_pos(a1)
    8.     move.l  #Obj25_MapUnc_12382,mappings(a1)
    9.     move.w  #$26BC,art_tile(a1)
    10.     bsr.w   Adjust2PArtPointer2
    11.     move.b  #$84,render_flags(a1)
    12.     move.b  #3,priority(a1)
    13.     move.b  #$47,collision_flags(a1)
    14.     move.b  #8,width_pixels(a1)
    15.     move.b  #-1,(Ring_spill_anim_counter).w
    16.     tst.w   d4
    17.     bmi.s   loc_12132
    18.     move.w  d4,d0
    19.     bsr.w   JmpTo4_CalcSine
    20.     move.w  d4,d2
    21.     lsr.w   #8,d2
    22.     tst.b   (Water_flag).w      ; Does the level have water?
    23.     beq.s   +           ; If not, branch and skip underwater checks
    24.     move.w  (Water_Level_2).w,d6    ; Move water level to d6
    25.     cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    26.     bgt.s   +           ; If not, branch and skip underwater commands
    27.     asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    28.     asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    29. +
    30.     asl.w   d2,d0
    31.     asl.w   d2,d1
    32.     move.w  d0,d2
    33.     move.w  d1,d3
    34.     addi.b  #$10,d4
    35.     bcc.s   loc_12132
    36.     subi.w  #$80,d4
    37.     bcc.s   loc_12132
    38.     move.w  #$288,d4
    This ensures that when underwater, the rings x_vel and y_vel are halved so they appear to be moving slower.



    Next, go to label "Obj_37_sub_2:" and under

    Code (ASM):
    1.     move.b  (Ring_spill_anim_frame).w,mapping_frame(a0)
    2.     bsr.w   ObjectMove
    3.     addi.w  #$18,y_vel(a0)
    Put this:

    Code (ASM):
    1.     tst.b   (Water_flag).w      ; Does the level have water?
    2.     beq.s   +           ; If not, branch and skip underwater checks
    3.     move.w  (Water_Level_2).w,d6    ; Move water level to d6
    4.     cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.     bgt.s   +           ; If not, branch and skip underwater commands
    6.     subi.w  #$E,y_vel(a0)       ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings
    7. +
    You can change the value of the gravity if you like, but I found $E to suit.

    So, you should have something looking like this:

    Code (ASM):
    1. Obj_37_sub_2:
    2.  
    3.     move.b  (Ring_spill_anim_frame).w,mapping_frame(a0)
    4.     bsr.w   ObjectMove
    5.     addi.w  #$18,y_vel(a0)
    6.     tst.b   (Water_flag).w      ; Does the level have water?
    7.     beq.s   +           ; If not, branch and skip underwater checks
    8.     move.w  (Water_Level_2).w,d6    ; Move water level to d6
    9.     cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    10.     bgt.s   +           ; If not, branch and skip underwater commands
    11.     subi.w  #$E,y_vel(a0)       ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings
    12. +
    13.     bmi.s   loc_121B8
    14.     move.b  ($FFFFFE0F).w,d0
    15.     add.b   d7,d0
    16.     andi.b  #7,d0
    17.     bne.s   loc_121B8
    18.     tst.b   render_flags(a0)
    19.     bpl.s   loc_121D0
    20.     jsr (RingCheckFloorDist).l
    21.     tst.w   d1
    22.     bpl.s   loc_121B8
    23.     add.w   d1,y_pos(a0)
    24.     move.w  y_vel(a0),d0
    25.     asr.w   #2,d0
    26.     sub.w   d0,y_vel(a0)
    27.     neg.w   y_vel(a0)
    This ensures when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.


    And that's it. Save, build and test.


    I don't think I've ever seen anyone do this in their hack. I've just applied to it in my Sonic 2 Recreation hack. I hope to see this in more hacks from now on!


    In case, here is a Sonic 2 Rom, only edited to include the underwater Scattered rings. To see for yourself.


    Cheers,
    redhotsonic
     
  2. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    I would've never even noticed this had you not pointed it out... Good spot. Page worthy of the SCHG, I think.

    Come to think of it... has such a fix been done, or should be done, to Sonic's 1 and 3? I highly doubt this is an isolated incident only occuring in Sonic 2.
     
  3. Aerosol

    Aerosol

    Not here. Moderator
    11,163
    573
    93
    Not where I want to be.
    Sonic (?): Coming summer of 2055...?
    A pet peeve of mine is when people write guides that amount to "paste this here and there". You wrote this in an effort to teach someone how to do it, yes? Then why not explain it a bit better?
     
  4. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    I do agree with that. At the very least, some tags next to the lines of code would suffice, telling us what the code does. Someone like myself who is novice at ASM will look at that and simply copy and paste without knowing what I'm doing or why I'm changing this.
     
  5. redhotsonic

    redhotsonic

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

    Sure, as you wish.


    Also, I had a facepalm moment. I forgot to make them do an extra check to see if the level has water or not. Otherwise, in other levels like EHZ or whatever, the rings may act if their underwater lol. I've fixed this in the first post.

    Cheers
     
  6. Aerosol

    Aerosol

    Not here. Moderator
    11,163
    573
    93
    Not where I want to be.
    Sonic (?): Coming summer of 2055...?
    Thanks for the that, RHS. Now somebody that uses the SVN disasms has a fighting chance to implement this themselves if they wanted to.
     
  7. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Thanks, that would be a nice edition if anyone did want to add it to the SCHG.



    This has never been applied to any Sonic game IIRC. Can't be too sure about Knuckles Chaotix as never played that game.



    You're welcome. It shouldn't be hard at all to apply using a SVN disassembly. Someone from SSRG has ported it into his Sonic 1 hack using my Sonic 2 guide so it can't be hard =P
     
  8. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    Tell you what, I'll get on it in the morning. It's night for me here right now, so wait a few hours. I'll put something together for you. (That is, if someone doesn't beat me to it)

    Any chance you can put together a tutorial for the same thing for Sonic's 1 and 3?
     
  9. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Sure, here is one for Sonic 1. I can'T find a disassembly for S3, but there's one for S3K. So I will include that next, although this requires a little more work, so will post that one later.


    Sonic 1 and Sonic 3 and Knuckles guides are using SVN disassemblies, seeming as that's what most of you use (for some strange reason).

    SONIC 1

    First, In your disassembly, go to "_incObj\25 & 37 Rings.asm"

    Go to "@makerings:" (part of the scattered rings object code) and find this bit of coding:

    Code (ASM):
    1.         bsr.w   CalcSine
    2.         move.w  d4,d2
    3.         lsr.w   #8,d2
    Just underneath, paste this:

    Code (ASM):
    1.         tst.b   ($FFFFF64C).w       ; Does the level have water?
    2.         beq.s   @skiphalvingvel     ; If not, branch and skip underwater checks
    3.         move.w  ($FFFFF646).w,d6    ; Move water level to d6
    4.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.         bgt.s   @skiphalvingvel     ; If not, branch and skip underwater commands
    6.         asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    7.         asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    8. @skiphalvingvel:

    So, you should end up with something looking like this:

    Code (ASM):
    1. @makerings:
    2.         move.b  #id_RingLoss,0(a1) ; load bouncing ring object
    3.         addq.b  #2,obRoutine(a1)
    4.         move.b  #8,obHeight(a1)
    5.         move.b  #8,obWidth(a1)
    6.         move.w  obX(a0),obX(a1)
    7.         move.w  obY(a0),obY(a1)
    8.         move.l  #Map_Ring,obMap(a1)
    9.         move.w  #$27B2,obGfx(a1)
    10.         move.b  #4,obRender(a1)
    11.         move.b  #3,obPriority(a1)
    12.         move.b  #$47,obColType(a1)
    13.         move.b  #8,obActWid(a1)
    14.         move.b  #-1,(v_ani3_time).w
    15.         tst.w   d4
    16.         bmi.s   @loc_9D62
    17.         move.w  d4,d0
    18.         bsr.w   CalcSine
    19.         move.w  d4,d2
    20.         lsr.w   #8,d2
    21.         tst.b   ($FFFFF64C).w       ; Does the level have water?
    22.         beq.s   @skiphalvingvel     ; If not, branch and skip underwater checks
    23.         move.w  ($FFFFF646).w,d6    ; Move water level to d6
    24.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    25.         bgt.s   @skiphalvingvel     ; If not, branch and skip underwater commands
    26.         asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    27.         asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    28. @skiphalvingvel:
    29.         asl.w   d2,d0
    30.         asl.w   d2,d1
    31.         move.w  d0,d2
    32.         move.w  d1,d3
    33.         addi.b  #$10,d4
    34.         bcc.s   @loc_9D62
    35.         subi.w  #$80,d4
    36.         bcc.s   @loc_9D62
    37.         move.w  #$288,d4
    This ensures that when underwater, the rings x_vel and y_vel are halved so they appear to be moving slower.



    Next, go to label "RLoss_Bounce:" and under

    Code (ASM):
    1.         move.b  (v_ani3_frame).w,obFrame(a0)
    2.         bsr.w   SpeedToPos
    3.         addi.w  #$18,obVelY(a0)
    Put this:

    Code (ASM):
    1.         tst.b   ($FFFFF64C).w       ; Does the level have water?
    2.         beq.s   @skipbounceslow     ; If not, branch and skip underwater checks
    3.         move.w  ($FFFFF646).w,d6    ; Move water level to d6
    4.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.         bgt.s   @skipbounceslow     ; If not, branch and skip underwater commands
    6.         subi.w  #$E,obVelY(a0)      ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    7. @skipbounceslow:
    You can change the value of the gravity if you like, but I found $E to suit.


    So, you should have something looking like this:

    Code (ASM):
    1. RLoss_Bounce:   ; Routine 2
    2.         move.b  (v_ani3_frame).w,obFrame(a0)
    3.         bsr.w   SpeedToPos
    4.         addi.w  #$18,obVelY(a0)
    5.         tst.b   ($FFFFF64C).w       ; Does the level have water?
    6.         beq.s   @skipbounceslow     ; If not, branch and skip underwater checks
    7.         move.w  ($FFFFF646).w,d6    ; Move water level to d6
    8.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    9.         bgt.s   @skipbounceslow     ; If not, branch and skip underwater commands
    10.         subi.w  #$E,obVelY(a0)      ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    11. @skipbounceslow:
    12.         bmi.s   @chkdel
    13.         move.b  (v_vbla_byte).w,d0
    14.         add.b   d7,d0
    15.         andi.b  #3,d0
    16.         bne.s   @chkdel
    17.         jsr ObjFloorDist
    18.         tst.w   d1
    19.         bpl.s   @chkdel
    20.         add.w   d1,obY(a0)
    21.         move.w  obVelY(a0),d0
    22.         asr.w   #2,d0
    23.         sub.w   d0,obVelY(a0)
    24.         neg.w   obVelY(a0)
    This ensures when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.
     
  10. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Double post, I thought it'd be better to have a seperate post for this, so on my first post, I can add quick links, so please forgive me.

    Anyway, here is your guide for adding gravity for scattered rings underwater for S3K. Again, SVN disassembly.

    Sonic 3 and Knuckles

    Go to "off_1A658:" (the routines of the scattered rings). You'll see that it's first job is to go to "loc_1A67A". That needs changing to "loc_1A68C".

    So, from this:

    Code (ASM):
    1. off_1A658:  dc.w loc_1A67A-off_1A658
    2.  
    3.         dc.w loc_1A75C-off_1A658
    4.         dc.w loc_1A7C2-off_1A658
    5.         dc.w loc_1A7D6-off_1A658
    6.         dc.w loc_1A7E4-off_1A658
    And replace with this:

    Code (ASM):
    1. off_1A658:  dc.w loc_1A68C-off_1A658
    2.  
    3.         dc.w loc_1A75C-off_1A658
    4.         dc.w loc_1A7C2-off_1A658
    5.         dc.w loc_1A7D6-off_1A658
    6.         dc.w loc_1A7E4-off_1A658
    This will skip "loc_1A67A" commands. This is because this location pushes the scattered rings object (or the reverse scattered rings object) to d6. For our water code, we need d6, because all other data registers are being used. It doesn't do this in Sonic 1 or 2 because there's no such thing as "reverse gravity". The scattered rings object needs to be moved to a1, but we can't do it here, because shortly after, a1 is being used for the amount of rings.

    Next, go to "off_1A670:" This is extremely similar to what we just done, but for reverse gravity. so no point explaining what it's doing here as I just did that. Anyway, you should see:

    Code (ASM):
    1. off_1A670:  dc.w loc_1A67A-off_1A670
    2.  
    3.         dc.w loc_1A7E8-off_1A670
    4.         dc.w loc_1A7C2-off_1A670
    5.         dc.w loc_1A7D6-off_1A670
    6.         dc.w loc_1A7E4-off_1A670
    And replace with:

    Code (ASM):
    1. off_1A670:  dc.w loc_1A68C-off_1A670
    2.  
    3.         dc.w loc_1A7E8-off_1A670
    4.         dc.w loc_1A7C2-off_1A670
    5.         dc.w loc_1A7D6-off_1A670
    6.         dc.w loc_1A7E4-off_1A670
    Again, this will skip "loc_1A67A" commands. Explained why above.

    Next, go to "loc_1A67A:" and you should see this.

    Code (ASM):
    1. loc_1A67A:
    2.  
    3.         move.l  #Obj_Bouncing_Ring,d6
    4.         tst.b   (Reverse_gravity_flag).w
    5.         beq.s   loc_1A68C
    6.         move.l  #Obj_Bouncing_Ring_Reverse_Gravity,d6
    Notice "Bouncing_ring" (and the reverse one) are being pushed to d6. We need d6, so, delete it. It's no longer needed. Trust me. We have now free'd d6. Although we've lost pushing the scattered rings into place. Do not worry, that's next.


    Next, go to "loc_1A6B6:". The very first command should be "addq.b #2,5(a1)" Just before that, add this:

    Code (ASM):
    1.         move.l  #Obj_Bouncing_Ring,(a1)
    2.         tst.b   (Reverse_gravity_flag).w
    3.         beq.s   loc_1A6B6CONTINUE
    4.         move.l  #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
    5. loc_1A6B6CONTINUE:
    Yes, you might recognise this. It's part of that code you just this second deleted. We're pushing the scattered rings back into place. But instead of putting it to d6, we're putting it to a1. a1 is now available as it's not being used again for a while.

    So you have something looking at this:

    Code (ASM):
    1. loc_1A6B6:
    2.         move.l  #Obj_Bouncing_Ring,(a1)
    3.         tst.b   (Reverse_gravity_flag).w
    4.         beq.s   loc_1A6B6CONTINUE
    5.         move.l  #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
    6. loc_1A6B6CONTINUE:
    7.         addq.b  #2,5(a1)
    8.         move.b  #8,$1E(a1)
    9.         move.b  #8,$1F(a1)
    10.         move.w  $10(a0),$10(a1)
    11.         move.w  $14(a0),$14(a1)
    12.         move.l  #Map_Ring,$C(a1)
    13.         move.w  #$A6BC,$A(a1)
    14.         move.b  #$84,4(a1)
    15.         move.w  #$180,8(a1)
    16.         move.b  #$47,$28(a1)
    17.         move.b  #8,7(a1)
    18.         move.b  #-1,(Ring_spill_anim_counter).w
    19.         tst.w   d4
    20.         bmi.s   loc_1A728
    21.         move.w  d4,d0
    22.         jsr (GetSineCosine).l
    23.         move.w  d4,d2
    24.         lsr.w   #8,d2
    25.         asl.w   d2,d0
    26.         asl.w   d2,d1
    27.         move.w  d0,d2
    28.         move.w  d1,d3
    29.         addi.b  #$10,d4
    30.         bcc.s   loc_1A728
    31.         subi.w  #$80,d4
    32.         bcc.s   loc_1A728
    33.         move.w  #$288,d4

    Still looking at "loc_1A6B6:" look and find this bit of coding:

    Code (ASM):
    1.         jsr (GetSineCosine).l
    2.         move.w  d4,d2
    3.         lsr.w   #8,d2
    Just underneath, paste this:

    Code (ASM):
    1.         tst.b   (Water_flag).w      ; Does the level have water?
    2.         beq.s   skiphalvingvel      ; If not, branch and skip underwater checks
    3.         move.w  (Water_level).w,d6  ; Move water level to d6
    4.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.         bgt.s   skiphalvingvel      ; If not, branch and skip underwater commands
    6.         asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    7.         asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    8. skiphalvingvel:

    So, you should end up with something looking like this:

    Code (ASM):
    1. loc_1A6B6:
    2.         move.l  #Obj_Bouncing_Ring,(a1)
    3.         tst.b   (Reverse_gravity_flag).w
    4.         beq.s   loc_1A6B6CONTINUE
    5.         move.l  #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
    6. loc_1A6B6CONTINUE:
    7.         addq.b  #2,5(a1)
    8.         move.b  #8,$1E(a1)
    9.         move.b  #8,$1F(a1)
    10.         move.w  $10(a0),$10(a1)
    11.         move.w  $14(a0),$14(a1)
    12.         move.l  #Map_Ring,$C(a1)
    13.         move.w  #$A6BC,$A(a1)
    14.         move.b  #$84,4(a1)
    15.         move.w  #$180,8(a1)
    16.         move.b  #$47,$28(a1)
    17.         move.b  #8,7(a1)
    18.         move.b  #-1,(Ring_spill_anim_counter).w
    19.         tst.w   d4
    20.         bmi.s   loc_1A728
    21.         move.w  d4,d0
    22.         jsr (GetSineCosine).l
    23.         move.w  d4,d2
    24.         lsr.w   #8,d2
    25.         tst.b   (Water_flag).w      ; Does the level have water?
    26.         beq.s   skiphalvingvel      ; If not, branch and skip underwater checks
    27.         move.w  (Water_level).w,d6  ; Move water level to d6
    28.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    29.         bgt.s   skiphalvingvel      ; If not, branch and skip underwater commands
    30.         asr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    31.         asr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    32. skiphalvingvel:
    33.         asl.w   d2,d0
    34.         asl.w   d2,d1
    35.         move.w  d0,d2
    36.         move.w  d1,d3
    37.         addi.b  #$10,d4
    38.         bcc.s   loc_1A728
    39.         subi.w  #$80,d4
    40.         bcc.s   loc_1A728
    41.         move.w  #$288,d4
    This ensures that when underwater, the rings x_vel and y_vel are halved so they appear to be moving slower.



    Next, go to label "loc_1A75C:" and under

    Code (ASM):
    1.         move.b  (Ring_spill_anim_frame).w,$22(a0)
    2.         bsr.w   MoveSprite2
    3.         addi.w  #$18,$1A(a0)
    Put this:

    Code (ASM):
    1.         tst.b   (Water_flag).w      ; Does the level have water?
    2.         beq.s   skiphalvinggrav     ; If not, branch and skip underwater checks
    3.         move.w  (Water_level).w,d6  ; Move water level to d6
    4.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.         bgt.s   skiphalvinggrav     ; If not, branch and skip underwater commands
    6.         subi.w  #$E,$1A(a0)     ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    7. skiphalvinggrav:
    You can change the value of the gravity if you like, but I found $E to suit.


    So, you should have something looking like this:

    Code (ASM):
    1. loc_1A75C:
    2.         move.b  (Ring_spill_anim_frame).w,$22(a0)
    3.         bsr.w   MoveSprite2
    4.         addi.w  #$18,$1A(a0)
    5.         tst.b   (Water_flag).w      ; Does the level have water?
    6.         beq.s   skiphalvinggrav     ; If not, branch and skip underwater checks
    7.         move.w  (Water_level).w,d6  ; Move water level to d6
    8.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    9.         bgt.s   skiphalvinggrav     ; If not, branch and skip underwater commands
    10.         subi.w  #$E,$1A(a0)     ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    11. skiphalvinggrav:
    12.         bmi.s   loc_1A7B0
    13.         move.b  (V_int_run_count+3).w,d0
    14.         add.b   d7,d0
    15.         andi.b  #7,d0
    16.         bne.s   loc_1A7B0
    17.         tst.b   4(a0)
    18.         bpl.s   loc_1A79C
    19.         jsr (sub_F994).l
    20.         tst.w   d1
    21.         bpl.s   loc_1A79C
    22.         add.w   d1,$14(a0)
    23.         move.w  $1A(a0),d0
    24.         asr.w   #2,d0
    25.         sub.w   d0,$1A(a0)
    26.         neg.w   $1A(a0)
    This ensures when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.


    This last bit is optional. You only need to do this if you're planning to have reverse gravity underwater. You'd be a bit mental if you do have this, but you never know =P

    Go to label "loc_1A7E8:" and under

    Code (ASM):
    1.         move.b  (Ring_spill_anim_frame).w,$22(a0)
    2.         bsr.w   MoveSprite_TestGravity2
    3.         addi.w  #$18,$1A(a0)
    Put this:

    Code (ASM):
    1.         tst.b   (Water_flag).w      ; Does the level have water?
    2.         beq.s   skiphalvingrevgrav      ; If not, branch and skip underwater checks
    3.         move.w  (Water_level).w,d6  ; Move water level to d6
    4.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    5.         bgt.s   skiphalvingrevgrav      ; If not, branch and skip underwater commands
    6.         subi.w  #$E,$1A(a0)     ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    7. skiphalvingrevgrav:
    Again, you can change the value of the reverse gravity if you like.


    So, you should have something looking like this:

    Code (ASM):
    1. loc_1A7E8:
    2.  
    3.         move.b  (Ring_spill_anim_frame).w,$22(a0)
    4.         bsr.w   MoveSprite_TestGravity2
    5.         addi.w  #$18,$1A(a0)
    6.         tst.b   (Water_flag).w      ; Does the level have water?
    7.         beq.s   skiphalvingrevgrav  ; If not, branch and skip underwater checks
    8.         move.w  (Water_level).w,d6  ; Move water level to d6
    9.         cmp.w   y_pos(a0),d6        ; Is the ring object underneath the water level?
    10.         bgt.s   skiphalvingrevgrav  ; If not, branch and skip underwater commands
    11.         subi.w  #$E,$1A(a0)     ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
    12. skiphalvingrevgrav:
    13.         bmi.s   loc_1A83C
    14.         move.b  (V_int_run_count+3).w,d0
    15.         add.b   d7,d0
    16.         andi.b  #7,d0
    17.         bne.s   loc_1A83C
    18.         tst.b   4(a0)
    19.         bpl.s   loc_1A828
    20.         jsr (sub_FCA0).l
    21.         tst.w   d1
    22.         bpl.s   loc_1A828
    23.         sub.w   d1,$14(a0)
    24.         move.w  $1A(a0),d0
    25.         asr.w   #2,d0
    26.         sub.w   d0,$1A(a0)
    27.         neg.w   $1A(a0)
    This ensures when underwater, the gravity is not as great when it's in reverse gravity mode.

    That should be it =)




    Now, with all this and my ASM guide I did years ago and my contributions to the SCHG, where's my tech status already? =P (joke)
     
  11. 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)
    I really can't emphasize enough that you should use lsr/asr instead of divu/divs whenever you are dividing by a power of 2. Meaning you really, really should change all instances of
    Code (Text):
    1. divu.w  #$2,d*
    by
    Code (Text):
    1. lsr.w  #$1,d*
    divu is almost 20 times slower than lsr in the particular case of division by 2.
     
  12. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    20x slower? Bloody hell. That's very slow, also, as this code has got to repeat itself for each ring you lose, that must make it extremely slower. Thanks for the tip =P

    I've applied it to all three guides.


    EDIT:

    I've now applied it to all 3 guides.

    If you have used these for your hack, please change:

    Code (ASM):
    1.     divu.w  #$2,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    2.     divu.w  #$2,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
    to this:

    Code (ASM):
    1.     lsr.w   #$1,d0          ; Half d0.  Makes the ring's x_vel bounce to the left/right slower
    2.     lsr.w   #$1,d1          ; Half d1.  Makes the ring's y_vel bounce up/down slower
     
  13. 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)
    Now that I looked more closely at the code, I think it should also be asr instead or lsr (just as it should have been divs instead of divu).
     
  14. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    LOO Good thing I haven't done anything yet. I'll wait til this gets sorted out...
     
  15. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I'm not at home at the moment so I can't test it out, but what will be the difference? To me, once all bits have shifted to the right, the new bit introduced may be a 1 instead of a 0 (depends if it's a negative value).
     
  16. ICEknight

    ICEknight

    Researcher Researcher
    This is very interesting, I can't believe I didn't remember the rings having the wrong gravity when underwater. Good work fixing them!
    They ended up not adding water to any level, so no need to check.


    Which makes me wonder if there could be any remnants (not counting graphics) of water implementation in the game...
     
  17. vladikcomper

    vladikcomper

    Tech Member
    205
    134
    43
    Sonic Warped
    ASR shifts arithmetically, which means -4 will become -2 after shifting.
    %1111111111111100 -> %1111111111111110

    LSR shifts logically ignoring source data's sign, so -4 will eventually become 32766!
    %1111111111111100 -> %0111111111111110

    If you're calculating signed numbers, there will be a huge bug with it.
    However, if you were dealing with shifting left (in case you wanted to multiply something by power of 2), there would be no difference between ASL and LSL, expect for ASL would set Overflow bit if sign bit was changed after operation.
     
  18. redhotsonic

    redhotsonic

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

    I see. I have tried it and have noticed a slight difference. With lsr, some rings were in the same place as another (one directly behind another), and ASR seems to fix this. I will apply this to the guide.
     
  19. RetroKoH

    RetroKoH

    Member
    1,662
    22
    18
    Project Sonic 8x16
    http://info.sonicret...erwater_Physics
    Here you go. I just copied and pasted from the OP. Slapped headers on the thing, and added the page to the How-To guide, categories, and the template at the bottom.
    If anyone knows how to put in a contents table, please do it, cuz it could use one. I just figured it would be fine on one page... seeing as how this is essentially the same guide for all three games, for the most part.
    EDIT: Why the fuck does my Wiki Edits stay at 1??? I have certainly made way more than one... both major and minor. :argh:
     
  20. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Thanks for doing that, mate. I hope it comes useful for everyone!