Jump Dash in Sonic 2

Discussion in 'Tutorials Archive' started by vladikcomper, Jan 11, 2010.

Thread Status:
Not open for further replies.
  1. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    There was no guide about adding Jump Dash in Sonic 2, so I decided to create it despite I know Sonic 2 engine not well. Everyone now can enjoy Jump Dash in Sonic 1, so let him enjoy it in Sonic 2.


    Jump Dash in Sonic 2


    Note that I used Sonic 2 2007 Disassembly.


    So, let's start!


    Go to the Obj01_MdJump subroutine and just before the line "bsr.w Sonic_JumpAngle" add:



    bsr.w Sonic_JumpDash ;++ branch to Jump Dash subroutine



    Now you need to add subroutines that allows Sonic to preform Jump Dash. I personally added it after Sonic_Jump. Find the end of this function, the line "; End of function Sonic_Jump" and right after it insert the following code:



    ; ---------------------------------------------------------------------------
    ; Subroutine to do Jump Dash (code by Vladikcomper)


    ; ---------------------------------------------------------------------------


    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||


    Sonic_JumpDash:


    cmpi.b #2,anim(a0) ; is Sonic rolling?


    bne.s Sonic_JumpDash_Rts ; if no, branch


    btst #7,status(a0) ; was Jump Dash flag set?


    bne.s Sonic_JumpDash_Rts ; if yes, branch


    move.b (Ctrl_1_Press_Logical).w,d0


    andi.b #$70,d0 ; is A,B or C pressed?


    beq.w Sonic_JumpDash_Rts ; if no, branch


    move.w #$BC,d0 ; play sound


    jsr (PlaySound).l


    bset #7,status(a0) ; set Jump Dash flag


    move.w #$900,x_vel(a0) ; set Jump Dash speed


    move.w #0,y_vel(a0) ; clear Y-velocity


    btst #0,status(a0) ; is sonic facing left?


    beq.s Sonic_JumpDash_Rts ; if no, branch


    neg.w x_vel(a0) ; negate X-velocity


    Sonic_JumpDash_Rts:


    rts


    ; End of function Sonic_JumpDash



    Build your ROM and try out new ability. As you'll find out, there is a bug, Sonic can preform Jump Dash only at once. That's because Jump Dash subroutine sets a flag to avoid Jump Dash reusing in Mid-air. This flag's address is status(a0), the eighth bit. When it's set, Sonic won't be able to Jump Dash. We need to clear this flag when Sonic touches the floor.


    Go to Sonic_ResetOnFloor label and add this line right after it:



    bclr #7,status(a0)



    Now Jump Dash seems to work normally. But there is another bug. When Sonic stands on objects (bridge, floating platform etc.) after Jump Dash, the flag isn't cleared. That's because Sonic_ResetOnFloor subroutine isn't run.


    To fix this bug, go to Obj01_Control and above the line "tst.b (Control_Locked).w ; are controls locked?", add this code:



    + btst #3,status(a0) ; is Sonic standing on an object?
    beq.s + ; if no, branch


    bclr #7,status(a0) ; clear Jump Dash flag



    This code checks if the fourth bit in the byte status(a0) is set. It's set when Sonic stands on an object. If it so, JD flag is cleared.


    And the last bug we need to fix is speed bug. You see, the game limits Jump Dash speed, so it can't be higher than Sonic's Top Speed. To fix the bug, you will have to remove the Mid-Air speed cap. This is a quite easy thing to do.


    Go to Sonic_ChgJumpDir subroutine and add the following code above "move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)":



    add.w d5,d0 ; remove this frame's acceleration change
    cmp.w d1,d0 ; compare speed with top speed


    ble.s + ; if speed was already greater than the maximum, branch



    Now find the "move.w d6,d0 ; limit speed in air going right, even if Sonic was already going faster (speed limit/cap)" line and add this before it:



    sub.w d5,d0 ; remove this frame's acceleration change
    cmp.w d1,d0 ; compare speed with top speed


    ble.s + ; if speed was already greater than the maximum, branch



    Build your ROM and enjoy.


    Please tell me if you notice any grammar/lexical mistakes in my text.
     
    Last edited by a moderator: Jan 13, 2010
  2. Selbi

    Selbi The Euphonic Mess Member

    Joined:
    Jul 20, 2008
    Messages:
    2,429
    Location:
    Northern Germany
    While it's nice designed for Sonic 2, I don't really see a point here, since my code also worked with Sonic 2. Besides that, you missed checks for being underwater or having shoes (while this is not necesary, I still think it's a good idea to do it). But nice guide though. :)
     
  3. Thorn

    Thorn wroar Member

    Joined:
    Aug 11, 2007
    Messages:
    70
    I don't know why people swear there's always some big difference between adding features to Sonic 1 and Sonic 2. I mean, on the scale of a complete game overhaul, of course there is, but for all of the small projects here, it's just a matter of changing equates and SST offsets. Basically, every project on here is Sonic 1, so Sonic 2 scares people now. I should totally make some crazy tutorial for some badass feature, but write it in terms of Sonic 2 and watch as absolutely *nobody* implements it. :)


    That said,

    ...no offense meant, because I know that Sonic 1 is slightly different in that regard, but that was pretty lazy. That still doesn't remove the mid-air speedcap. Lemme pretend that paragraph of your tutorial doesn't exist, and I'll continue your tutorial here. vladikcomper, if you could test what I put down and see if it works for you, I'd kindly ask that you remove that paragraph from your tutorial, else it'll make every hack have the same altered speed for Sonic instead of simply having a speed limit removal like Sonic 3 & Knuckles.


    *ahem*


    Right then, the key difference between the speed cap in Sonic 1 and the speed cap in Sonic 2 is that Sonic 2 only caps speed in midair. All you need to do is remove the midair speed cap. In the 2007 disassembly, the relevant routine for Sonic is...




    ; loc_1A8E8:


    Sonic_ChgJumpDir:


    move.w (Sonic_top_speed).w,d6


    move.w (Sonic_acceleration).w,d5


    asl.w #1,d5


    btst #4,status(a0) ; did Sonic jump from rolling?


    bne.s Obj01_Jump_ResetScr ; if yes, branch to skip midair control


    move.w x_vel(a0),d0


    btst #2,(Ctrl_1_Held_Logical).w


    beq.s + ; if not holding left, branch


    bset #0,status(a0)


    sub.w d5,d0 ; add acceleration to the left


    move.w d6,d1


    neg.w d1


    cmp.w d1,d0 ; compare new speed with top speed


    bgt.s + ; if new speed is less than the maximum, branch


    move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)


    +


    btst #3,(Ctrl_1_Held_Logical).w


    beq.s + ; if not holding right, branch


    bclr #0,status(a0)


    add.w d5,d0 ; accelerate right in the air


    cmp.w d6,d0 ; compare new speed with top speed


    blt.s + ; if new speed is less than the maximum, branch


    move.w d6,d0 ; limit speed in air going right, even if Sonic was already going faster (speed limit/cap)


    ; Obj01_JumpMove:


    + move.w d0,x_vel(a0)



    ...and a similar routine exists for Tails. You can plainly see the code that causes the speedcap. In plain English, it does the following for both right and left movement if you're holding a directional button (the speedcap in Sonic 1 and 2 only occurs if you push a directional button):


    * Accelerate the character in the x direction


    * Check if the character's speed is more than the character's max speed


    * If so, slow the character down to his max speed


    Here's what we want to happen:


    * Check if the character's speed is more than the character's max speed


    * If so, don't accelerate (but don't slow down either)...


    * ...else, accelerate in the x direction.


    What we want is basically a rearrangement of what the game has where the acceleration comes after the speed check instead of before, and we simply remove the speedcapping line.




    ; loc_1A8E8:


    Sonic_ChgJumpDir:


    move.w (Sonic_top_speed).w,d6


    move.w (Sonic_acceleration).w,d5


    asl.w #1,d5


    btst #4,status(a0) ; did Sonic jump from rolling?


    bne.s Obj01_Jump_ResetScr ; if yes, branch to skip midair control


    move.w x_vel(a0),d0


    btst #2,(Ctrl_1_Held_Logical).w


    beq.s + ; if not holding left, branch


    bset #0,status(a0)


    move.w d6,d1


    neg.w d1


    cmp.w d0,d1 ; compare new speed with top speed


    bgt.s + ; if new speed is more than the maximum, branch


    ;move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)


    sub.w d5,d0 ; add acceleration to the left


    +


    btst #3,(Ctrl_1_Held_Logical).w


    beq.s + ; if not holding right, branch


    bclr #0,status(a0)


    cmp.w d0,d6 ; compare new speed with top speed


    blt.s + ; if new speed is more than the maximum, branch


    ;move.w d6,d0 ; limit speed in air going right, even if Sonic was already going faster (speed limit/cap)


    add.w d5,d0 ; accelerate right in the air


    ; Obj01_JumpMove:


    + move.w d0,x_vel(a0)



    The speedcap is commented out, and the game only accelerates the character if he's not already going too fast already.


    As Selbi said while I was typing this (stupid post ninjas), checks for situations where Sonic's top speed is altered should be added to vladikcomper's code. Underwater checks are a must, and if you want the speed shoes to power up the jump dash as well (they don't in most official games), that could be done as well. On the topic of Selbi's code:

    This does not constitute a Sonic 2 Jump Dash guide. Saying what modifications are required constitutes a guide, even if you don't actually type out the exact ASM edits.


    There's a little something extra that you can do here if you wish, depending on what kind of physics you prefer. The 4th and 5th lines of code under this label check to see if you've jumped from a roll, and if you have, you forfeit midair control. This is a behavior that occurs in the classic Sonic games that has been removed for more recent games. Simply commenting out these two lines will allow you to control any jump regardless of how you initiated it. This is completely optional and won't change the performance of the jump dash, but it will give you control of a jump dash if you jump out of a roll, so it's probably desired.
     
    Last edited by a moderator: Jan 11, 2010
  4. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    That's because most of Sonic 2 hackers don't know ASM well, as I can see playing S2 hacks. You see people wanting to learn ASM, start their ASM edits in Sonic 1. Most of them stay hacking Sonic 1 forever. Another reason may be that code in S2 2007 Disassembly mostly uses constants instead of RAM addresses, so it looks really different from the code from S1 Hivebrain's Disassembly.


    Selbi, I knew your guide is able to work in Sonic 2, but I see JD in Sonic 2 really seldom, so I decided to help people and made this guide specifically for Sonic 2.

    Of course, I'll remove that part of tutorial. Though I see nothing bad in simple increasing Sonic's Top Speed. Most of hacks will have the same speed, but the gameplay'll be definitely better. Who cares if the speed will be the same =P

    Sorry, but I haven't enough time even to read your tutorial now. But I'll replace the last paragraph in my guide very soon. :)
     
  5. MrSpade

    MrSpade It's meant to be Mr_Spad3 but y'know... Member

    Joined:
    Dec 5, 2009
    Messages:
    172
    Location:
    The UK
    I would give this a go, but the jumpdash might cause some conflicting code with my supersonic double-jump thing.


    And it doesn't help that it's 9:52PM in the UK at the moment, so I'd rather not risk me with my own ASM file in case I fuck it up out of tiredness. =P
     
  6. Thorn

    Thorn wroar Member

    Joined:
    Aug 11, 2007
    Messages:
    70
    ^ Why would it cause conflicting code? You have three buttons to work with, not one. All you need to do is assign one button to one feature and the other to... the other.
     
  7. MrSpade

    MrSpade It's meant to be Mr_Spad3 but y'know... Member

    Joined:
    Dec 5, 2009
    Messages:
    172
    Location:
    The UK
    The whole Jumpdash whilst transforming scenario.


    Thats what I meant in the fist place, Aplogies.
     
  8. shadowbeasts

    shadowbeasts I'm Legend Member

    Joined:
    Jan 5, 2009
    Messages:
    286
    Location:
    Good 'ol USA.
    I found one error with this guide (with the branch to jumpdash planting)


    You said

    for me the jumpdash didn't work when I put


    Code:
    	bsr.w   Sonic_JumpDash  ;++ branch to Jump Dash subroutine
    
    at the Obj01_MdJump subroutine, just before the line "bsr.w Sonic_JumpAngle it only worked when I put it at
    Code:
    Obj01_MdJump2
    
    after the label. Please fix this errer in the code.
     
    Last edited by a moderator: Jan 12, 2010
  9. Selbi

    Selbi The Euphonic Mess Member

    Joined:
    Jul 20, 2008
    Messages:
    2,429
    Location:
    Northern Germany
    Code:
    ; Start of subroutine Obj01_MdJump
    ; Called if Sonic is in a ball and airborne (he could be jumping but not necessarily)
    
    
    ; Notes: This is identical to Obj01_MdAir, at least at this outer level.
    
    
    ;        Why they gave it a separate copy of the code, I don't know.
    
    
    ; loc_1A330: Obj01_MdJump2:
    
    
    Obj01_MdJump:
    
    
    	bsr.w	Sonic_JumpHeight
    
    
    	bsr.w	Sonic_ChgJumpDir
    
    
    	bsr.w	Sonic_LevelBound
    
    
    	jsr	ObjectMoveAndFall
    
    
    	btst	#6,status(a0)	; is Sonic underwater?
    
    
    	beq.s	+		; if not, branch
    
    
    	subi.w	#$28,y_vel(a0)	; reduce gravity by $28 ($38-$28=$10)
    
    
    +
    
    
    	bsr.w	Sonic_JumpAngle
    
    
    	bsr.w	Sonic_DoLevelCollision
    
    
    	rts
    
    
    ; End of subroutine Obj01_MdJump
    
    
    That is the code of Obj01_MdJump (unchanged). As you can see, Obj01_MdJump2 is commented out, which means, MdJump and MdJump2 are for the same purpose in here. I guess you confused this with Sonic 1.
     
  10. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    I've just replaced the last part of my guide. Now it says how to remove Mid-Air speed cap.


    Thorn, commenting out the line that limits the speed will cause that Sonic will have unlimited speed in the air. It better just to compare the speed before acceleration with the top speed, like it's done in Sonic_Move subroutine. If current speed is more than the top one, it won't be neither limited nor increased.

    It works fine for me. Maybe you added the line above the "+"? If so, JD will work only in water.
     
    Last edited by a moderator: Jan 13, 2010
  11. Thorn

    Thorn wroar Member

    Joined:
    Aug 11, 2007
    Messages:
    70
    How does it allow an infinite speed in the air? Here's what I had for traveling left (and similar for the right, of course):




    cmp.w d0,d1 ; compare new speed with top speed


    bgt.s + ; if new speed is more than the maximum, branch


    ;move.w d1,d0 ; limit speed in air going left, even if Sonic was already going faster (speed limit/cap)


    sub.w d5,d0 ; add acceleration to the left


    +



    If your speed is more than the set maximum, the code branches around the line that actually applies acceleration, which is moved from before the check against (Sonic_top_speed).w to after the check. Therefore, the speed limit for this is the greater of (Sonic_top_speed).w or whatever speed you were going when you left the ground. Of course, outside of this code, natural deceleration kicks in in midair at the peak of a jump unless you hit a ceiling to avoid a natural peak, so you speed would drop over time, not increase infinitely. Admittedly this does mean that somebody traveling at a speed of, say, 1 below the value of (Sonic_top_speed).w will accelerate ever-so-slightly past it, but it will be imperceptible and it's an easy fix, far from the "infinite speed" you're claiming.


    EDIT: Just realized... even if you do go slightly over (Sonic_top_speed).w, the natural deceleration in the air will bring you back to it. So yeah, this works perfectly.
     
    Last edited by a moderator: Jan 14, 2010
  12. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    415
    Ops, my bad. Sorry, I didn't understand your code correctly the first time due to my bad English. Now it's clear for me.


    Your way to remove the speed cap is better, but I'm too lazy to change my tutorial again =P
     
  13. shadowbeasts

    shadowbeasts I'm Legend Member

    Joined:
    Jan 5, 2009
    Messages:
    286
    Location:
    Good 'ol USA.
    Ya, that's what I did but it works either way so it all works out. :)
     
Thread Status:
Not open for further replies.