Creating the Homing Attack
To add this skill to Sonic, you need go to Obj01_MdJump2 in sonic1.asm, and add this line:
Go below Sonic_Roll subroutine (below this text: ; End of function Sonic_Roll) , and Add this (a normal skill code):
For other buttons, change the #$40 to:
Doing the Homing Attack work
Now, we start with main homing attack command, to move the Sonic in enemy direction.
Between these lines:
Add this:
In this code, the Sonic is going vs any object (rocks, bridge, spikes, .....)
I will explain this code by parts (the part 3, 4 and 5 have already been explained in Step 0.)
Part 1:
Why this address?
Because in Sonic 1, $FFFFD800 address, where is located "the first level object".
This code is completed by the 2nd part, to understand this part, read the 2nd part.
Part 2:
Here is the difference between the basic Homing Attack and the Pinball Bumper, in Pinball Bumper the two objects already have determined (the Sonic and own Pinball Bumper as you saw in Step 0),we already know the Pinball Bumper's RAM address (since the calculation is done within the object's subroutines, a0 being the address) and the Sonic's address in RAM is always fixed ($FFFFD000), no needing find the Sonic in RAM.
But in the Homing Attack, Sonic can attack any object, which in fact is not fixed in RAM, according the objects are being erased in the RAM (when the Sonic destroy him for example), new objects that will be loaded, will earn a RAM position, which may be or not, of the deleted object.
Knowing that the positions of objects in RAM are not fixed, we will be forced to find them in RAM, this way the Homing Attack is not limited to only one object.
but if it exists, go to HA_calcdistance subroutine to calculate the distance, angle, sine and cosine .... and execute the Homing Attack.
Now an explanation line by line:
1st - each object has a size of $40 bytes, so "adda.w #$40, a1", to skip $40 bytes in a1, going to the next object.
2nd - "level object variable space" ends at address $FFFFF000, so "cmpa.w #$F000, a1", compares a1 with address where ends "level object variable space".
3rd - The "blt.s HA_enemylist" is if the RAM position that is in a1 is less than the address where ends "level object variable space", keep searching for an object, returning to the enemy list.
Part 3:
Part 4:
Part 5:
This calculation serves to increase the sine and cosine's value that are very low, as explained in Step 0.
And after increase, set the sine at Sonic's y-velocity and set the cosine at Sonic's x-velocity.
To add this skill to Sonic, you need go to Obj01_MdJump2 in sonic1.asm, and add this line:
- Code:
bsr.w Sonic_Homingattack
- Code:
Obj01_MdJump2: ; XREF: Obj01_Modes
bsr.w Sonic_Homingattack
bsr.w Sonic_JumpHeight
bsr.w Sonic_ChgJumpDir
bsr.w Sonic_LevelBound
jsr ObjectFall
btst #6,$22(a0)
beq.s loc_12EA6
subi.w #$28,$12(a0)
Go below Sonic_Roll subroutine (below this text: ; End of function Sonic_Roll) , and Add this (a normal skill code):
- Code:
; ---------------------------------------------------------------------------
; Subroutine Sonic_Homingattack
; ---------------------------------------------------------------------------
; ||||||||||||||| S U B R O U T I N E |||||||||||||||||||||||||||||||||||||||
Sonic_Homingattack:
move.b ($FFFFF603).w,d1 ; read controller
andi.b #$40,d1 ; is A pressed?
beq.w Sonic_HA_rts ; if not, branch
Sonic_HA_rts:
rts ; return
; Command of Homingattack end here
For other buttons, change the #$40 to:
- Code:
A = #$40
B = #$10
C = #$20
Start = #$80
Up = #1
Down = #2
Left = #4
Right = #8
Doing the Homing Attack work
Now, we start with main homing attack command, to move the Sonic in enemy direction.
Between these lines:
- Code:
beq.w Sonic_HA_rts ; if not, branch
----->>>>>> HERE <<<<<<-----
Sonic_HA_rts:
Add this:
- Code:
lea ($FFFFD800).w,a1 ; start at the first level object RAM
; ---------------------------------------------------------------------------
HA_enemylist:
tst.b (a1) ; is a Null object
bne.s HA_calcdistance ; if not, branch
HA_nextobject:
adda.w #$40,a1 ; jump to next object RAM entry
cmpa.w #$F000,a1 ; already tested all object RAM entry?
blt.s HA_enemylist ; if not, return to enemy list
rts
; ---------------------------------------------------------------------------
HA_calcdistance: ; distance calculator
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
; ---------------------------------------------------------------------------
HA_Move:
jsr (CalcAngle).l ; calculates the angle
jsr (CalcSine).l ; calculates the sine and the cosine
muls.w #$C,d1 ; multiply cosine by $C
move.w d1,$10(a0) ; move d1 to X-velocity
muls.w #$C,d0 ; multiply sine by $C
move.w d0,$12(a0) ; move d0 to Y-velocity
In this code, the Sonic is going vs any object (rocks, bridge, spikes, .....)
I will explain this code by parts (the part 3, 4 and 5 have already been explained in Step 0.)
Part 1:
- Code:
lea ($FFFFD800).w,a1 ; start at the first level object RAM
Why this address?
Because in Sonic 1, $FFFFD800 address, where is located "the first level object".
This code is completed by the 2nd part, to understand this part, read the 2nd part.
Part 2:
- Code:
HA_enemylist:
tst.b (a1) ; is a Null object
bne.s HA_calcdistance ; if not, branch
HA_nextobject:
adda.w #$40,a1 ; jump to next object RAM entry
cmpa.w #$F000,a1 ; already tested all object RAM entry?
blt.s HA_enemylist ; if not, return to enemy list
rts
Here is the difference between the basic Homing Attack and the Pinball Bumper, in Pinball Bumper the two objects already have determined (the Sonic and own Pinball Bumper as you saw in Step 0),we already know the Pinball Bumper's RAM address (since the calculation is done within the object's subroutines, a0 being the address) and the Sonic's address in RAM is always fixed ($FFFFD000), no needing find the Sonic in RAM.
But in the Homing Attack, Sonic can attack any object, which in fact is not fixed in RAM, according the objects are being erased in the RAM (when the Sonic destroy him for example), new objects that will be loaded, will earn a RAM position, which may be or not, of the deleted object.
Knowing that the positions of objects in RAM are not fixed, we will be forced to find them in RAM, this way the Homing Attack is not limited to only one object.
- Code:
tst.b (a1) ; is a Null object
bne.s HA_calcdistance ; if not, branch
but if it exists, go to HA_calcdistance subroutine to calculate the distance, angle, sine and cosine .... and execute the Homing Attack.
- Code:
adda.w #$40,a1 ; jump to next object RAM entry
cmpa.w #$F000,a1 ; already tested all object RAM entry?
blt.s HA_enemylist ; if not, return to enemy list
rts
Now an explanation line by line:
1st - each object has a size of $40 bytes, so "adda.w #$40, a1", to skip $40 bytes in a1, going to the next object.
2nd - "level object variable space" ends at address $FFFFF000, so "cmpa.w #$F000, a1", compares a1 with address where ends "level object variable space".
3rd - The "blt.s HA_enemylist" is if the RAM position that is in a1 is less than the address where ends "level object variable space", keep searching for an object, returning to the enemy list.
Part 3:
- Code:
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
Part 4:
- Code:
jsr (CalcAngle).l ; calculates the angle
jsr (CalcSine).l ; calculates the sine and the cosine
Part 5:
- Code:
muls.w #$C,d1 ; multiply cosine by $C
move.w d1,$10(a0) ; move d1 to X-velocity
muls.w #$C,d0 ; multiply sine by $C
move.w d0,$12(a0) ; move d0 to Y-velocity
This calculation serves to increase the sine and cosine's value that are very low, as explained in Step 0.
And after increase, set the sine at Sonic's y-velocity and set the cosine at Sonic's x-velocity.