1; Prints values in various ways to output,
2; including numbers and strings.
3
4newline = 10
5
6zp_byte print_temp_
7
8; Prints indicated register to console as two hex
9; chars and space
10; Preserved: A, X, Y, flags
11print_a:
12	php
13	pha
14print_reg_:
15	jsr print_hex
16	lda #' '
17	jsr print_char_
18	pla
19	plp
20	rts
21
22print_x:
23	php
24	pha
25	txa
26	jmp print_reg_
27
28print_y:
29	php
30	pha
31	tya
32	jmp print_reg_
33
34print_p:
35	php
36	pha
37	php
38	pla
39	jmp print_reg_
40
41print_s:
42	php
43	pha
44	txa
45	tsx
46	inx
47	inx
48	inx
49	inx
50	jsr print_x
51	tax
52	pla
53	plp
54	rts
55
56
57; Prints A as two hex characters, NO space after
58; Preserved: A, X, Y
59print_hex:
60	jsr update_crc
61
62	pha
63	lsr a
64	lsr a
65	lsr a
66	lsr a
67	jsr print_hex_nibble
68	pla
69
70	pha
71	and #$0F
72	jsr print_hex_nibble
73	pla
74	rts
75
76print_hex_nibble:
77	cmp #10
78	blt @digit
79	adc #6;+1 since carry is set
80@digit: adc #'0'
81	jmp print_char_
82
83
84; Prints character and updates checksum UNLESS
85; it's a newline.
86; Preserved: A, X, Y
87print_char:
88	cmp #newline
89	beq :+
90	jsr update_crc
91:       pha
92	jsr print_char_
93	pla
94	rts
95
96
97; Prints space. Does NOT update checksum.
98; Preserved: A, X, Y
99print_space:
100	pha
101	lda #' '
102	jsr print_char_
103	pla
104	rts
105
106
107; Advances to next line. Does NOT update checksum.
108; Preserved: A, X, Y
109print_newline:
110	pha
111	lda #newline
112	jsr print_char_
113	pla
114	rts
115
116
117; Prints string
118; Preserved: A, X, Y
119.macro print_str str,str2,str3,str4,str5,str6,str7,str8,str9,str10,str11,str12,str13,str14,str15
120	jsr print_str_
121	.byte str
122	.ifnblank str2
123		.byte str2
124	.endif
125	.ifnblank str3
126		.byte str3
127	.endif
128	.ifnblank str4
129		.byte str4
130	.endif
131	.ifnblank str5
132		.byte str5
133	.endif
134	.ifnblank str6
135		.byte str6
136	.endif
137	.ifnblank str7
138		.byte str7
139	.endif
140	.ifnblank str8
141		.byte str8
142	.endif
143	.ifnblank str9
144		.byte str9
145	.endif
146	.ifnblank str10
147		.byte str10
148	.endif
149	.ifnblank str11
150		.byte str11
151	.endif
152	.ifnblank str12
153		.byte str12
154	.endif
155	.ifnblank str13
156		.byte str13
157	.endif
158	.ifnblank str14
159		.byte str14
160	.endif
161	.ifnblank str15
162		.byte str15
163	.endif
164	.byte 0
165.endmacro
166
167
168print_str_:
169	sta print_temp_
170
171	pla
172	sta addr
173	pla
174	sta addr+1
175
176	jsr inc_addr
177	jsr print_str_addr
178
179	lda print_temp_
180	jmp (addr)
181
182
183; Prints string at addr and leaves addr pointing to
184; byte AFTER zero terminator.
185; Preserved: A, X, Y
186print_str_addr:
187	pha
188	tya
189	pha
190
191	ldy #0
192	beq :+ ; always taken
193@loop:  jsr print_char
194	jsr inc_addr
195:       lda (addr),y
196	bne @loop
197
198	pla
199	tay
200	pla
201	; FALL THROUGH
202
203; Increments 16-bit value in addr.
204; Preserved: A, X, Y
205inc_addr:
206	inc addr
207	beq :+
208	rts
209:       inc addr+1
210	rts
211
212
213
214.pushseg
215.segment "RODATA"
216	; >= 60000 ? (EA60)
217	; >= 50000 ? (C350)
218	; >= 40000 ? (9C40)
219	; >= 30000 ? (7530)
220	; >= 20000 ? (4E20)
221	; >= 10000 ? (2710)
222digit10000_hi: .byte $00,$27,$4E,$75,$9C,$C3,$EA
223digit10000_lo: .byte $00,$10,$20,$30,$40,$50,$60
224	; >= 9000 ? (2328 (hex))
225	; >= 8000 ? (1F40 (hex))
226	; >= 7000 ? (1B58 (hex))
227	; >= 6000 ? (1770 (hex))
228	; >= 5000 ? (1388 (hex))
229	; >= 4000 ? (FA0 (hex))
230	; >= 3000 ? (BB8 (hex))
231	; >= 2000 ? (7D0 (hex))
232	; >= 1000 ? (3E8 (hex))
233digit1000_hi: .byte $00,$03,$07,$0B,$0F,$13,$17,$1B,$1F,$23
234digit1000_lo: .byte $00,$E8,$D0,$B8,$A0,$88,$70,$58,$40,$28
235; >= 900 ? (384 (hex))
236; >= 800 ? (320 (hex))
237; >= 700 ? (2BC (hex))
238; >= 600 ? (258 (hex))
239; >= 500 ? (1F4 (hex))
240; >= 400 ? (190 (hex))
241; >= 300 ? (12C (hex))
242; >= 200 ? (C8 (hex))
243; >= 100 ? (64 (hex))
244digit100_hi: .byte $00,$00,$00,$01,$01,$01,$02,$02,$03,$03
245digit100_lo: .byte $00,$64,$C8,$2C,$90,$F4,$58,$BC,$20,$84
246.popseg
247
248.macro dec16_comparew table_hi, table_lo
249	.local @lt
250	cmp table_hi,y
251	bcc @lt
252	bne @lt ; only test the lo-part if hi-part is equal
253	pha
254	 txa
255	 cmp table_lo,y
256	pla
257@lt:
258.endmacro
259.macro do_digit table_hi, table_lo
260	pha
261	 ; print Y as digit; put X in A and do SEC for subtraction
262	 jsr @print_dec16_helper
263	 sbc table_lo,y
264	 tax
265	pla
266	sbc table_hi,y
267.endmacro
268
269; Prints A:X as 2-5 digit decimal value, NO space after.
270; A = high 8 bits, X = low 8 bits.
271print_dec16:
272	ora #0
273	beq @less_than_256
274
275	ldy #6
276	sty print_temp_
277
278	; TODO: Use binary search?
279:	dec16_comparew digit10000_hi,digit10000_lo
280	bcs @got10000
281	dey
282	bne :-
283	;cpy print_temp_
284	;beq @got10000
285@cont_1000:
286	ldy #9
287:	dec16_comparew digit1000_hi,digit1000_lo
288	bcs @got1000
289	dey
290	bne :-		; Y = 0.
291	cpy print_temp_ ; zero print_temp_ = print zero-digits
292	beq @got1000
293@cont_100:
294	ldy #9
295:	dec16_comparew digit100_hi,digit100_lo
296	bcs @got100
297	dey
298	bne :-
299	cpy print_temp_
300	beq @got100
301@got10000:
302	do_digit digit10000_hi,digit10000_lo
303	; value is now 0000..9999
304	ldy #0
305	sty print_temp_
306	beq @cont_1000
307@got1000:
308	do_digit digit1000_hi,digit1000_lo
309	; value is now 000..999
310	ldy #0
311	sty print_temp_
312	beq @cont_100
313@got100:
314	do_digit digit100_hi,digit100_lo
315	; value is now 00..99
316	txa
317	jmp print_dec_00_99
318@less_than_256:
319	txa
320	jmp print_dec
321@print_dec16_helper:
322	 tya
323	 jsr print_digit
324	 txa
325	 sec
326	rts
327; Prints A as 2-3 digit decimal value, NO space after.
328; Preserved: Y
329print_dec:
330	; Hundreds
331	cmp #10
332	blt print_digit
333	cmp #100
334	blt print_dec_00_99
335print_dec_100_255:
336	ldx #'0'-1
337:       inx
338	sbc #100
339	bge :-
340	adc #100
341	jsr print_char_x
342
343	; Tens
344print_dec_00_99:
345	sec
346	ldx #'0'-1
347:       inx
348	sbc #10
349	bge :-
350	adc #10
351	jsr print_char_x
352	; Ones
353print_digit:
354	ora #'0'
355	jmp print_char
356	; Print a single digit
357print_char_x:
358	pha
359	txa
360	jsr print_char
361	pla
362	rts
363
364
365; Prints one of two characters based on condition.
366; SEC; print_cc bcs,'C','-' prints 'C'.
367; Preserved: A, X, Y, flags
368.macro print_cc cond,yes,no
369	; Avoids labels since they're not local
370	; to macros in ca65.
371	php
372	pha
373	cond *+6
374	lda #no
375	bne *+4
376	lda #yes
377	jsr print_char
378	pla
379	plp
380.endmacro
381
382