How to insert the reverse gravity gimmick from S3K into Sonic 2

Discussion in 'Tutorials Archive' started by ThomasThePencil, Mar 25, 2013.

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

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    NOTE: THIS GUIDE IS NOT FINISHED YET.
     
    Note: This guide is written with the Hg disassembly in mind.
    So, I was playing around with Death Egg Zone Act 1 in my hack (I had just ported the S3K art) when I thought it would be fitting to also port the reverse gravity gimmick from S3K's Death Egg Zone. In this guide, we'll make pressing a button activate the reverse gravity gimmick. I used Death Egg Zone Act 1 for this guide, but you, of course, can change that to whatever zone you want.
     
    Step 1: Getting the flag set up
    First and foremost, we need to insert the flag itself, so that the game knows what the fuck we're doing later on. So find this:


    ds.b 3 ; $FFFFF7D7-$FFFFF7D9 ; seems unused

     
    And change it to this:


    ds.b 2 ; $FFFFF7D7-$FFFFF7D8 ; seems unused

    Reverse_gravity_flag: ds.b 1 ; flag to reverse the gravity

     
    Now we have our reverse gravity flag.
     
    Step 2: Setting up the button object to set and unset the flag in a certain zone
    Now that we have our flag, we need to set up the button object to work with it. So head to Obj47_Main and change it to this:


    ; loc_24D32:

    Obj47_Main:

    tst.b render_flags(a0)

    bpl.s BranchTo_JmpTo12_MarkObjGone

    move.w #$1B,d1

    move.w #4,d2

    move.w #5,d3

    move.w x_pos(a0),d4

    bsr.w JmpTo6_SolidObject

    move.b #0,mapping_frame(a0)

    move.b subtype(a0),d0

    andi.w #$F,d0

    lea (ButtonVine_Trigger).w,a3

    lea (a3,d0.w),a3

    moveq #0,d3

    btst #6,subtype(a0)

    beq.s +

    moveq #7,d3

    +

    move.b status(a0),d0

    andi.b #standing_mask,d0

    bne.s +++

    bclr d3,(a3)

    cmpi.w #death_egg_zone_act_1,(Current_ZoneAndAct).w

    bne.s ++

    cmpi.b #1,(Reverse_gravity_flag).w

    beq.s +

    move.b #1,(Reverse_gravity_flag).w

    bra.s ++

    +

    move.b #0,(Reverse_gravity_flag).w

    +

    bra.s BranchTo_JmpTo12_MarkObjGone

    You can change death_egg_zone_act_1 to whatever zone you want.


    Step 2.1: Fixing the art for the button
    If you don't mind the art not displaying correctly, skip this step. Otherwise, keep reading.
    When the button object comes on-screen, chances are you're going to be force-killed without reason (read: insta-killed) because the art is displaying entirely wrong. So, we need to do a bit of work to perform this right.

    First, head upwards to Obj47_Init and change it so it looks like this:
     


    ; loc_24D06:

    Obj47_Init:

    addq.b #2,routine(a0)

    move.l #Obj47_MapUnc_24D96,mappings(a0)

    cmpi.b #death_egg_zone_act_1,(Current_ZoneAndAct).w

    beq.s +

    move.w #make_art_tile(ArtTile_ArtNem_Button_DEZ,0,0),art_tile(a0)

    bra.s ++

    rts

    +

    move.w #make_art_tile(ArtTile_ArtNem_Button,0,0),art_tile(a0)

    +

    bsr.w JmpTo21_Adjust2PArtPointer

    move.b #4,render_flags(a0)

    move.b #$10,width_pixels(a0)

    move.w #$200,priority(a0)

    addq.w #4,y_pos(a0)

    Once again, you can change the death_egg_zone_act_1 to whatever you want, but for the purposes of this tutorial, I will leave it as it is.
     
    Now, head to PlrList_Dez2. You should see something like this.


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

    ; Pattern load queue

    ; DEZ Secondary

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

    PlrList_Dez2: plrlistheader

    plreq tiles_to_bytes(ArtTile_ArtNem_SilverSonic), ArtNem_SilverSonic

    plreq tiles_to_bytes(ArtTile_ArtNem_DEZWindow), ArtNem_DEZWindow

    plreq tiles_to_bytes(ArtTile_ArtNem_RobotnikRunning), ArtNem_RobotnikRunning

    plreq tiles_to_bytes(ArtTile_ArtNem_RobotnikUpper), ArtNem_RobotnikUpper

    plreq tiles_to_bytes(ArtTile_ArtNem_RobotnikLower), ArtNem_RobotnikLower

    PlrList_Dez2_End

     
    Just above PlrList_Dez2_End, put this:


    plreq tiles_to_bytes(ArtTile_ArtNem_Button), ArtNem_Button

     
    Now the art should load properly.
     
     

     
    Step 3: Adding a lot of code to work with the flag
    So we have our flag, and we have code that references it. Are we done, you might ask? NO. There are a TON of changes we need to make for the flag to work right.

    Step 3.1: Hurt_Sidekick
    First, head to Hurt_Sidekick. It should look like this:


    ; loc_3F8BE:

    Hurt_Sidekick:

    move.b #4,routine(a0)

    bsr.w JmpTo_Sonic_ResetOnFloor_Part2

    bset #1,status(a0)

    move.w #-$400,y_vel(a0) ; make Sonic bounce away from the object

    move.w #-$200,x_vel(a0)

    btst #6,status(a0) ; underwater?

    beq.s Hurt_Reverse ; if not, branch

    move.w #-$200,y_vel(a0) ; bounce slower

    move.w #-$100,x_vel(a0)

     
     
     
    Change it to this:


    ; loc_3F8BE:

    Hurt_Sidekick:

    move.b #4,routine(a0)

    bsr.w JmpTo_Sonic_ResetOnFloor_Part2

    bset #1,status(a0)

    move.w #-$400,y_vel(a0) ; make Sonic bounce away from the object

    move.w #-$200,x_vel(a0)

    tst.b (Reverse_gravity_flag).w ; is the reverse gravity gimmick activated?

    beq.s + ; if not, branch

    move.w #$400,y_vel(a0) ; make Sonic bounce away from the object

    move.w #-$200,x_vel(a0)

    bra.s Hurt_Reverse

    +

    btst #6,status(a0) ; underwater?

    beq.s Hurt_Reverse ; if not, branch

    move.w #-$200,y_vel(a0) ; bounce slower

    move.w #-$100,x_vel(a0)

     
    Now your character should bounce away properly when they hit an object. But, we're not done yet.
     
    Step 3.2: KillCharacter
    This one isn't difficult at all, either. Head to KillCharacter. You should see this:


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



    ; loc_3F926: KillSonic:

    KillCharacter:

    tst.w (Debug_placement_mode).w

    bne.s ++

    clr.b status_secondary(a0)

    move.b #6,routine(a0)

    bsr.w JmpTo_Sonic_ResetOnFloor_Part2

    bset #1,status(a0)

    move.w #-$700,y_vel(a0)

    move.w #0,x_vel(a0)

    move.w #0,inertia(a0)

    move.b #AniIDSonAni_Death,anim(a0)

    bset #high_priority_bit,art_tile(a0)

    move.w #$A3,d0

    cmpi.b #ObjID_Spikes,(a2)

    bne.s +

    move.w #$A6,d0

    +

    jsr (PlaySound).l

    +

    moveq #-1,d0

    rts
    Change it to this (new code suggested by redhotsonic):


    KillCharacter:
    tst.w (Debug_placement_mode).w
    bne.s +++
    clr.b status_secondary(a0)
    move.b #6,routine(a0)
    bsr.w JmpTo_Sonic_ResetOnFloor_Part2
    bset #1,status(a0)
    move.w #-$700,y_vel(a0) ; Apply gravity to Sonic when he dies
    tst.b (Reverse_gravity_flag).w ; WAIT! Is reverse gravity on?
    beq.s + ; It isn't? Branch then and carry on
    neg.w y_vel(a0) ; As reverse gravity is on, reverse the Y velocity
    +
    move.w #0,x_vel(a0)
    move.w #0,inertia(a0)
    move.b #AniIDSonAni_Death,anim(a0)
    bset #high_priority_bit,art_tile(a0)
    move.w #$A3,d0
    cmpi.b #ObjID_Spikes,(a2)
    bne.s +
    move.w #$A6,d0
    +
    jsr (PlaySound).l
    +
    moveq #-1,d0
    rts 

     
    This should fix the way your character falls when he/she is dying. However, we're still not done.

     
    Step 3.3: ObjectMoveAndFall
    This is probably the most important change. We need to fix the way the character falls when he/she does, well, just about anything! Head to ObjectMoveAndFall and change it to this:


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

    ; Subroutine to make an object move and fall downward increasingly fast

    ; This moves the object horizontally and vertically

    ; and also applies gravity to its speed

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



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



    ; sub_16380: ObjectFall:

    ObjectMoveAndFall:

    move.w x_vel(a0),d0

    ext.l d0

    lsl.l #8,d0

    add.l d0,x_pos(a0)

    move.w y_vel(a0),d0

    tst.b (Reverse_gravity_flag).w

    bne.s +

    addi.w #$38,y_vel(a0) ; apply gravity

    bra.s ++

    +

    addi.w #-$38,y_vel(a0) ; apply reverse gravity

    +

    ext.l d0

    lsl.l #8,d0

    add.l d0,y_pos(a0)

    rts

    ; End of function ObjectMoveAndFall

     
    As a bonus, pasting it as it is here will also speed up your hack slightly. Regardless, this will fix the way your character falls.

     
    BUT WAIT!
    I'm sorry, this thing can still fuck up with the way it does things. The death_egg_zone_act_1 note still applies, but I'd like to explain to you how we fix this. Change ObjectMoveAndFall to this (new code suggested by redhotsonic):

    Code:
    ; ---------------------------------------------------------------------------
    
    ; Subroutine to make an object move and fall downward increasingly fast
    
    ; This moves the object horizontally and vertically
    
    ; and also applies gravity to its speed
    
    ; ---------------------------------------------------------------------------
    
    
    
    ; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
    
    
    
    ; sub_16380: ObjectFall:
    
    ObjectMoveAndFall:
    move.w    x_vel(a0),d0
    ext.l    d0
    lsl.l    #8,d0
    add.l    d0,x_pos(a0)
    move.w    y_vel(a0),d0
    addi.w    #$38,y_vel(a0)             ; apply gravity
    tst.b    (Reverse_gravity_flag).w    ; WAIT! Is reverse gravity on?
    beq.s    +                ; It isn't? Branch then and carry on
    subi.w    #$70,y_vel(a0)            ; As reverse gravity is on, reverse the Y velocity
    +
    ext.l    d0
    lsl.l    #8,d0
    add.l    d0,y_pos(a0)
    rts
     
    Last edited by a moderator: Mar 26, 2013
  2. XtremerSadiqX

    XtremerSadiqX Burning Way Past Cool Member

    Joined:
    Feb 5, 2013
    Messages:
    76
    Location:
    Creedmoor City,NC
    think you could make a poc hack
     
  3. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    Well, I suppose I could, once I finish getting this feature ready in my own hack. There's a lot to do with this kind of thing, considering how much is involved.

    Also, I've added KillCharacter to the guide so people don't try to go through and do some crazy feat of coding when it's so simple to fix!
     
  4. Dark Lips

    Dark Lips Well-Known Member Member

    Joined:
    Nov 14, 2008
    Messages:
    293
    Location:
    Wolverhampton UK
    What version of the s2 dissasembelly are you using as I am unable to find ds.b    3    ; $FFFFF7D7-$FFFFF7D9 ; seems unused
     
  5. JoenickROS

    JoenickROS ROS (bug fixing in progress) Member

    Joined:
    Feb 5, 2012
    Messages:
    929
    He's using the HG he says it in the beginning if the guide, not to sound like an ass or anything.
     
  6. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    Yes. This guide, along with my other guides, are written with the Hg disassembly in mind. And that's how it's going to be for I-don't-even-have-a-fucking-idea-how-long :p

    Seriously, though, I've already done so much with my hack. It doesn't seem worth it to start over on an Xenowhirl disassembly just because more people use it. I am sticking with the Hg disassembly, and these guides of mine are meant to help people slowly edge into using the Hg disassembly.

    Now that I think about it, this guide is probably the most interesting thing I've posted in a long time.
     
  7. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    I almost forgot to ask, is anyone having any problems with this?

    Also, I've finally added the most important change to this guide: ObjectMoveAndFall! This one fixes the way Sonic falls when he does just about anything.
     
    Last edited by a moderator: Mar 26, 2013
  8. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    This looks interesting, and your guide is very-well layed out. Nice work.  I might give this a go in a clean S2 disassembly tonight.  So at the moment, I can't comment if this works or not (I had a quick skim through so I haven't picked up any errors in your guide).

    Although, like been asked by another member, can you upload a clean S2 game with this feature enabled?  To get more people interested, it's nice to see a ROM with it featured.  Doesn't have to be your hack, but a clean S2 ROM with it would be nice.  Like I did in one of my guides.
     
  9. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    Now add gravity switches that work with angles of 90 degrees, so Sonic can walk on walls.


    *runs*
     
  10. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    Death Egg - Sonic 4 episode II style =P
     
  11. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    Okay, I've had a quick look and tried it, and as completely expected, this isn't complete.  It's a good try and I can see where you're coming from, but it doesn't work (well, not for me anyway).  I know you've put at the top saying the guide isn't finished, but seriously, why release a guide on guiding people how to port an unfinished feature?  You just don't.  Until you get it completely working and guide completed, then post your guides.


     
    You need to get collision sorted out for a start so sonic can walk upside down and react.  Another is to make Sonic die when he hits the top of the screen, rather than fall through it forever.  And some of your coding here can be improved.

    I was going to post how to improve some, but it looks like the ASM and CODE tags do not want to work today (well, ASM hasn't for ages but still).

    Nevermind.  Anyway.  Your way of telling people to change the "KillCharacter" routine is to test the reverse gravity and if it's on, branch to a new routine, which is the same as the other bar one line:


    move.w #-$700,y_vel(a0)




    So, why not change the whole routine to something like this:


    KillCharacter:
    tst.w (Debug_placement_mode).w
    bne.s loc_3F972
    clr.b status_secondary(a0)
    move.b #6,routine(a0)
    bsr.w JmpTo_Sonic_ResetOnFloor_Part2
    bset #1,status(a0)
    move.w #-$700,y_vel(a0) ; Apply gravity to Sonic when he dies
    tst.b (Reverse_gravity_flag).w ; WAIT! Is reverse gravity on?
    beq.s + ; It isn't? Branch then and carry on
    neg.w y_vel(a0) ; As reverse gravity is on, reverse the Y velocity
    +
    move.w #0,x_vel(a0)
    move.w #0,inertia(a0)
    move.b #$18,anim(a0)
    bset #7,art_tile(a0)
    move.w #$A3,d0
    cmpi.b #$36,(a2)
    bne.s loc_3F96C
    move.w #$A6,d0

    loc_3F96C:
    jsr (PlaySound).l

    loc_3F972:
    moveq #-1,d0
    rts




    Also, instead of this:



    ObjectMoveAndFall:
    move.w x_vel(a0),d0
    ext.l d0
    lsl.l #8,d0
    add.l d0,x_pos(a0)
    move.w y_vel(a0),d0
    tst.b (Reverse_gravity_flag).w
    bne.s +
    addi.w #$38,y_vel(a0) ; apply gravity
    bra.s ++
    +
    addi.w #-$38,y_vel(a0) ; apply reverse gravity
    +
    ext.l d0
    lsl.l #8,d0
    add.l d0,y_pos(a0)
    rts

     


    Try this:


    move.w x_vel(a0),d0
    ext.l d0
    lsl.l #8,d0
    add.l d0,x_pos(a0)
    move.w y_vel(a0),d0
    addi.w #$38,y_vel(a0) ; apply gravity
    tst.b (Reverse_gravity_flag).w ; WAIT! Is reverse gravity on?
    beq.s + ; It isn't? Branch then and carry on
    subi.w #$70,y_vel(a0) ; As reverse gravity is on, reverse the Y velocity
    +
    ext.l d0
    lsl.l #8,d0
    add.l d0,y_pos(a0)
    rts


    Also, under your "Hurt_Sidekick" routine, you have this:


    bra.s Hurt_Reverse
    rts



    No point in the rts.  That's a waste of space.  If the above line is always going to branch, it will never ever read that rts, rendering it useless.

    Please bear in mind, I was using XenoWhirls' disassembly, so my coding may look slightly different compared to yours.
     
    Last edited by a moderator: Mar 26, 2013
  12. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    Ah...I see what you're saying here. Once the guide is done, that little note at the top can be removed. It may sound a bit confusing, but I am writing this guide in real-time as I port the feature.



    Death Egg - Sonic 4 episode II style =P

    If only we could somehow accomplish that. It's hard enough just doing reverse gravity :p
     
    Last edited by a moderator: Mar 26, 2013
  13. Mike B Berry

    Mike B Berry A grandiose return Member

    Joined:
    Jun 6, 2012
    Messages:
    377
    Location:
    New places, newer motivation
    I've converted this guide over to Xenowhirl, it was pretty easy considering... though there is one step that is not available in both the HG and Xenowhirl disassembly, I assume it is directly from S3K. If so, it isn't working in game at all. I'm greeted with a black screen.


    The step i'm referring to is the main flag setup.
     
    Last edited by a moderator: Mar 26, 2013
  14. StephenUK

    StephenUK Working on a Quackshot disassembly Member

    Joined:
    Aug 5, 2007
    Messages:
    1,026
    I'm locking this topic until you have got it working perfectly and are ready to release a full guide. This subforum is for completed guides, not for half arsed efforts that don't actually work as intended. PM an admin or staff when you're ready to post the full guide and we'll reopen it.
     
Thread Status:
Not open for further replies.