-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathprint.asm
383 lines (309 loc) · 6.39 KB
/
print.asm
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
; print.asm
; Printing library from Teletextr
_MINIMAL_PRINT = TRUE
.beeb_print_start
IF _MINIMAL_PRINT = FALSE
.print_temp EQUB 0
; print given string with one argument value supplied in A
; preserves all registers
MACRO MPRINT stringaddr
sta print_temp:txa:pha:tya:pha
ldx #LO(stringaddr)
ldy #HI(stringaddr)
lda print_temp
jsr print
pla:tay:pla:tax:lda print_temp
ENDMACRO
MACRO MPRINTMEM stringaddr, bufferaddr
sta print_temp:txa:pha:tya:pha
ldx #LO(bufferaddr)
ldy #HI(bufferaddr)
jsr print_set_output_buffer
ldx #LO(stringaddr)
ldy #HI(stringaddr)
lda print_temp
jsr print
jsr print_set_output_os
pla:tay:pla:tax:lda print_temp
ENDMACRO
; Select OSWRCH as the output stream
.print_set_output_os
{
lda #LO(oswrch)
sta print_char+1
lda #HI(oswrch)
sta print_char+2
rts
}
; Select a memory buffer as the output stream
; X,Y is the output buffer address LSB/MSB
.print_set_output_buffer
{
lda #LO(render_char)
sta print_char+1
lda #HI(render_char)
sta print_char+2
stx render_char+1
sty render_char+2
rts
}
; X/Y address of ZT string to print
; Strings may contain embedded %a which is replaced by value of A
; Strings may contain embedded %w which must be followed by a 16-bit address containing the 16-bit word value to be printed
; Strings may contain %b which must be followed by a 16-bit address containing the 8-bit value to be printed
; Strings may contain %v which must be followed by a 16-bit number to be printed
; Strings may contain %% to print a % character
;
; eg.
; EQUS "text %a", 0
; EQUS "memory address value is %w", memory_address_lsb, memory_address_msb, ".", 0
.print
{
stx print_fetch_char+1
sty print_fetch_char+2
tay
.loop
jsr print_fetch_char
cmp #0
bne continue
rts
.continue
cmp #'%'
beq check_arg
jsr print_char
jmp loop
.check_arg
jsr print_fetch_char
cmp #'%'
bne check_arg_h
jsr print_char
jmp loop
.check_arg_h
cmp #'h'
bne check_arg_v
; todo
jmp loop
.hex2ascii EQUS "0123456789ABCDEF"
.check_arg_v
cmp #'v'
bne check_arg_a
jsr print_fetch_char
sta binary_in+0
jsr print_fetch_char
sta binary_in+1
jsr bin2bcd16
jmp output_ascii
jmp loop
.check_arg_a
cmp #'a'
bne check_arg_b
; single byte argument
; convert binary number to decimal
tya
jsr bin2bcd8
jmp output_ascii
.check_arg_b
cmp #'b'
bne check_arg_w
; word address argument
; convert binary number to decimal
jsr print_fetch_char
sta arg_addr8+1
jsr print_fetch_char
sta arg_addr8+2
; copy 8-bit value stored at word address cont
.arg_addr8
lda &FFFF
jsr bin2bcd8
jmp output_ascii
.check_arg_w
cmp #'w'
bne loop ; unknown so ignore and continue
; word address argument
; convert binary number to decimal
jsr print_fetch_char
sta arg_addr16+1
jsr print_fetch_char
sta arg_addr16+2
; copy 16-bit value stored at word address cont
ldx #0
.arg_addr16
lda &FFFF,x
sta binary_in,x
inx
cpx #2
bne arg_addr16
jsr bin2bcd16
; 16 bit bcd_out result
; 16 bit value generates max 5 decimal chars
; falls through to output_ascii
.output_ascii
; 16 bit bcd_out result
; 8 bit value generates max 3 decimal chars
jsr bcd2ascii
ldx #0
.ascii_loop
lda ascii_out,x
beq ascii_done
jsr print_char
inx
bne ascii_loop
.ascii_done
jmp loop
}
.binary_in EQUW 0 ; value to convert (LSB first) 65536
.bcd_out SKIP 3 ; bcd_out output, input of 0xffff will become $36, $55, $06
.ascii_out SKIP 7 ; zero terminated ascii string output
; A contains 8-bit value to convert
.bin2bcd8
{
sta binary_in+0
lda #0
sta binary_in+1
}
.bin2bcd16
{
TXA
PHA
SED ; Switch to decimal mode
LDA #0 ; Ensure the result is clear
STA bcd_out+0
STA bcd_out+1
STA bcd_out+2
LDX #16 ; The number of source bits
.CNVBIT
ASL binary_in+0 ; Shift out one bit
ROL binary_in+1
LDA bcd_out+0 ; And add into result
ADC bcd_out+0
STA bcd_out+0
LDA bcd_out+1 ; propagating any carry
ADC bcd_out+1
STA bcd_out+1
LDA bcd_out+2 ; ... thru whole result
ADC bcd_out+2
STA bcd_out+2
DEX ; And repeat for next bit
BNE CNVBIT
CLD ; Back to binary
PLA
TAX
rts
}
; take a 3-byte bcd encoded number and convert to an ascii zero terminated string
; with leading zeros stripped
; result placed into 'ascii_out'
; preserves X,Y
.bcd2ascii
{
txa
pha
tya
pha
; convert each BCD byte to two ascii bytes
ldx #0
ldy #2
.bcd_loop
lda bcd_out,y
and #&f0
lsr a
lsr a
lsr a
lsr a
clc
adc #48
sta ascii_out,x
inx
lda bcd_out,y
and #&0f
clc
adc #48
sta ascii_out,x
inx
dey
bpl bcd_loop
; zero terminate
lda #0
sta ascii_out,x
; strip leading zeros by copying numeric part of string
; to the front of the ascii_out array
ldx #0
.lz_loop
lda ascii_out,x
cmp #48
bne lz_out
inx
cpx #6
bne lz_loop
; all zeros, so make sure at least one zero is emitted
dex
.lz_out
ldy #0
.lz_loop2
lda ascii_out,x
sta ascii_out,y
beq lz_done
inx
iny
cpx #6
bne lz_loop2
.lz_done
; ??? not sure why I need this, above code should copy the ZT byte also.
lda #0
sta ascii_out,y
pla
tay
pla
tax
rts
}
; send A to currently selected output stream
; set by print_set_output_buffer or print_set_output_os, defaults to OSWRCH
.print_char
{
jsr oswrch ; MODIFIED
rts
}
; send the byte in A to the current output buffer
.render_char
{
sta &FFFF ; MODIFIED
inc render_char+1
bne done
inc render_char+2
.done
rts
}
; fetch the next byte from the current input stream
.print_fetch_char
{
lda &FFFF ; MODIFIED
inc print_fetch_char+1
bne done
inc print_fetch_char+2
.done
rts
}
ELSE
MACRO MPRINT string
{
LDX #LO(string):LDY #HI(string):JSR print_XY
}
ENDMACRO
.print_XY
{
STX stringaddr+1
STY stringaddr+2
LDX #0
.loop
.stringaddr
LDA &FFFF, X
BEQ loop_done
JSR osasci
INX
BNE loop
.loop_done
RTS
}
ENDIF
.beeb_print_end