keep track only of when the button is pressed and not when it's being held down. You can do this by recording a "previous button state" variable and comparing it to the current button state.
Assuming each button is represented as a single bit in a byte:
Code:
LDA current_buttons
STA previous_buttons
JSR read_joy_data_from_4016_and_put_in_current_buttons
LDA previous_buttons
EOR #$FF
AND current_buttons
STA buttons_just_pressed
What I'm doing here is ANDing the current buttons with the inverse of the previous buttons... so that buttons which were not previously down will be masked out.
To visualize this... say that the player just pressed the left button (so previous_buttons=$00 and current_buttons=$40)
Code:
LDA previous_buttons ; $00
EOR #$FF ; $FF
AND current_buttons ; $40
Now let's say that left is being held down (so previous_buttons=$40 and current_buttons=$40)
Code:
LDA previous_buttons ; $40
EOR #$FF ; $BF
AND current_buttons ; $00
even though current_buttons is $40, the $40 is being dropped by the AND operation.
-- edit: changed around that first code segment to make it easier to understand --
-- edit again --
and because I'm bored... here's a sample routine to read joy data and put it in current_buttons:
Code:
read_joy_data_from_4016_and_put_in_current_buttons:
LDX #$09
STX $4016 ; set strobe (only bit 0 significant)
DEX
STX $4016 ; clear strobe X now=8
: LDA $4016 ; get key state
LSR A ; move button state into C flag
ROR current_buttons ; roll C into current_buttons var
DEX
BNE :- ; rinse and repeat 8 times -- for each button
RTS