Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.
I found this subroutine in RECCA. Based on when this subroutine is used it calculates the direction from object to player and shifts the result left x times. The part I don't get is from $ECB9 to $ECD3. My best guess is that it is supposed to normalize the values, but still, I don't understand why it is doing things as it is. Like, why subtract #$01 from the high byte, why compare #$FE and why branch to the locations they do after the comparisons.
$EC91
STA result_shift_count
LDA player_pos_y
SEC
SBC obj_pos_y,X
STA object_player_y_distance_low
LDA #$00
SBC #$00
STA object_player_y_distance_high
LDA player_pos_x
SEC
SBC obj_pos_x,X
STA object_player_x_distance_low
LDA #$00
SBC #$00
STA object_player_x_distance_high
ORA object_player_x_distance_low
ORA object_player_y_distance_low
ORA object_player_y_distance_high
BEQ $ECE1
$ECB9
ASL object_player_x_distance_low
ROL object_player_x_distance_high
ASL object_player_y_distance_low
ROL object_player_y_distance_high
LDA object_player_x_distance_high
SEC
SBC #$01
CMP #$FE
BCC $ECD3
LDA object_player_y_distance_high
SEC
SBC #$01
CMP #$FE
BCS $ECB9
$ECD3
ASL object_player_x_distance_low
ROL object_player_x_distance_high
ASL object_player_y_distance_low
ROL object_player_y_distance_high
DEC result_shift_count
BPL $ECD3
LDA #$01
$ECE1
RTS ; ------------------------------------------------
I left the CPU addresses in so you can find it in the subroutine. The subroutine uses "temporary" variables, but I replaced them with more descriptive names to make it easier to read.
Avatar is pixel art of Noah Prime from Astral Chain
Looks to me like it's checking if the distance is within 255 units, positive or negative, after the multiply by 4 (so, 64 units on the original scale). If the high byte were 0, subtracting 1 would give #$FF and the check would pass. If it were #$FF, subtracting 1 would give #$FE and the check would pass. Anything outside that range is further than 255 units and will fail the check.
$EC91
STA result_shift_count
LDA player_pos_y
SEC
SBC obj_pos_y,X
STA object_player_y_distance_low
LDA #$00
SBC #$00
STA object_player_y_distance_high ; yDist = player.y-object.y
LDA player_pos_x
SEC
SBC obj_pos_x,X
STA object_player_x_distance_low
LDA #$00
SBC #$00
STA object_player_x_distance_high ; xDist = player.x-object.x
ORA object_player_x_distance_low ; if xDist == 0
ORA object_player_y_distance_low ; and
ORA object_player_y_distance_high ; yDist == 0
BEQ $ECE1 ; then return 0
$ECB9
ASL object_player_x_distance_low ; xDist *= 2
ROL object_player_x_distance_high
ASL object_player_y_distance_low ; yDist *= 2
ROL object_player_y_distance_high
LDA object_player_x_distance_high ; if xDist
SEC ; >= 256
SBC #$01
CMP #$FE
BCC $ECD3 ; then shift
LDA object_player_y_distance_high ; if yDist
SEC ; < 256
SBC #$01
CMP #$FE
BCS $ECB9 ; then mul again
$ECD3
ASL object_player_x_distance_low ; xDist * scalar
ROL object_player_x_distance_high
ASL object_player_y_distance_low
ROL object_player_y_distance_high ; yDist * scalar
DEC result_shift_count
BPL $ECD3
LDA #$01 ; return 1
$ECE1
RTS
; ------------------------------------------------
but what does that mean?
Well you are taking the distance between both objects and then you doing div two until one of the values is 1 or -1. So effectively you are normalizing the heading vector from the object to the player. ( or what the code actually does is /8 and then mul 2 until one of them crosses becomes +/- 1)
then you multiple the heading vector by a scalar value.
I'm going to guess that RECCA is a shoot-em-up and this is the "fire bullet with speed A towards the player" routine.
I'm assuming this way of normalizing the vector is not accurate, but rather a approximation. I have noticed that bullets fired at player are fired at double speed at certain distances between the player and the enemy that fired it. I'm assuming this is a side effect of the approximation.
Avatar is pixel art of Noah Prime from Astral Chain
yeah very inaccurate. Its just first past 1, so if you have $100 and $0Fe or $100 and $001 it doesn't matter it just first past 1,it just x2 until one of them hits $100 it doesn't pay any attentive to the actual length of both values. Both can hit "over 1" if they are close enough 45 degrees rather than say 0.5, 0.5 which is what you actually want. This is why in a lot of games its faster to move diagonally than forwards.