Page 1 of 1
Single button press joystick (assembly)
Posted: Tue Nov 28, 2023 10:12 am
by unartic
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?
Re: Single button press joystick (assembly)
Posted: Tue Nov 28, 2023 2:00 pm
by Daedalus
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.
Re: Single button press joystick (assembly)
Posted: Tue Nov 28, 2023 3:01 pm
by Johan Kårlin
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):
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
Use like this in you code:
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)
Posted: Tue Nov 28, 2023 5:05 pm
by unartic
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.
Re: Single button press joystick (assembly)
Posted: Tue Nov 28, 2023 6:36 pm
by BruceRMcF
unartic wrote: ↑Tue Nov 28, 2023 5:05 pm 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.
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.
I found RDTIM as a kernal routine with a 1/60th of a second precision. I think I'll give that a go.
That precision is due to an update that is done once per frame.
Re: Single button press joystick (assembly)
Posted: Wed Nov 29, 2023 4:17 am
by DragWx
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:
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
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):
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.