Difference between revisions of "Fix Scattered Rings Underwater Physics"
From Sonic Retro
(Removed Sonic 2 SVN workaround and directly fixed problem. Replaced spaces in code with tabs. Overall cleanup.) |
m (Text replacement - "\[\[Category:SCHG How-tos.*" to "") |
||
(7 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
− | ''(Original guide for all 3 games by [[redhotsonic]])'' | + | ''(Original guide for all 3 games by [[User:Redhotsonic|redhotsonic]])'' |
Quote from ''redhotsonic'', - "Ah, the scattered rings when you get hurt. It can cause slowdown to your game, and even mess up the underwater 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?" | Quote from ''redhotsonic'', - "Ah, the scattered rings when you get hurt. It can cause slowdown to your game, and even mess up the underwater 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?" | ||
Line 5: | Line 5: | ||
This is something that occurs in all 3 Sonic the Hedgehog Mega Drive games (and by 3, that IS counting S3&K as one game, though S&K has no water anyway, so it wouldn't be included regardless... but I digress). But is it really a bug, or is it merely a design choice? In either case, it's something that could stand to be fixed, and this guide tells you how to fix the ring physics in all of the games. First off... let's start with the original: | This is something that occurs in all 3 Sonic the Hedgehog Mega Drive games (and by 3, that IS counting S3&K as one game, though S&K has no water anyway, so it wouldn't be included regardless... but I digress). But is it really a bug, or is it merely a design choice? In either case, it's something that could stand to be fixed, and this guide tells you how to fix the ring physics in all of the games. First off... let's start with the original: | ||
+ | ==Sonic 1 HiveBrain fix== | ||
+ | ''(Addition by [[User:Luigi Hero|Luigi Hero]])'' | ||
− | == | + | First, in your disassembly, go to "'''''Obj37_MakeRings:'''''" and find this bit of coding: |
− | ''This | + | <syntaxhighlight lang="asm"> |
+ | bsr.w CalcSine | ||
+ | move.w d4,d2 | ||
+ | lsr.w #8,d2 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | Just underneath, paste this: | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | tst.b ($FFFFF64C).w ; Does the level have water? | ||
+ | beq.s @skiphalvingvel ; If not, branch and skip underwater checks | ||
+ | move.w ($FFFFF646).w,d6 ; Move water level to d6 | ||
+ | cmp.w $C(a0),d6 ; Is the ring object underneath the water level? | ||
+ | bgt.s @skiphalvingvel ; If not, branch and skip underwater commands | ||
+ | asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower | ||
+ | asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | ||
+ | |||
+ | @skiphalvingvel: | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | You should end up with something looking like this: | ||
+ | <syntaxhighlight lang="asm">Obj37_MakeRings: ; XREF: Obj37_CountRings | ||
+ | move.b #$37,0(a1) ; load bouncing ring object | ||
+ | addq.b #2,$24(a1) | ||
+ | move.b #8,$16(a1) | ||
+ | move.b #8,$17(a1) | ||
+ | move.w 8(a0),8(a1) | ||
+ | move.w $C(a0),$C(a1) | ||
+ | move.l #Map_obj25,4(a1) | ||
+ | move.w #$27B2,2(a1) | ||
+ | move.b #4,1(a1) | ||
+ | move.b #3,$18(a1) | ||
+ | move.b #$47,$20(a1) | ||
+ | move.b #8,$19(a1) | ||
+ | move.b #-1,($FFFFFEC6).w | ||
+ | tst.w d4 | ||
+ | bmi.s loc_9D62 | ||
+ | move.w d4,d0 | ||
+ | bsr.w CalcSine | ||
+ | move.w d4,d2 | ||
+ | lsr.w #8,d2 | ||
+ | tst.b ($FFFFF64C).w ; Does the level have water? | ||
+ | beq.s @skiphalvingvel ; If not, branch and skip underwater checks | ||
+ | move.w ($FFFFF646).w,d6 ; Move water level to d6 | ||
+ | cmp.w $C(a0),d6 ; Is the ring object underneath the water level? | ||
+ | bgt.s @skiphalvingvel ; If not, branch and skip underwater commands | ||
+ | asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower | ||
+ | asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | ||
+ | |||
+ | @skiphalvingvel: | ||
+ | asl.w d2,d0 | ||
+ | asl.w d2,d1 | ||
+ | move.w d0,d2 | ||
+ | move.w d1,d3 | ||
+ | addi.b #$10,d4 | ||
+ | bcc.s loc_9D62 | ||
+ | subi.w #$80,d4 | ||
+ | bcc.s loc_9D62 | ||
+ | move.w #$288,d4 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | 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 "''Obj37_Bounce:''" and under this... | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | move.b ($FFFFFEC7).w,$1A(a0) | ||
+ | bsr.w SpeedToPos | ||
+ | addi.w #$18,$12(a0) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ...place this: | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | tst.b ($FFFFF64C).w ; Does the level have water? | ||
+ | beq.s @skipbounceslow ; If not, branch and skip underwater checks | ||
+ | move.w ($FFFFF646).w,d6 ; Move water level to d6 | ||
+ | cmp.w $C(a0),d6 ; Is the ring object underneath the water level? | ||
+ | bgt.s @skipbounceslow ; If not, branch and skip underwater commands | ||
+ | subi.w #$E,$12(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | ||
+ | |||
+ | @skipbounceslow: | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | You can change the value of the gravity if you like, but I found $E to suit. | ||
+ | Anyway, you should have something looking like this: | ||
+ | <syntaxhighlight lang="asm"> | ||
+ | Obj37_Bounce: ; XREF: Obj37_Index | ||
+ | move.b ($FFFFFEC7).w,$1A(a0) | ||
+ | bsr.w SpeedToPos | ||
+ | addi.w #$18,$12(a0) | ||
+ | tst.b ($FFFFF64C).w ; Does the level have water? | ||
+ | beq.s @skipbounceslow ; If not, branch and skip underwater checks | ||
+ | move.w ($FFFFF646).w,d6 ; Move water level to d6 | ||
+ | cmp.w $C(a0),d6 ; Is the ring object underneath the water level? | ||
+ | bgt.s @skipbounceslow ; If not, branch and skip underwater commands | ||
+ | subi.w #$E,$12(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | ||
+ | |||
+ | @skipbounceslow: | ||
+ | bmi.s Obj37_ChkDel | ||
+ | move.b ($FFFFFE0F).w,d0 | ||
+ | add.b d7,d0 | ||
+ | andi.b #3,d0 | ||
+ | bne.s Obj37_ChkDel | ||
+ | jsr ObjHitFloor | ||
+ | tst.w d1 | ||
+ | bpl.s Obj37_ChkDel | ||
+ | add.w d1,$C(a0) | ||
+ | move.w $12(a0),d0 | ||
+ | asr.w #2,d0 | ||
+ | sub.w d0,$12(a0) | ||
+ | neg.w $12(a0) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | This ensures that, when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect. | ||
+ | |||
+ | ==Sonic 1 Git fix== | ||
First, in your disassembly, go to "'''''_incObj\25 & 37 Rings.asm'''''" | 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: | Go to ''@makerings:'' (part of the scattered rings object code) and find this bit of coding: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
bsr.w CalcSine | bsr.w CalcSine | ||
move.w d4,d2 | move.w d4,d2 | ||
lsr.w #8,d2 | lsr.w #8,d2 | ||
− | </ | + | </syntaxhighlight> |
Just underneath, paste this: | Just underneath, paste this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b ($FFFFF64C).w ; Does the level have water? | tst.b ($FFFFF64C).w ; Does the level have water? | ||
beq.s @skiphalvingvel ; If not, branch and skip underwater checks | beq.s @skiphalvingvel ; If not, branch and skip underwater checks | ||
move.w ($FFFFF646).w,d6 ; Move water level to d6 | move.w ($FFFFF646).w,d6 ; Move water level to d6 | ||
− | cmp.w | + | cmp.w $C(a0),d6 ; Is the ring object underneath the water level? |
bgt.s @skiphalvingvel ; If not, branch and skip underwater commands | bgt.s @skiphalvingvel ; If not, branch and skip underwater commands | ||
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower | asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower | ||
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | ||
+ | |||
@skiphalvingvel: | @skiphalvingvel: | ||
− | </ | + | </syntaxhighlight> |
You should end up with something looking like this: | You should end up with something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm">@makerings: |
− | @makerings: | ||
move.b #id_RingLoss,0(a1) ; load bouncing ring object | move.b #id_RingLoss,0(a1) ; load bouncing ring object | ||
addq.b #2,obRoutine(a1) | addq.b #2,obRoutine(a1) | ||
Line 70: | Line 191: | ||
bcc.s @loc_9D62 | bcc.s @loc_9D62 | ||
move.w #$288,d4 | move.w #$288,d4 | ||
− | </ | + | </syntaxhighlight> |
Line 76: | Line 197: | ||
Next, go to label "''RLoss_Bounce:''" and under this... | Next, go to label "''RLoss_Bounce:''" and under this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.b (v_ani3_frame).w,obFrame(a0) | move.b (v_ani3_frame).w,obFrame(a0) | ||
bsr.w SpeedToPos | bsr.w SpeedToPos | ||
addi.w #$18,obVelY(a0) | addi.w #$18,obVelY(a0) | ||
− | </ | + | </syntaxhighlight> |
...place this: | ...place this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b ($FFFFF64C).w ; Does the level have water? | tst.b ($FFFFF64C).w ; Does the level have water? | ||
beq.s @skipbounceslow ; If not, branch and skip underwater checks | beq.s @skipbounceslow ; If not, branch and skip underwater checks | ||
Line 91: | Line 212: | ||
bgt.s @skipbounceslow ; If not, branch and skip underwater commands | bgt.s @skipbounceslow ; If not, branch and skip underwater commands | ||
subi.w #$E,obVelY(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | subi.w #$E,obVelY(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | ||
+ | |||
@skipbounceslow: | @skipbounceslow: | ||
− | </ | + | </syntaxhighlight> |
You can change the value of the gravity if you like, but I found $E to suit. | You can change the value of the gravity if you like, but I found $E to suit. | ||
Anyway, you should have something looking like this: | Anyway, you should have something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
RLoss_Bounce: ; Routine 2 | RLoss_Bounce: ; Routine 2 | ||
move.b (v_ani3_frame).w,obFrame(a0) | move.b (v_ani3_frame).w,obFrame(a0) | ||
Line 122: | Line 244: | ||
sub.w d0,obVelY(a0) | sub.w d0,obVelY(a0) | ||
neg.w obVelY(a0) | neg.w obVelY(a0) | ||
− | </ | + | </syntaxhighlight> |
Line 131: | Line 253: | ||
First, go to "''loc_120BA:''" (part of the scattered rings object code. Git users, ''Obj37_Init'', three '+'s down) and find this bit of coding: | First, go to "''loc_120BA:''" (part of the scattered rings object code. Git users, ''Obj37_Init'', three '+'s down) and find this bit of coding: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
bsr.w JmpTo4_CalcSine | bsr.w JmpTo4_CalcSine | ||
move.w d4,d2 | move.w d4,d2 | ||
lsr.w #8,d2 | lsr.w #8,d2 | ||
− | </ | + | </syntaxhighlight> |
Just underneath, paste this: | Just underneath, paste this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b (Water_flag).w ; Does the level have water? | tst.b (Water_flag).w ; Does the level have water? | ||
beq.s .skiphalvingvel ; If not, branch and skip underwater checks | beq.s .skiphalvingvel ; If not, branch and skip underwater checks | ||
Line 148: | Line 270: | ||
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | ||
.skiphalvingvel: | .skiphalvingvel: | ||
− | </ | + | </syntaxhighlight> |
So, you should end up with something looking like this: | So, you should end up with something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_120BA: | loc_120BA: | ||
_move.b #$37,0(a1) ; load obj37 | _move.b #$37,0(a1) ; load obj37 | ||
Line 191: | Line 313: | ||
bcc.s loc_12132 | bcc.s loc_12132 | ||
move.w #$288,d4 | move.w #$288,d4 | ||
− | </ | + | </syntaxhighlight> |
Line 198: | Line 320: | ||
Next, go to label "''Obj_37_sub_2:''" and under this... | Next, go to label "''Obj_37_sub_2:''" and under this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.b (Ring_spill_anim_frame).w,mapping_frame(a0) | move.b (Ring_spill_anim_frame).w,mapping_frame(a0) | ||
bsr.w ObjectMove | bsr.w ObjectMove | ||
addi.w #$18,y_vel(a0) | addi.w #$18,y_vel(a0) | ||
− | </ | + | </syntaxhighlight> |
...put this: | ...put this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b (Water_flag).w ; Does the level have water? | tst.b (Water_flag).w ; Does the level have water? | ||
beq.s .skipbounceslow ; If not, branch and skip underwater checks | beq.s .skipbounceslow ; If not, branch and skip underwater checks | ||
Line 214: | Line 336: | ||
subi.w #$E,y_vel(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings | subi.w #$E,y_vel(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings | ||
.skipbounceslow: | .skipbounceslow: | ||
− | </ | + | </syntaxhighlight> |
You can change the value of the gravity if you like, but I found $E to suit. | You can change the value of the gravity if you like, but I found $E to suit. | ||
Anyway, you should have something looking like this: | Anyway, you should have something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
Obj_37_sub_2: | Obj_37_sub_2: | ||
move.b (Ring_spill_anim_frame).w,mapping_frame(a0) | move.b (Ring_spill_anim_frame).w,mapping_frame(a0) | ||
Line 246: | Line 368: | ||
sub.w d0,y_vel(a0) | sub.w d0,y_vel(a0) | ||
neg.w y_vel(a0) | neg.w y_vel(a0) | ||
− | </ | + | </syntaxhighlight> |
Line 256: | Line 378: | ||
Go to "''off_1A658:''" (the routines of the scattered rings). You'll see that its first job is to go to "''loc_1A67A''". That needs changing to "''loc_1A68C''". | Go to "''off_1A658:''" (the routines of the scattered rings). You'll see that its first job is to go to "''loc_1A67A''". That needs changing to "''loc_1A68C''". | ||
So, find this... | So, find this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
off_1A658: dc.w loc_1A67A-off_1A658 | off_1A658: dc.w loc_1A67A-off_1A658 | ||
Line 263: | Line 385: | ||
dc.w loc_1A7D6-off_1A658 | dc.w loc_1A7D6-off_1A658 | ||
dc.w loc_1A7E4-off_1A658 | dc.w loc_1A7E4-off_1A658 | ||
− | </ | + | </syntaxhighlight> |
...and replace it with this: | ...and replace it with this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
off_1A658: dc.w loc_1A68C-off_1A658 | off_1A658: dc.w loc_1A68C-off_1A658 | ||
Line 274: | Line 396: | ||
dc.w loc_1A7D6-off_1A658 | dc.w loc_1A7D6-off_1A658 | ||
dc.w loc_1A7E4-off_1A658 | dc.w loc_1A7E4-off_1A658 | ||
− | </ | + | </syntaxhighlight> |
Line 280: | Line 402: | ||
Next, go to "''off_1A670:''" This is extremely similar to what we just done, but for reverse gravity, so there's no point explaining what it's doing here as I just did that. Anyway, you should see this... | Next, go to "''off_1A670:''" This is extremely similar to what we just done, but for reverse gravity, so there's no point explaining what it's doing here as I just did that. Anyway, you should see this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
off_1A670: dc.w loc_1A67A-off_1A670 | off_1A670: dc.w loc_1A67A-off_1A670 | ||
Line 287: | Line 409: | ||
dc.w loc_1A7D6-off_1A670 | dc.w loc_1A7D6-off_1A670 | ||
dc.w loc_1A7E4-off_1A670 | dc.w loc_1A7E4-off_1A670 | ||
− | </ | + | </syntaxhighlight> |
...replace it with: | ...replace it with: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
off_1A670: dc.w loc_1A68C-off_1A670 | off_1A670: dc.w loc_1A68C-off_1A670 | ||
Line 298: | Line 420: | ||
dc.w loc_1A7D6-off_1A670 | dc.w loc_1A7D6-off_1A670 | ||
dc.w loc_1A7E4-off_1A670 | dc.w loc_1A7E4-off_1A670 | ||
− | </ | + | </syntaxhighlight> |
Line 304: | Line 426: | ||
Next, go to "''loc_1A67A:''" and you should see this: | Next, go to "''loc_1A67A:''" and you should see this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_1A67A: | loc_1A67A: | ||
Line 311: | Line 433: | ||
beq.s loc_1A68C | beq.s loc_1A68C | ||
move.l #Obj_Bouncing_Ring_Reverse_Gravity,d6 | move.l #Obj_Bouncing_Ring_Reverse_Gravity,d6 | ||
− | </ | + | </syntaxhighlight> |
Line 318: | Line 440: | ||
Next, go to "''loc_1A6B6:''". The very first command should be "addq.b #2,5(a1)" Just before that, add this: | Next, go to "''loc_1A6B6:''". The very first command should be "addq.b #2,5(a1)" Just before that, add this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.l #Obj_Bouncing_Ring,(a1) | move.l #Obj_Bouncing_Ring,(a1) | ||
tst.b (Reverse_gravity_flag).w | tst.b (Reverse_gravity_flag).w | ||
Line 324: | Line 446: | ||
move.l #Obj_Bouncing_Ring_Reverse_Gravity,(a1) | move.l #Obj_Bouncing_Ring_Reverse_Gravity,(a1) | ||
.notreverse: | .notreverse: | ||
− | </ | + | </syntaxhighlight> |
Line 330: | Line 452: | ||
So you have something looking at this: | So you have something looking at this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_1A6B6: | loc_1A6B6: | ||
move.l #Obj_Bouncing_Ring,(a1) | move.l #Obj_Bouncing_Ring,(a1) | ||
Line 364: | Line 486: | ||
bcc.s loc_1A728 | bcc.s loc_1A728 | ||
move.w #$288,d4 | move.w #$288,d4 | ||
− | </ | + | </syntaxhighlight> |
Still looking at "''loc_1A6B6:''", look and find this bit of coding: | Still looking at "''loc_1A6B6:''", look and find this bit of coding: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
jsr (GetSineCosine).l | jsr (GetSineCosine).l | ||
move.w d4,d2 | move.w d4,d2 | ||
lsr.w #8,d2 | lsr.w #8,d2 | ||
− | </ | + | </syntaxhighlight> |
Just underneath, paste this: | Just underneath, paste this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b (Water_flag).w ; Does the level have water? | tst.b (Water_flag).w ; Does the level have water? | ||
beq.s .skiphalvingvel ; If not, branch and skip underwater checks | beq.s .skiphalvingvel ; If not, branch and skip underwater checks | ||
Line 385: | Line 507: | ||
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower | ||
.skiphalvingvel: | .skiphalvingvel: | ||
− | </ | + | </syntaxhighlight> |
So, you should end up with something looking like this: | So, you should end up with something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_1A6B6: | loc_1A6B6: | ||
move.l #Obj_Bouncing_Ring,(a1) | move.l #Obj_Bouncing_Ring,(a1) | ||
Line 431: | Line 553: | ||
bcc.s loc_1A728 | bcc.s loc_1A728 | ||
move.w #$288,d4 | move.w #$288,d4 | ||
− | </ | + | </syntaxhighlight> |
Line 438: | Line 560: | ||
Next, go to label "''loc_1A75C:''" and under this... | Next, go to label "''loc_1A75C:''" and under this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.b (Ring_spill_anim_frame).w,$22(a0) | move.b (Ring_spill_anim_frame).w,$22(a0) | ||
bsr.w MoveSprite2 | bsr.w MoveSprite2 | ||
addi.w #$18,$1A(a0) | addi.w #$18,$1A(a0) | ||
− | </ | + | </syntaxhighlight> |
...put this: | ...put this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b (Water_flag).w ; Does the level have water? | tst.b (Water_flag).w ; Does the level have water? | ||
beq.s .skiphalvinggrav ; If not, branch and skip underwater checks | beq.s .skiphalvinggrav ; If not, branch and skip underwater checks | ||
Line 454: | Line 576: | ||
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | ||
.skiphalvinggrav: | .skiphalvinggrav: | ||
− | </ | + | </syntaxhighlight> |
You can change the value of the gravity if you like, but I found $E to suit. | You can change the value of the gravity if you like, but I found $E to suit. | ||
Anyway, you should have something looking like this: | Anyway, you should have something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_1A75C: | loc_1A75C: | ||
move.b (Ring_spill_anim_frame).w,$22(a0) | move.b (Ring_spill_anim_frame).w,$22(a0) | ||
Line 486: | Line 608: | ||
sub.w d0,$1A(a0) | sub.w d0,$1A(a0) | ||
neg.w $1A(a0) | neg.w $1A(a0) | ||
− | </ | + | </syntaxhighlight> |
Line 495: | Line 617: | ||
Go to label "''loc_1A7E8:''" and under this... | Go to label "''loc_1A7E8:''" and under this... | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
move.b (Ring_spill_anim_frame).w,$22(a0) | move.b (Ring_spill_anim_frame).w,$22(a0) | ||
bsr.w MoveSprite_TestGravity2 | bsr.w MoveSprite_TestGravity2 | ||
addi.w #$18,$1A(a0) | addi.w #$18,$1A(a0) | ||
− | </ | + | </syntaxhighlight> |
...put this: | ...put this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
tst.b (Water_flag).w ; Does the level have water? | tst.b (Water_flag).w ; Does the level have water? | ||
beq.s .skiphalvingrevgrav ; If not, branch and skip underwater checks | beq.s .skiphalvingrevgrav ; If not, branch and skip underwater checks | ||
Line 511: | Line 633: | ||
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect | ||
.skiphalvingrevgrav: | .skiphalvingrevgrav: | ||
− | </ | + | </syntaxhighlight> |
Again, you can change the value of the reverse gravity if you like. | Again, you can change the value of the reverse gravity if you like. | ||
So, you should have something looking like this: | So, you should have something looking like this: | ||
− | <asm> | + | <syntaxhighlight lang="asm"> |
loc_1A7E8: | loc_1A7E8: | ||
Line 544: | Line 666: | ||
sub.w d0,$1A(a0) | sub.w d0,$1A(a0) | ||
neg.w $1A(a0) | neg.w $1A(a0) | ||
− | </ | + | </syntaxhighlight> |
Line 553: | Line 675: | ||
{{S1Howtos}} | {{S1Howtos}} | ||
{{S2Howtos}} | {{S2Howtos}} | ||
− | + | {{S3KHowtos}} | |
+ | |Fix Scattered Rings Underwater Physics]] |
Latest revision as of 11:10, 25 August 2018
(Original guide for all 3 games by redhotsonic)
Quote from redhotsonic, - "Ah, the scattered rings when you get hurt. It can cause slowdown to your game, and even mess up the underwater 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?"
This is something that occurs in all 3 Sonic the Hedgehog Mega Drive games (and by 3, that IS counting S3&K as one game, though S&K has no water anyway, so it wouldn't be included regardless... but I digress). But is it really a bug, or is it merely a design choice? In either case, it's something that could stand to be fixed, and this guide tells you how to fix the ring physics in all of the games. First off... let's start with the original:
Sonic 1 HiveBrain fix
(Addition by Luigi Hero)
First, in your disassembly, go to "Obj37_MakeRings:" and find this bit of coding:
bsr.w CalcSine
move.w d4,d2
lsr.w #8,d2
Just underneath, paste this:
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skiphalvingvel ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w $C(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
@skiphalvingvel:
You should end up with something looking like this:
Obj37_MakeRings: ; XREF: Obj37_CountRings
move.b #$37,0(a1) ; load bouncing ring object
addq.b #2,$24(a1)
move.b #8,$16(a1)
move.b #8,$17(a1)
move.w 8(a0),8(a1)
move.w $C(a0),$C(a1)
move.l #Map_obj25,4(a1)
move.w #$27B2,2(a1)
move.b #4,1(a1)
move.b #3,$18(a1)
move.b #$47,$20(a1)
move.b #8,$19(a1)
move.b #-1,($FFFFFEC6).w
tst.w d4
bmi.s loc_9D62
move.w d4,d0
bsr.w CalcSine
move.w d4,d2
lsr.w #8,d2
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skiphalvingvel ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w $C(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
@skiphalvingvel:
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s loc_9D62
subi.w #$80,d4
bcc.s loc_9D62
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 "Obj37_Bounce:" and under this...
move.b ($FFFFFEC7).w,$1A(a0)
bsr.w SpeedToPos
addi.w #$18,$12(a0)
...place this:
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skipbounceslow ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w $C(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,$12(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
@skipbounceslow:
You can change the value of the gravity if you like, but I found $E to suit.
Anyway, you should have something looking like this:
Obj37_Bounce: ; XREF: Obj37_Index
move.b ($FFFFFEC7).w,$1A(a0)
bsr.w SpeedToPos
addi.w #$18,$12(a0)
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skipbounceslow ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w $C(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,$12(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
@skipbounceslow:
bmi.s Obj37_ChkDel
move.b ($FFFFFE0F).w,d0
add.b d7,d0
andi.b #3,d0
bne.s Obj37_ChkDel
jsr ObjHitFloor
tst.w d1
bpl.s Obj37_ChkDel
add.w d1,$C(a0)
move.w $12(a0),d0
asr.w #2,d0
sub.w d0,$12(a0)
neg.w $12(a0)
This ensures that, when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.
Sonic 1 Git fix
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:
bsr.w CalcSine
move.w d4,d2
lsr.w #8,d2
Just underneath, paste this:
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skiphalvingvel ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w $C(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
@skiphalvingvel:
You should end up with something looking like this:
@makerings:
move.b #id_RingLoss,0(a1) ; load bouncing ring object
addq.b #2,obRoutine(a1)
move.b #8,obHeight(a1)
move.b #8,obWidth(a1)
move.w obX(a0),obX(a1)
move.w obY(a0),obY(a1)
move.l #Map_Ring,obMap(a1)
move.w #$27B2,obGfx(a1)
move.b #4,obRender(a1)
move.b #3,obPriority(a1)
move.b #$47,obColType(a1)
move.b #8,obActWid(a1)
move.b #-1,(v_ani3_time).w
tst.w d4
bmi.s @loc_9D62
move.w d4,d0
bsr.w CalcSine
move.w d4,d2
lsr.w #8,d2
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skiphalvingvel ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w obY(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
@skiphalvingvel:
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s @loc_9D62
subi.w #$80,d4
bcc.s @loc_9D62
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 this...
move.b (v_ani3_frame).w,obFrame(a0)
bsr.w SpeedToPos
addi.w #$18,obVelY(a0)
...place this:
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skipbounceslow ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w obY(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,obVelY(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
@skipbounceslow:
You can change the value of the gravity if you like, but I found $E to suit.
Anyway, you should have something looking like this:
RLoss_Bounce: ; Routine 2
move.b (v_ani3_frame).w,obFrame(a0)
bsr.w SpeedToPos
addi.w #$18,obVelY(a0)
tst.b ($FFFFF64C).w ; Does the level have water?
beq.s @skipbounceslow ; If not, branch and skip underwater checks
move.w ($FFFFF646).w,d6 ; Move water level to d6
cmp.w obY(a0),d6 ; Is the ring object underneath the water level?
bgt.s @skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,obVelY(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
@skipbounceslow:
bmi.s @chkdel
move.b (v_vbla_byte).w,d0
add.b d7,d0
andi.b #3,d0
bne.s @chkdel
jsr ObjFloorDist
tst.w d1
bpl.s @chkdel
add.w d1,obY(a0)
move.w obVelY(a0),d0
asr.w #2,d0
sub.w d0,obVelY(a0)
neg.w obVelY(a0)
This ensures that, when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.
Sonic 2 fix
This guide uses the Xenowhirl disassembly, but notes for Git users are available.
First, go to "loc_120BA:" (part of the scattered rings object code. Git users, Obj37_Init, three '+'s down) and find this bit of coding:
bsr.w JmpTo4_CalcSine
move.w d4,d2
lsr.w #8,d2
Just underneath, paste this:
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingvel ; If not, branch and skip underwater checks
move.w (Water_Level_2).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
.skiphalvingvel:
So, you should end up with something looking like this:
loc_120BA:
_move.b #$37,0(a1) ; load obj37
addq.b #2,routine(a1)
move.b #8,y_radius(a1)
move.b #8,x_radius(a1)
move.w x_pos(a0),x_pos(a1)
move.w y_pos(a0),y_pos(a1)
move.l #Obj25_MapUnc_12382,mappings(a1)
move.w #$26BC,art_tile(a1)
bsr.w Adjust2PArtPointer2
move.b #$84,render_flags(a1)
move.b #3,priority(a1)
move.b #$47,collision_flags(a1)
move.b #8,width_pixels(a1)
move.b #-1,(Ring_spill_anim_counter).w
tst.w d4
bmi.s loc_12132
move.w d4,d0
bsr.w JmpTo4_CalcSine
move.w d4,d2
lsr.w #8,d2
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingvel ; If not, branch and skip underwater checks
move.w (Water_Level_2).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
.skiphalvingvel:
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s loc_12132
subi.w #$80,d4
bcc.s loc_12132
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 this...
move.b (Ring_spill_anim_frame).w,mapping_frame(a0)
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
...put this:
tst.b (Water_flag).w ; Does the level have water?
beq.s .skipbounceslow ; If not, branch and skip underwater checks
move.w (Water_Level_2).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,y_vel(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings
.skipbounceslow:
You can change the value of the gravity if you like, but I found $E to suit.
Anyway, you should have something looking like this:
Obj_37_sub_2:
move.b (Ring_spill_anim_frame).w,mapping_frame(a0)
bsr.w ObjectMove
addi.w #$18,y_vel(a0)
tst.b (Water_flag).w ; Does the level have water?
beq.s .skipbounceslow ; If not, branch and skip underwater checks
move.w (Water_Level_2).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skipbounceslow ; If not, branch and skip underwater commands
subi.w #$E,y_vel(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect for the rings
.skipbounceslow:
bmi.s loc_121B8
move.b ($FFFFFE0F).w,d0
add.b d7,d0
andi.b #7,d0
bne.s loc_121B8
tst.b render_flags(a0)
bpl.s loc_121D0
jsr (RingCheckFloorDist).l
tst.w d1
bpl.s loc_121B8
add.w d1,y_pos(a0)
move.w y_vel(a0),d0
asr.w #2,d0
sub.w d0,y_vel(a0)
neg.w y_vel(a0)
This ensures that, when underwater, the gravity is not as great. Otherwise, the rings will gain speed and then it won't give the desired underwater effect.
Sonic 3&K fix
This guide uses the SVN disassembly.
Go to "off_1A658:" (the routines of the scattered rings). You'll see that its first job is to go to "loc_1A67A". That needs changing to "loc_1A68C". So, find this...
off_1A658: dc.w loc_1A67A-off_1A658
dc.w loc_1A75C-off_1A658
dc.w loc_1A7C2-off_1A658
dc.w loc_1A7D6-off_1A658
dc.w loc_1A7E4-off_1A658
...and replace it with this:
off_1A658: dc.w loc_1A68C-off_1A658
dc.w loc_1A75C-off_1A658
dc.w loc_1A7C2-off_1A658
dc.w loc_1A7D6-off_1A658
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 there's no point explaining what it's doing here as I just did that. Anyway, you should see this...
off_1A670: dc.w loc_1A67A-off_1A670
dc.w loc_1A7E8-off_1A670
dc.w loc_1A7C2-off_1A670
dc.w loc_1A7D6-off_1A670
dc.w loc_1A7E4-off_1A670
...replace it with:
off_1A670: dc.w loc_1A68C-off_1A670
dc.w loc_1A7E8-off_1A670
dc.w loc_1A7C2-off_1A670
dc.w loc_1A7D6-off_1A670
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:
loc_1A67A:
move.l #Obj_Bouncing_Ring,d6
tst.b (Reverse_gravity_flag).w
beq.s loc_1A68C
move.l #Obj_Bouncing_Ring_Reverse_Gravity,d6
Notice "Bouncing_Ring" (and the reverse one) is being pushed to d6. We need d6, so, delete it. It's no longer needed. Trust me. We have now freed 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:
move.l #Obj_Bouncing_Ring,(a1)
tst.b (Reverse_gravity_flag).w
beq.s .notreverse
move.l #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
.notreverse:
Yes, you might recognize this. It's part of that code you'd just 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:
loc_1A6B6:
move.l #Obj_Bouncing_Ring,(a1)
tst.b (Reverse_gravity_flag).w
beq.s .notreverse
move.l #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
.notreverse:
addq.b #2,5(a1)
move.b #8,$1E(a1)
move.b #8,$1F(a1)
move.w $10(a0),$10(a1)
move.w $14(a0),$14(a1)
move.l #Map_Ring,$C(a1)
move.w #$A6BC,$A(a1)
move.b #$84,4(a1)
move.w #$180,8(a1)
move.b #$47,$28(a1)
move.b #8,7(a1)
move.b #-1,(Ring_spill_anim_counter).w
tst.w d4
bmi.s loc_1A728
move.w d4,d0
jsr (GetSineCosine).l
move.w d4,d2
lsr.w #8,d2
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s loc_1A728
subi.w #$80,d4
bcc.s loc_1A728
move.w #$288,d4
Still looking at "loc_1A6B6:", look and find this bit of coding:
jsr (GetSineCosine).l
move.w d4,d2
lsr.w #8,d2
Just underneath, paste this:
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingvel ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
.skiphalvingvel:
So, you should end up with something looking like this:
loc_1A6B6:
move.l #Obj_Bouncing_Ring,(a1)
tst.b (Reverse_gravity_flag).w
beq.s .notreverse
move.l #Obj_Bouncing_Ring_Reverse_Gravity,(a1)
.notreverse:
addq.b #2,5(a1)
move.b #8,$1E(a1)
move.b #8,$1F(a1)
move.w $10(a0),$10(a1)
move.w $14(a0),$14(a1)
move.l #Map_Ring,$C(a1)
move.w #$A6BC,$A(a1)
move.b #$84,4(a1)
move.w #$180,8(a1)
move.b #$47,$28(a1)
move.b #8,7(a1)
move.b #-1,(Ring_spill_anim_counter).w
tst.w d4
bmi.s loc_1A728
move.w d4,d0
jsr (GetSineCosine).l
move.w d4,d2
lsr.w #8,d2
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingvel ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingvel ; If not, branch and skip underwater commands
asr.w d0 ; Half d0. Makes the ring's x_vel bounce to the left/right slower
asr.w d1 ; Half d1. Makes the ring's y_vel bounce up/down slower
.skiphalvingvel:
asl.w d2,d0
asl.w d2,d1
move.w d0,d2
move.w d1,d3
addi.b #$10,d4
bcc.s loc_1A728
subi.w #$80,d4
bcc.s loc_1A728
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 this...
move.b (Ring_spill_anim_frame).w,$22(a0)
bsr.w MoveSprite2
addi.w #$18,$1A(a0)
...put this:
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvinggrav ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvinggrav ; If not, branch and skip underwater commands
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
.skiphalvinggrav:
You can change the value of the gravity if you like, but I found $E to suit.
Anyway, you should have something looking like this:
loc_1A75C:
move.b (Ring_spill_anim_frame).w,$22(a0)
bsr.w MoveSprite2
addi.w #$18,$1A(a0)
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvinggrav ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvinggrav ; If not, branch and skip underwater commands
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
.skiphalvinggrav:
bmi.s loc_1A7B0
move.b (V_int_run_count+3).w,d0
add.b d7,d0
andi.b #7,d0
bne.s loc_1A7B0
tst.b 4(a0)
bpl.s loc_1A79C
jsr (sub_F994).l
tst.w d1
bpl.s loc_1A79C
add.w d1,$14(a0)
move.w $1A(a0),d0
asr.w #2,d0
sub.w d0,$1A(a0)
neg.w $1A(a0)
This ensures that, 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 this...
move.b (Ring_spill_anim_frame).w,$22(a0)
bsr.w MoveSprite_TestGravity2
addi.w #$18,$1A(a0)
...put this:
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingrevgrav ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingrevgrav ; If not, branch and skip underwater commands
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
.skiphalvingrevgrav:
Again, you can change the value of the reverse gravity if you like.
So, you should have something looking like this:
loc_1A7E8:
move.b (Ring_spill_anim_frame).w,$22(a0)
bsr.w MoveSprite_TestGravity2
addi.w #$18,$1A(a0)
tst.b (Water_flag).w ; Does the level have water?
beq.s .skiphalvingrevgrav ; If not, branch and skip underwater checks
move.w (Water_level).w,d6 ; Move water level to d6
cmp.w y_pos(a0),d6 ; Is the ring object underneath the water level?
bgt.s .skiphalvingrevgrav ; If not, branch and skip underwater commands
subi.w #$E,$1A(a0) ; Reduce gravity by $E ($18-$E=$A), giving the underwater effect
.skiphalvingrevgrav:
bmi.s loc_1A83C
move.b (V_int_run_count+3).w,d0
add.b d7,d0
andi.b #7,d0
bne.s loc_1A83C
tst.b 4(a0)
bpl.s loc_1A828
jsr (sub_FCA0).l
tst.w d1
bpl.s loc_1A828
sub.w d1,$14(a0)
move.w $1A(a0),d0
asr.w #2,d0
sub.w d0,$1A(a0)
neg.w $1A(a0)
This ensures that, when underwater, the gravity is not as great when it's in reverse gravity mode.
SCHG How-To Guide: Sonic the Hedgehog 3 and Knuckles |
---|
Fixing Bugs |
Fix Blue Knuckles | Fix Tails' Respawn Speeds | Fix Super Sonic Bugs |
Design Choices |
Fix Scattered Rings' Underwater Physics | Edit Level Select Text & Pointers | Work with Water | Make the Slots Bonus Game Rotate Smoothly |
Adding Features |
Restore (Sonic 2) Options Menu |
|Fix Scattered Rings Underwater Physics]]