aboutsummaryrefslogtreecommitdiff
path: root/src/kgetc.s
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2026-03-25 03:08:11 -0400
committerB. Watson <urchlay@slackware.uk>2026-03-25 03:08:11 -0400
commitb74d292847b22cf282ff8ae7d1b51df34176ce4d (patch)
tree4717814a5390d1672840c2c417ebb4d9606480d8 /src/kgetc.s
parent8f19c016edd9f258c1b39eb44647c685b245f2fc (diff)
downloadfujinet-chat-b74d292847b22cf282ff8ae7d1b51df34176ce4d.tar.gz
Banish cgetc(), and all its annoyances. Much more flexible and precise keyboard control, see keytab.[ch] and kgetc.[ch]
Diffstat (limited to 'src/kgetc.s')
-rw-r--r--src/kgetc.s125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/kgetc.s b/src/kgetc.s
new file mode 100644
index 0000000..c11cb6d
--- /dev/null
+++ b/src/kgetc.s
@@ -0,0 +1,125 @@
+; kgetc() is a replacement for cc65's cgetc(). It does *not* call the
+; OS's K: "get one byte" routine to decode keycodes into (AT)ASCII. It
+; *does* support all 255 keycodes, meaning ctrl+shift combos work.
+
+; kgetc() actually does call the OS K: handler to produce a keyclick, but
+; it does so with a fixed keycode (12, the Return key) and throws away
+; the result. This means we can turn off the keyclick even on an 800.
+; The OS NOCLIK location is used on the 800, too.
+
+; There is no blocking for another keystroke, if a key like Escape or
+; Inverse is pressed. The ctrl-1 keystroke is detected, even though
+; the OS "pre-empts" it (we never see $b1 in CH).
+
+; There is no inverse video mode! INVFLG is never set, and is ignored.
+; There is no Control-lock either, although Caps-lock exists.
+
+; Unlike cgetc(), kgetc() doesn't need to be able to return 0 as a valid
+; character. So instead, 0 is used to mean "ignore keystroke".
+
+; Since inverse numbers can't be returned, I've reused their ATASCII codes
+; for 'switch window' with ctrl-1 through 7.
+
+; kgetc() blocks if no key has been pressed when it's called. to do
+; non-blocking reads:
+; if(keypress())
+; c = kgetc();
+; /* c is 0 if either no key or a non-ATASCII keystroke was pressed,
+; e.g. caps lock or an unused ctrl-shift-letter. */
+
+ .include "atari.inc"
+ .export _kgetc, _keypress
+ .import _keytab
+
+ XCH_CAPS = $8a ; must agree with keytab.h
+
+_keypress:
+ ldx CH
+ cpx #$ff
+ bne ret1 ; if CH != $ff, a key is pressed...
+ ldx SSFLAG
+ bne ret1 ; if SSFLAG != 0, a key is pressed...
+ ldx HELPFG
+ bne ret1 ; if HELPFG != 0, a key (Help) is pressed...
+ txa ; return(0);
+ .byte $2c ; BIT ABS, skip LDA imm below
+ret1:
+ lda #1
+ rts
+
+_kgetc:
+ ldx HELPFG
+ beq read_ch ; Help key pressed?
+ lda #0
+ sta HELPFG ; yes, clear it
+ ldx #$54 ; 1200XL Shift-F4 keycode
+ bne decode
+
+read_ch:
+ ldx CH
+ cpx #$ff
+ bne decode
+ ldx SSFLAG
+ beq read_ch
+ lda #0
+ sta SSFLAG
+ ldx #$9f ; real Ctrl-1 keycode
+
+decode:
+ lda _keytab,x
+ beq done ; 0 in the table means ignore the keystroke (not even a click)
+
+ cmp #XCH_CAPS
+ bne gotkey
+
+ lda SHFLOK ; caps was pressed. we use SHFLOK different from how the OS does.
+ eor #$20
+ sta SHFLOK
+ lda #0
+ beq click_and_done
+
+gotkey: ; ATASCII code in A here, don't overwrite
+ cmp #'z'+1 ; only apply caps lock to a-z
+ bcs noshf
+ cmp #'a'
+ bcc noshf
+ sbc SHFLOK
+noshf:
+ ldx NOCLIK
+ bne done ; obey the XL OS's keyclick disable flag, even on an 800
+
+ ; sound the keyclick (let the OS do it)
+click_and_done:
+ pha
+ jsr keyclick
+ pla
+
+done:
+ ldx #$ff
+ stx CH
+ rts
+
+keyclick:
+ lda NOCLIK
+ bne return ; disabled
+ lda #0
+ sta SSFLAG
+ lda #12 ; EOL (could be any regular key but we need 12 below)
+ sta CH ; fall thru to cgetc...
+
+; ripped from the cc65 lib src, and modified.
+; original code by Christian Groessler, November-2002.
+;_cgetc:
+ ;lda #12 ; already in A
+ sta ICAX1Z ; fix problems with direct call to KEYBDV
+ jsr callit
+return:
+ ;ldx #0
+ rts
+
+callit:
+ lda KEYBDV+5
+ pha
+ lda KEYBDV+4
+ pha
+ rts