restructure keyboardhandler example due to X register bug, discussed in #94

This commit is contained in:
Irmen de Jong 2023-01-24 01:30:57 +01:00
parent 8cda8a727c
commit 74b69e191e

View File

@ -10,56 +10,85 @@ main {
sys.set_irqd() sys.set_irqd()
uword old_keyhdl = cx16.KEYHDL uword old_keyhdl = cx16.KEYHDL
cx16.KEYHDL = &main.keyboard_scancode_handler.asm_shim cx16.KEYHDL = &keyboard_scancode_handler
sys.clear_irqd() sys.clear_irqd()
bool escape_pressed bool escape_pressed
while not escape_pressed { while not escape_pressed {
; just sit here handle_keyboard_event()
} }
sys.set_irqd() sys.set_irqd()
cx16.KEYHDL = old_keyhdl cx16.KEYHDL = old_keyhdl
sys.clear_irqd() sys.clear_irqd()
} }
sub keyboard_scancode_handler(ubyte prefix, ubyte scancode, bool updown) -> bool { ; Keyboard handler communication variables.
txt.print_ubhex(prefix, true) ; these need to be in block scope instead of in a subroutine,
; so that they won't get overwritten with initialization values every time.
; The assembly keyboard handler will set these, prog8 will read them.
bool @shared keyhdl_event ; is there a keyboard event to handle?
ubyte @shared keyhdl_prefix
ubyte @shared keyhdl_scancode
ubyte @shared keyhdl_updown
sub handle_keyboard_event() {
; Potentially handle keyboard event.
; Note that we do this from the program's main loop instead of
; the actual keyboard handler routine itself.
; The reason for this is documented below in the handler assembly routine.
if not keyhdl_event
return
keyhdl_event = false
txt.print_ubhex(keyhdl_prefix, true)
txt.chrout(':') txt.chrout(':')
txt.print_ubhex(scancode, true) txt.print_ubhex(keyhdl_scancode, true)
txt.spc() txt.spc()
if updown if keyhdl_updown
txt.chrout('u') txt.chrout('u')
else else
txt.chrout('d') txt.chrout('d')
txt.nl() txt.nl()
if prefix==0 and scancode==119 and updown { if keyhdl_prefix==0 and keyhdl_scancode==119 and keyhdl_updown {
; escape was pressed! exit back to basic ; escape was pressed! exit back to basic
main.start.escape_pressed = true main.start.escape_pressed = true
} }
return true ; true = consume key event, false = continue processing it }
asmsub keyboard_scancode_handler() {
; NOTE that the keyboard handler is an asm subroutine.
; Unfortunately is it not possible to use prog8 code or calls here,
; because the X register gets overwritten here (to store the prefix byte)
; and prog8 uses the X register internally (for the evaluation stack).
; So it is unsafe to call prog8 code from here because the evaluation stack pointer
; will be invalid which produces undefined results.
; So, instead, we store the various keyboard event bytes and signal
; the main prog8 program that a keyboard event has occurred.
; It then processes it independently from the assembly code here.
;
; Unfortunately this also means you cannot decide from that prog8 code
; if the keyboard press should be consumed/ignored or put into the keyboard queue
; (this is controlled by returning 0 or 1 in register A here)
asm_shim:
%asm {{ %asm {{
php php
pha pha
phx phx
stz updown stz keyhdl_updown
bcc + bcc +
inc updown inc keyhdl_updown
+ stx prefix + stx keyhdl_prefix
sta scancode sta keyhdl_scancode
jsr keyboard_scancode_handler lda #1
beq + sta keyhdl_event
; we can do additional stuff here and decide if we want to
; consume the key event or not (A=0 or A!=0)
plx plx
pla pla
lda #0 ;By setting A=0 we will consume this key event lda #0 ;By setting A=0 we will remove this key event for now
tax tax
plp plp
rts rts
+ plx
pla ; leave A untouched, continue processing
plp
rts
}} }}
} }
} }