don't click here

Adding Double Jump to Sonic 1?

Discussion in 'Engineering & Reverse Engineering' started by ALittleTooFast, Jul 31, 2017.

  1. ALittleTooFast

    ALittleTooFast

    How about that? Member
    I've been trying to figure out how to add the double jump into my Sonic 1 asm, but instead of giving me a double jump, it just gives me infinite jumps.
    While this is cool, it isn't what I want.

    Here's the code:

    ; -----------------------------------------------------------------------------
    ; Subroutine to make Sonic perform a double-jump
    ; -----------------------------------------------------------------------------

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


    Sonic_DoubleJump:
    tst.w $12(a0); is Sonic moving upwards?
    beq.s endofdoublejump; if not, branch
    cmpi.b #$13,$1C(a0); is sonic using "bounce" animation?
    beq.w endofdoublejump; if yes, branch
    cmpi.b #2,$1C(a0); is Sonic rolling/jumping?
    move.b ($FFFFF605).w,d0
    andi.b #$20,d0; is C button pressed?
    beq.s endofdoublejump; if not, branch
    sub.w #$600,$12(a0); move Sonic upwards
    move.b #2,$1C(a0); use "rolling" animation
    move.w #$A0,d0
    jsr (PlaySound_Special).l
    move.b #1,$21(a0); set the double-jump flag
    endofdoublejump:
    rts


    It should be noted that I'm using the Hivebrain Disassembly now, and that this code was taken from an old SSRG post by a user called shadowbeasts, so that's probably why it isn't working, barring my own general incompetence. :v:

    Edit: Also, I would also like to figure out a way to make the code use a new sprite(s) for the double jump, as well as have Sonic become vulnerable while doing it, similar to a spring jump state. While this isn't required, it would be nice to have.
     
  2. DigitalDuck

    DigitalDuck

    Arriving four years late. Member
    5,352
    438
    63
    Lincs, UK
    TurBoa, S1RL
    You're setting a double-jump flag, but you're not checking it anywhere.
     
  3. ALittleTooFast

    ALittleTooFast

    How about that? Member
    How would I go about "checking" it then?

    Sorry, I'm pretty bad with code, if that wasn't painfully obvious enough.
     
  4. DigitalDuck

    DigitalDuck

    Arriving four years late. Member
    5,352
    438
    63
    Lincs, UK
    TurBoa, S1RL
    If you're planning any serious ASM work, this guide will be invaluable. But since you're a beginner and this is a relatively small thing, I'll go through all the problems.

    If we look at the first two lines of the code:

    Code (Text):
    1. tst.w $12(a0); is Sonic moving upwards?
    2. beq.s endofdoublejump; if not, branch
    This looks at the word at $12(a0) (in this case, it's Sonic's Y-velocity), and sets certain flags depending on its value. If it's 0, it goes to the "endofdoublejump" label.

    This is wrong to start with; it'll only prevent you from a double jump if your Y-velocity is exactly 0; you either want to make it so it's less than 0 (as the label suggests):

    Code (Text):
    1. tst.w $12(a0); is Sonic moving upwards?
    2. blt.s endofdoublejump; if not, branch
    ... but you don't actually need it and can remove it entirely, which is what I'd suggest.

    The next problem is here:

    Code (Text):
    1. cmpi.b #2,$1C(a0); is Sonic rolling/jumping?
    There's a check for if Sonic is rolling/jumping, but nothing is done about it. This means that Sonic can double-jump at any time, even if he hasn't jumped. It should be followed with a branch - in this case, you want to branch if Sonic's state is not equal to 2, so the code becomes:

    Code (Text):
    1. cmpi.b #2,$1C(a0); is Sonic rolling/jumping?
    2. bne.s endofdoublejump; if not, branch
    The third problem is here:

    Code (Text):
    1. sub.w #$600,$12(a0); move Sonic upwards
    This subtracts from Sonic's Y-velocity when you double jump. This means that if you double jump early (e.g. by pressing B and then C the frame afterwards), you'll end up with four times the jump height. If you want behaviour similar to the lightning shield in Sonic 3, you need to be setting Sonic's Y-velocity, like this:

    Code (Text):
    1. move.w #-$600,$12(a0); move Sonic upwards
    If you want to change the double-jump height, just change the first number (but remember it's in hex).

    Now onto checking the double jump flag. You'll notice a lot of the checks all look the same, and this'll look exactly like those.

    Code (Text):
    1. tst.w $21(a0); is the double jump flag set?
    2. bne.s endofdoublejump; if yes, branch
    This can go in between any of the checks before the velocity is set, but it fits best right at the start.

    The final code looks like this:

    Code (Text):
    1. ; -----------------------------------------------------------------------------
    2. ; Subroutine to make Sonic perform a double-jump
    3. ; -----------------------------------------------------------------------------
    4.  
    5. ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    6.  
    7.  
    8. Sonic_DoubleJump:
    9. tst.w $21(a0); is the double jump flag set?
    10. bne.s endofdoublejump; if yes, branch
    11. cmpi.b #$13,$1C(a0); is sonic using "bounce" animation?
    12. beq.w endofdoublejump; if yes, branch
    13. cmpi.b #2,$1C(a0); is Sonic rolling/jumping?
    14. bne.s endofdoublejump; if not, branch
    15. move.b ($FFFFF605).w,d0
    16. andi.b #$20,d0; is C button pressed?
    17. beq.s endofdoublejump; if not, branch
    18. move.w #-$600,$12(a0); move Sonic upwards
    19. move.b #2,$1C(a0); use "rolling" animation
    20. move.w #$A0,d0
    21. jsr (PlaySound_Special).l
    22. move.b #1,$21(a0); set the double-jump flag
    23. endofdoublejump:
    24. rts
    Some more notes:

    - You need to clear the double-jump flag when Sonic lands, so Sonic can double jump again. I don't know exactly where this is in Hivebrain, but I believe you're looking for the label "Sonic_Floor". A simple

    Code (Text):
    1. move.b #0,$21(a0); clear the double-jump flag
    does the job.

    - This code only does a double-jump when the C button is pressed. I believe you need to change the line

    Code (Text):
    1. andi.b #$20,d0; is C button pressed?
    to

    Code (Text):
    1. andi.b #$70,d0; is ABC button pressed?
    in order to fix this.

    - If you want Sonic to be vulnerable in the double-jump, you want to change this line:

    Code (Text):
    1. move.b #2,$1C(a0); use "rolling" animation
    To change to the spring animation, you'd want to change #2 to #16 (or #$10); to use your own animation, you need change it to whatever number your new animation is.
     
  5. ALittleTooFast

    ALittleTooFast

    How about that? Member
    Alright, I tried to change and use the code the way you told me to, but now Sonic doesn't want to double jump, at all. Not even the first time. Where exactly do I put the "clear the double jump flag" in Sonic_Floor? Near the end? Or at the beginning?
     
  6. DigitalDuck

    DigitalDuck

    Arriving four years late. Member
    5,352
    438
    63
    Lincs, UK
    TurBoa, S1RL
    At the beginning should be fine.

    It's possible that there's no double jump because of when the double jump routine is being called - it should only be called while in the jump state (make sure your "bsr.w Sonic_DoubleJump" is in Sonic_MdJump, near the branches to Sonic_JumpDirection etc. (labels may be different in your disassembly)).

    If this doesn't help, comment out the double jump flag check (add a semicolon to the beginning of the lines so that they're ignored - do this to both the test and the following branch). This will either give you infinite double jumps (in which case the flag is indeed the problem), or it'll do nothing (in which case it's not the problem). Do this to all of the checks and you should be able to tell us what's going wrong.
     
  7. ALittleTooFast

    ALittleTooFast

    How about that? Member
    Alright, I tried commenting out every single check in order, and still Sonic does nothing. It appears that "Sonic_MdJump" label in the Hivebrain disassembly is called "Obj01_MdJump".
    For the other checks aside from the first one, do I comment out "cmbi.b" AND "beq.w" or just "cmbi.b"?
    Edit: Also, should "endofdoublejump" be it's own label, or should it be double tabbed along with the rest of the code?
     
  8. DigitalDuck

    DigitalDuck

    Arriving four years late. Member
    5,352
    438
    63
    Lincs, UK
    TurBoa, S1RL
    I'm not sure, then.
    Both. Commenting out just the comparison will mess things up (the branch will be based on the previous check); you have to comment out the branch as well.
    It's a label (your branches go there). I'm not sure how whitespace is treated (depends on your build system), but conventionally labels are left-aligned without tabs.
     
  9. ALittleTooFast

    ALittleTooFast

    How about that? Member
    Alright, just going to state everything I've done just to make sure I may not have missed something.

    I put bsr.w Sonic_DoubleJump right after the Label "Obj01_MdJump"
    I added the Subroutine "Sonic_DoubleJump" right after "Sonic_JumpHeight" and before "Sonic_SpinDash", which I did add.
    I put this code in;

    Sonic_DoubleJump:
    tst.w $21(a0); is the double jump flag set?
    bne.s End_DoubleJump; if yes, branch
    cmpi.b #$13,$1C(a0); is sonic using "bounce" animation?
    beq.w End_DoubleJump; if yes, branch
    cmpi.b #2,$1C(a0); is Sonic rolling/jumping?
    bne.s End_DoubleJump; if not, branch
    move.b ($FFFFF605).w,d0
    andi.b #$20,d0; is C button pressed?
    beq.s End_DoubleJump; if not, branch
    move.w #-$600,$12(a0); move Sonic upwards
    move.b #2,$1C(a0); use "rolling" animation
    move.w #$A0,d0
    jsr (PlaySound_Special).l
    move.b #1,$21(a0); set the double-jump flag
    End_DoubleJump:
    rts

    And finally, I put move.b #0,$21(a0); clear the double-jump flag after the label "Sonic_Floor"

    Perhaps I put the subroutine in the wrong place? That's the only thing I could think of. :v: