Single button press joystick (assembly)

All aspects of programming on the Commander X16.
Post Reply
unartic
Posts: 145
Joined: Sat Oct 28, 2023 3:26 pm

Single button press joystick (assembly)

Post 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?
User avatar
Daedalus
Posts: 229
Joined: Fri Nov 11, 2022 3:03 am

Re: Single button press joystick (assembly)

Post 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.
Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Re: Single button press joystick (assembly)

Post 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
unartic
Posts: 145
Joined: Sat Oct 28, 2023 3:26 pm

Re: Single button press joystick (assembly)

Post 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.
BruceRMcF
Posts: 224
Joined: Sat Jan 07, 2023 10:33 pm

Re: Single button press joystick (assembly)

Post 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.
DragWx
Posts: 345
Joined: Tue Mar 07, 2023 9:07 pm

Re: Single button press joystick (assembly)

Post 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.
Post Reply