ASM to Sega Genesis Platform

All about assembly programming in the Sega Genesis console.


    Homing Attack in Sonic 1 - Step 4 - Auto-Chasing the Object and Time Limit

    Share

    OuricoDoido
    Admin

    Mensagens : 46
    Data de inscrição : 2011-01-09
    Current Project : Sonic Open Source Project

    Homing Attack in Sonic 1 - Step 4 - Auto-Chasing the Object and Time Limit

    Post  OuricoDoido on Tue Jan 25, 2011 6:54 pm

    To the Sonic chase the enemies, we must use some RAM's value, so you can set and check if Sonic is chasing an object.

    To the Sonic auto-chase the object, you need to create a jump (to skip pieces of code, as the check of button pessed), that every frame, calculate and execute the Homing Attack, if Sonic is chasing some object.
    And in our case, we will create a counter to the chase have a time limit.

    Note: Our counter's flag (RAM's address) is the same of our Homing Attack's flag.

    Below these lines:
    Code:
          cmp.l  #16384,d1      ; is distance of Sonic, greater than or equal 128 pixels of the object? (128^2=16384 // $80^2=$4000)
          bge.s  HA_nextobject   ; if yes, don't execute the homing attack
    add this:
    Code:
          move.b   #30,($FFFFFFD1).w   ; number of frames Sonic can chasing the object
          move.l   a1,($FFFFFFD2).w   ; save the object address that Sonic is chasing
    Why save the object's address that Sonic is chasing?
    Because the next time that we calculate the Homing Attack (after the jump), we need to know the object's x and y position that Sonic is chasing - we need know which object the Sonic is chasing, to obtain the object's x and y position.


    Now, below the HA_Move, add this code of four lines, which i will explain line by line:
    Code:
          movea.l   ($FFFFFFD2).w,a1   ; load the object address that Sonic is chasing
          subi.b   #1,($FFFFFFD1).w   ; sub 1 of frames counter
          tst.b   ($FFFFFFD1).w      ; the time to the Sonic chasing some object is over?
          beq.w   Sonic_HA_rts      ; if yes, don't make the Homing Attack

    The 1st line - Loads the RAM address of the object that Sonic is chasing, you need load the object's address in RAM to variable a1, in order to can make "the calculation of distance", which is the code below:
    Code:
    ; Recalculating the distance between the Sonic and the object (d1 = x distance / d2 = y distance)
          move.w  8(a1),d1   ; move the object x-position to d1
          move.w  $C(a1),d2   ; move the object y-position to d2
          sub.w  8(a0),d1   ; sub sonic x-position of object x-position
          sub.w  $C(a0),d2   ; sub sonic y-position of object y-position

    The 2nd line - Subtracts 1 of frames counter, so that when get 0, Sonic stop chasing the object, this explains the 3rd and 4th line of the code:
    Code:
          tst.b   ($FFFFFFD1).w      ; the time to the Sonic chasing some object is over?
          beq.w   Sonic_HA_rts      ; if yes, don't make the Homing Attack


    Now we need to make the jump, below Sonic_Homingattack add these two lines:
    Code:
          tst.b   ($FFFFFFD1).w      ; is Sonic chasing some object?
          bne.w   HA_Move            ; if yes, chase him
    These two lines serve to verify that the Sonic are chasing some object, if is chasing go for HA_Move routine, making Sonic go against the object, but if is not chasing, continues with the Homing Attack normally.


    BUGS AND OTHER CODE MODIFICATIONS
    Everything down from here and the Step 5, 6 and 7 is bug corrections and others modifications.


    Bug: "Auto Homing Attack" after any jump

    After doing all these modifications, if you compiled, you may have noticed an error after use the Homing Attack:
    • touch the ground
    • destroy a monitor (if you will do "bounce Sonic upwards in Homing Attack", fix it in Step 6)
    • destroy a enemy (if you will do "bounce Sonic upwards in Homing Attack", fix it in Step 6)
    • collect a giant ring
    • hit a boss (this will be fixed in Step 5)


    After any of these events, if you try jump, Sonic makes the Homing Attack,
    or in case of monitor, enemy and boss, the Sonic is stopped for a time in air until the Homing Attack's time is over.

    Why?
    Because the Homing Attack is enabled (not was reset or set to 0)
    The variable that determines whether the Homing Attack is activated is this below:
    Code:
          $FFFFFFD1      ; number of frames Sonic can chasing the object
    To fix this, we need reset this value.


    How to: Fix the bug when "touch the ground"

    Search for Sonic_ResetOnFloor (values that are reset when Sonic touches the ground) and you will see this:
    Code:
    Sonic_ResetOnFloor:         ; XREF: PlatformObject; et al
          btst   #4,$22(a0)
          beq.s   loc_137AE
          nop   
          nop   
          nop   

    loc_137AE:
          bclr   #5,$22(a0)
          bclr   #1,$22(a0)
          bclr   #4,$22(a0)
          btst   #2,$22(a0)
          beq.s   loc_137E4
          bclr   #2,$22(a0)
          move.b   #$13,$16(a0)
          move.b   #9,$17(a0)
          move.b   #0,$1C(a0)   ; use running/walking animation
          subq.w   #5,$C(a0)

    loc_137E4:
          move.b   #0,$3C(a0)
          move.w   #0,($FFFFF7D0).w
          rts   
    ; End of function Sonic_ResetOnFloor
    below loc_137AE, add this line:
    Code:
          clr.b   ($FFFFFFD1).w    ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
    Now when Sonic touches the ground, the Homing Attack will be canceled.


    How to: Fix the bug when "destroy a monitor"

    If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
    Search for Touch_Monitor (the code that says what should happen if Sonic touches a monitor) and you'll find this:
    Code:
    Touch_Monitor:
          tst.w   $12(a0)      ; is Sonic moving upwards?
          bpl.s   loc_1AF1E   ; if not, branch
          move.w   $C(a0),d0
          subi.w   #$10,d0
          cmp.w   $C(a1),d0
          bcs.s   locret_1AF2E
          neg.w   $12(a0)      ; reverse Sonic's y-motion
          move.w   #-$180,$12(a1)
          tst.b   $25(a1)
          bne.s   locret_1AF2E
          addq.b   #4,$25(a1)   ; advance the monitor's routine counter
          rts   
    ; ===========================================================================

    loc_1AF1E:
          cmpi.b   #2,$1C(a0)   ; is Sonic rolling/jumping?
          bne.s   locret_1AF2E
          neg.w   $12(a0)      ; reverse Sonic's y-motion
          addq.b   #2,$24(a1)   ; advance the monitor's routine counter

    locret_1AF2E:
          rts   
    Below the first two lines of the routine loc_1AF1E:
    Code:
          cmpi.b   #2,$1C(a0)   ; is Sonic rolling/jumping?
          bne.s   locret_1AF2E
    Add this line:
    Code:
          clr.b   ($FFFFFFD1).w    ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
    Now, if the Sonic hit the monitor with the jumping animation, the Homing Attack is canceled (the Homing Attack is done with the Sonic's jumping animation)


    How to: Fix the bug when "destroy a enemy"

    If you will do "bounce Sonic upwards in Homing Attack", this will be fixed in Step 6, but if you do not want this, continue normally.
    Search for Touch_KillEnemy (the code that says what should happen if Sonic destroy a enemy) and you'll find this:
    Code:
    Touch_KillEnemy:
          bset   #7,$22(a1)
          moveq   #0,d0
          move.w   ($FFFFF7D0).w,d0
          addq.w   #2,($FFFFF7D0).w ; add 2 to item bonus counter
          cmpi.w   #6,d0
          bcs.s   loc_1AF82
          moveq   #6,d0

    loc_1AF82:
          move.w   d0,$3E(a1)
          move.w   Enemy_Points(pc,d0.w),d0
          cmpi.w   #$20,($FFFFF7D0).w ; have 16 enemies been destroyed?
          bcs.s   loc_1AF9C   ; if not, branch
          move.w   #1000,d0   ; fix bonus to 10000
          move.w   #$A,$3E(a1)

    loc_1AF9C:
          bsr.w   AddPoints
          move.b   #$27,0(a1)   ; change object   to points
          move.b   #0,$24(a1)
          tst.w   $12(a0)
          bmi.s   loc_1AFC2
          move.w   $C(a0),d0
          cmp.w   $C(a1),d0
          bcc.s   loc_1AFCA
          neg.w   $12(a0)
          rts   
    Below this code:
    Code:
    loc_1AF9C:
          bsr.w   AddPoints
    Add this line:
    Code:
          clr.b   ($FFFFFFD1).w    ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
    Now, when Sonic destroy an enemy, the Homing Attack will be canceled.


    How to: Fix the bug when "collect a giant ring"

    When you collect a giant ring with the Homing Attack, the variable that shows whether Sonic is chasing someone is not reset, after you play a special stage, you can see that it's the same bug as in the previous three items:
    • touch the ground
    • destroy a monitor
    • destroy a enemy


    How to fix?
    Search for Obj4B_Collect (subroutine that shows what must happen when Sonic get a giant ring) and below these lines:
    Code:
    Obj4B_Collect:            ; XREF: Obj4B_Index
          subq.b   #2,$24(a0)
          move.b   #0,$20(a0)
          bsr.w   SingleObjLoad
          bne.w   Obj4B_PlaySnd
    Add this:
    Code:
          clr.b   ($FFFFFFD1).w    ; cancel the Homing Attack, clearing the number of frames Sonic can chasing the object
    avatar
    Green Snake

    Mensagens : 2093
    Data de inscrição : 2012-04-07
    Localização : I do not even know
    Current Project : nope

    Re: Homing Attack in Sonic 1 - Step 4 - Auto-Chasing the Object and Time Limit

    Post  Green Snake on Sun May 19, 2013 11:39 am


      Current date/time is Wed Jun 28, 2017 3:04 pm