With kernal jsr joystick_get I can get the state of the joystick buttons.
I want to call a subroutine when a button is pressed. After I've called the subroutine there needs to be a timeout, before the next call fires, while the button is being held down.
What would be a good approach to solve this timing?
Single button press joystick (assembly)
Re: Single button press joystick (assembly)
Set a state that ignores subsequent button presses. Then release the state after N frames. Setting the state as a the number of states to ignore the button is the easiest, then dec the state each frame. When it hits 0, the button is enabled again.
-
- Posts: 292
- Joined: Wed Jun 03, 2020 11:33 am
- Location: Kalmar, Sweden
Re: Single button press joystick (assembly)
Is it for use in a program driven by interrupts? In that case, in my games I use this macro repeatedly to create various delays (ca65):
Use like this in you code:
Code: Select all
.macro Timer_Tick counter, limit ;IN: address of counter, limit as immediate value. OUT: .C = 1 if limit reached
inc counter
lda counter
cmp #limit
bne skip1
stz counter
sec
bra skip2
skip1: clc
skip2:
.endmacro
Code: Select all
Timer_Tick delay_timer, FRAME_DELAY
bcs cont
rts
cont:
;whatever you want to do when user presses the button
...
rts
FRAME_DELAY = 60 ;wait one second
delay_timer: .byte 0
Re: Single button press joystick (assembly)
Thanks for your suggestions. If I understand correctly these methods asume that the framerate is somewhat fixed. If (for whatever reason) the x16 performce faster or slower, the timing will be off.
I found RDTIM as a kernal routine with a 1/60th of a second precision. I think I'll give that a go.
I found RDTIM as a kernal routine with a 1/60th of a second precision. I think I'll give that a go.
Re: Single button press joystick (assembly)
The X16 performance could be faster or slower, but the framerate is going to be 60 times a second. It's not how fast frames are generated in a framebuffer GPU, it's the 60Hz of a standard VGA display.
That precision is due to an update that is done once per frame.I found RDTIM as a kernal routine with a 1/60th of a second precision. I think I'll give that a go.
Re: Single button press joystick (assembly)
You can check for a not-pressed (1) to pressed (0) transition with (old_state & !new_state).
In 65c02-speak, that'd be something like this, for example:
The "singlebuttons" bytes now contain the single-shots for each button on the controller. Those ORAs are optional, depending on how the rest of your game loop is structured.
When you have single-shot bytes like this, you can implement an auto-repeat by watching for single-shots and injecting artificial ones with a counter, like this (adding repeats only on d-pad buttons):
In 65c02-speak, that'd be something like this, for example:
Code: Select all
; Prepare old buttons.
LDA buttons1
EOR #$FF
STA oldbuttons1
LDA buttons2
EOR #$FF
STA oldbuttons2
; Get new buttons.
JSR joystick_get
; Byte 1
EOR #$FF
STA buttons1
AND oldbuttons1
ORA singlebuttons1
STA singlebuttons1
; Byte 2
TXA
EOR #$FF
STA buttons2
AND oldbuttons2
ORA singlebuttons2
STA singlebuttons2
When you have single-shot bytes like this, you can implement an auto-repeat by watching for single-shots and injecting artificial ones with a counter, like this (adding repeats only on d-pad buttons):
Code: Select all
LDA buttons1
AND #$0F ;Any directions being held?
BEQ end
LDA singlebuttons1 ;Any natural single-shots?
ORA singlebuttons2
BEQ noReset
LDA #$10 ;Long delay after button press.
STA keyRepeatDelay
noReset:
DEC keyRepeatDelay
BNE end
LDA #$04 ;Reload with repeat rate
STA keyRepeatDelay
LDA buttons1 ;Inject current directions as
AND #$0F ;new single-shots.
ORA singlebuttons1
STA singlebuttons1
end:
; Clear singlebuttons1 before this routine runs again,
; or else the artificial single-shots will be
; misinterpreted as natural ones.