aboutsummaryrefslogtreecommitdiff
path: root/src/kgetc.s
blob: c11cb6da80f99b26208844f535dbe26bf890033c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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