aboutsummaryrefslogtreecommitdiff
path: root/timed_getch.s
blob: fdb0dc033915b215b4bab856890240857b22a74c (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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

 .export _timed_getch, _set_jiffy_timer, _agetc, _numgetc
 .export  _yngetc, _lcgetc, _jsleep, _get_item_port, _get_item_battle, _tjsleep
 .import _cgetc, _cblank, putchar, _rand, _turbo

 .include "atari.inc"

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

; keyboard and timer functions for taipan.

; sleep for j jiffies, unless _turbo is set.
; extern void __fastcall__ tjsleep(unsigned int j);
_tjsleep:
 sta FR0+4
 lda _turbo
 bne jret
 lda FR0+4

; 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
jret:
 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

 .ifdef GAME_HELP
   .import _print_game_help
 cmp #'?'
 bne notquestion
 jmp _print_game_help
notquestion:
 .endif

 ; 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
 ora #$80 ; show user the default (or a regular cursor if none)
 and #$bf ; (uppercase)
 jsr putchar
 jsr _agetc_no_cursor
 ora #$20 ; lowercase
 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_port(void)
; return 0-3 for opium, silk, arms, general.
; return 5 for Enter key (nothing chosen)
_get_item_port:
 lda #4
 .byte $2c

; extern unsigned char get_item_battle(void)
; return 0-4 for opium, silk, arms, general, all.
_get_item_battle:
 lda #5
 sta FR0
@get_loop:
 jsr get_item
 cmp FR0
 beq @get_loop
 rts


get_item:
@getkey:
 jsr _lcgetc ; switch(lcgetc()) {
 sta FR0+1

;;; 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;

 ldx #5
@giloop:
 lda items_tbl,x
 cmp FR0+1
 beq @gi_done
 dex
 bpl @giloop
 bmi @getkey
@gi_done:
 txa
 rts

.rodata
 items_tbl: .byte "osag*",$9b