aboutsummaryrefslogtreecommitdiff
path: root/timed_getch.s
blob: eaf7ab30746103fa96f609fac48f104004dad94e (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

 .export _timed_getch, _set_jiffy_timer, _agetc, _numgetc
 .export  _yngetc, _lcgetc, _jsleep, _get_item
 .import _cgetc, _cblank, putchar, _rand

 .include "atari.inc"

 .ifdef CART_TARGET
  .segment "HIGHCODE"
 .else
  .code
 .endif

; keyboard and timer functions for taipan.

; sleep for j jiffies.
; extern void __fastcall__ jsleep(unsigned int j);
_jsleep:
 jsr _set_jiffy_timer
jiffy_wait:
 lda CDTMV3
 ora CDTMV3+1
 bne jiffy_wait
 rts

; extern void __fastcall__ set_jiffy_timer(unsigned int jiffies);
_set_jiffy_timer: ; called by jsleep() also.
 sei          ; disable IRQ while setting timer (probably overkill)
 sta CDTMV3
 stx CDTMV3+1
 cli
 rts

; like curses timeout(5000) followed by getch(): sleep until either
; a key is pressed or the timer expires. returns 0 if no key pressed.
; extern char __fastcall__ timed_getch(void);
_timed_getch:
 lda #$2c ; $012c jiffies = 5 sec (NTSC) or 6 sec (PAL)
 ldx #$01
 jsr _set_jiffy_timer

@wait4key:
 lda CDTMV3   ; has timer counted down to 0?
 ora CDTMV3+1
 bne @timer_running
 tax ; timer expired, return(0), A is already 0 here
 rts

@timer_running:
 lda CH   ; no, check for a keypress
          ; ...but don't let the capslock or inverse keys count
			 ; as a keypress, here.

 cmp #$ff ; no key pressed
 beq @wait4key
 and #$3f ; mask shift/control bits
 cmp #$3c ; caps-lock
 beq @wait4key
 cmp #$27 ; inverse (atari) key
 beq @wait4key

 ; user hit a key, handle it. but don't print a cursor.
_agetc_no_cursor:
 jsr _cgetc
 jmp finish_agetc

; _agetc removes the inverse-video bit, and if
; a control key is pressed, it turns it into the non-control version
; (e.g. ^A = lowercase a). Keys that can't be mapped to regular ASCII
; (such as clear, delete, escape) are replaced with a space.
; extern unsigned char agetc(void);
_agetc:
 ; show the user a cursor
 lda #$80 ; inverse space (putchar uses screen codes)
 jsr putchar

 jsr _cgetc ; get ATASCII code of keypress
 pha

 ; get rid of the cursor
 lda #$00 ; space
 jsr putchar
 pla

finish_agetc:
 pha
 ; twitch the random bottle based on the low bit of
 ; the character entered.
 and #$01
 beq @nr
 jsr _rand
@nr:
 pla

 ; special cases
 cmp #$9b   ; enter key, return as-is
 beq ok
 cmp #$9c   ; delete key, return as-is
 beq ok
 cmp #$7e   ; backspace
 beq ok

 ; everything else
 and #$7f   ; strip bit 7 (inverse)
 bne notnull
 lda #$20   ; map null (heart, ctrl-,) to space
notnull:
 cmp #$20
 bcs notcontrol
 ora #$60   ; 1 - 31 map to 96 - 127
notcontrol:
 cmp #$7c ; | (pipe, vertical bar) allowed as-is.
 beq ok
 cmp #$7b ; rest of range $7b - $7f is unmappable.
 bcc ok   ; (remember, $7e, backspace, was handled above)
 lda #$20
ok:
; pha
; ldx #0
; lda FR1+2
; jsr _cursor
; pla
 ldx #0
 rts

; extern unsigned char lcgetc(void);
_lcgetc:
 jsr _agetc
 cmp #'A'
 bcc ok
 cmp #'Z'+1
 bcs ok
 eor #$20   ; lowercase it
 bcc ok

; extern unsigned char numgetc(void);
_numgetc:
 jsr _agetc
 cmp #$9b
 beq ok
 cmp #$7e   ; backspace
 beq ok
 cmp #$61   ; allow 'a' for "all"
 beq ok
 cmp #$6b   ; allow 'k' for 1000
 beq ok
 cmp #$6d   ; allow 'm' for 1 million
 beq ok
 cmp #$9c   ; shift-del
 beq ok
 cmp #'0'
 bcc _numgetc
 cmp #'9'+1
 bcc ok
 bcs _numgetc

; extern unsigned char __fastcall__ yngetc(char dflt);
_yngetc:
 sta FR0 ; stash default arg
 jsr _lcgetc
 cmp #'y'  ; return y or n immediately
 beq ok
 cmp #'n'
 beq ok
 lda FR0     ; otherwise, check for default arg
 beq _yngetc ; no default, get another keypress
 rts         ; else return the default

; extern unsigned char get_item(unsigned char allow_all);
_get_item:
 sta FR0 ; stash arg
@getkey:
 jsr _lcgetc ; switch(lcgetc()) {
 ldx #0
 cmp #'o'
 beq @gi_done ; case 'o': return 0;
 inx
 cmp #'s'
 beq @gi_done ; case 's': return 1;
 inx
 cmp #'a'
 beq @gi_done ; case 'a': return 2;
 inx
 cmp #'g'
 beq @gi_done ; case 'g': return 3;
 ldy FR0
 beq @getkey ; if allow_all is false, get another key
 inx
 cmp #'*'    ; case '*': return 4;
 bne @getkey ; if none of the above, get another key
@gi_done:
 txa
 rts