140 lines
3.3 KiB
ArmAsm
140 lines
3.3 KiB
ArmAsm
|
|
//
|
|
// Official Kernal routine, described in:
|
|
//
|
|
// - [RG64] C64 Programmer's Reference Guide - page 295
|
|
// - [CM64] Compute's Mapping the Commodore 64 - page 220
|
|
//
|
|
// CPU registers that has to be preserved (see [RG64]): none
|
|
//
|
|
|
|
// Variables used:
|
|
// - KEYTAB - keyboard matrix pointer
|
|
// - DELAY - counter for first delay between key repeats
|
|
// - KOUNT - counter for next delays between key repeats
|
|
// - SHFLAG - SHIFT / CTRL / VENDOR keypress status
|
|
// - NDX - number of characters in keyboard buffer
|
|
// - XMAX - maximum size of keyboard buffer
|
|
// - LSTX - matrix coordinate of last pressed key
|
|
// - LSTSHF - previous status of SHFLAG
|
|
// - MODE - flag, whether charset toggle (SHIFT+VENDOR) is allowed
|
|
|
|
|
|
// XXX add Commodore 128 keyboard support
|
|
// XXX add Commodore 65 keybopard support
|
|
// XXX add support for using joystick to move sursor keys
|
|
// XXX prevent joystick port 1 interference
|
|
|
|
#if !CONFIG_SCNKEY_TWW_CTR
|
|
|
|
// Routine takes some ideas from TWW/CTR proposal, see here:
|
|
// - http://codebase64.org/doku.php?id=base:scanning_the_keyboard_the_correct_and_non_kernal_way
|
|
|
|
|
|
SCNKEY:
|
|
|
|
// Prepare for SHFLAG update
|
|
|
|
lda SHFLAG
|
|
sta LSTSHF
|
|
lda #$00
|
|
sta SHFLAG
|
|
|
|
// XXX retrieve ALT and NO_SCRL status for C128/C65 keyboards
|
|
|
|
// Check for any activity
|
|
|
|
lda #$00
|
|
sta CIA1_PRA // connect all the rows
|
|
ldx #$FF
|
|
cpx CIA1_PRB
|
|
beq scnkey_no_keys
|
|
|
|
// Retrieve SHIFT / VENDOR / CTRL status
|
|
// Use .X to detect 2 or more keys pressed (should be $FF now)
|
|
ldy #$03
|
|
scnkey_bucky_loop:
|
|
lda kb_matrix_bucky_confmask, y
|
|
sta CIA1_PRA
|
|
lda kb_matrix_bucky_testmask, y
|
|
and CIA1_PRB
|
|
bne !+ // not pressed
|
|
lda SHFLAG
|
|
ora kb_matrix_bucky_shflag, y
|
|
sta SHFLAG
|
|
!:
|
|
dey
|
|
bpl scnkey_bucky_loop
|
|
|
|
// Set KEYTAB vector
|
|
|
|
jsr scnkey_via_keylog // XXX for some CPUs we have indirect jsr
|
|
|
|
// XXX check if there is space in keyboard buffer
|
|
// XXX check for joystick activity
|
|
|
|
// Scan the keyboard matrix
|
|
|
|
ldy #$07 // XXX adapt for C128 and C65 keyboards
|
|
ldx #$FF // offset in key matrix table, $FF for not found yet
|
|
scnkey_matrix_loop:
|
|
lda kb_matrix_row_keys, y
|
|
sta CIA1_PRA
|
|
lda kb_matrix_bucky_filter, y // filter out bucky keys
|
|
ora CIA1_PRB
|
|
cmp #$FF
|
|
beq scnkey_matrix_loop_next // skip if no key pressed from this row
|
|
cpx #$FF
|
|
bne scnkey_no_keys // clash, more than one key pressed
|
|
// We have at least one key pressed in this row, we need to find which one exactly
|
|
ldx #$07
|
|
scnkey_matrix_loop_inner:
|
|
cmp kb_matrix_row_keys, x
|
|
bne !+ // not this particular key
|
|
txa // now .A contains key offset within a row
|
|
sec
|
|
adc kb_matrix_row_offsets, y // now .A contains key offset from the matrix start
|
|
tax
|
|
jmp scnkey_matrix_loop_next
|
|
!:
|
|
dex
|
|
bpl scnkey_matrix_loop_inner
|
|
bmi scnkey_no_keys // branch always, multiple keys must have been pressed
|
|
scnkey_matrix_loop_next:
|
|
dey
|
|
bpl scnkey_matrix_loop
|
|
|
|
// Scanning complete
|
|
|
|
cpx #$FF
|
|
bne scnkey_got_key
|
|
|
|
// FALLTROUGH
|
|
|
|
scnkey_no_keys:
|
|
|
|
// XXX
|
|
|
|
lda #$40 // XXX adapt value for C128 and C65 keyboards
|
|
sta LSTX
|
|
|
|
rts
|
|
|
|
scnkey_got_key: // .X should now contain the key offset in matrix pointed by KEYTAB
|
|
|
|
// Handle repeat timer
|
|
|
|
.break
|
|
lda KOUNT
|
|
beq !+
|
|
dec KOUNT
|
|
!:
|
|
|
|
// XXX
|
|
rts
|
|
|
|
scnkey_via_keylog:
|
|
jmp (KEYLOG)
|
|
|
|
#endif // no CONFIG_SCNKEY_TWW_CTR
|