]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/utils.180
refactor print utils
[z180-stamp-cpm3.git] / cbios / utils.180
1 title 'general utility routines'
2
3 ; i/o port init routines
4
5 public ioiniml,ioini1l ;
6
7 ; math
8
9 public ijphl ; vectored CALL point
10 public add_hla ; add a to hl
11 public div32_16,div32_r ; divide 32 bit by 16 bit number (rounded)
12
13 ; print utils
14
15 public ?pchar,?pmsg ; print char <A>, print message (<HL>)
16 public pr.idx ; print message from table indexed by <A>
17 public pr.inln,pr.crlf ; print message inline, print newline
18 public phex2,phex4 ; print 2 digit hex <A> or 4 digit hex <HL>
19 public pr.dec,pr.decl ; print 16 or 32 bit decimal number
20 public pr.errors ; print BIOS disk error message header
21
22
23
24 extrn ?const,?conin,?cono
25 extrn @adrv,@trk,@sect ; used by disk error message
26 extrn @op,@ermde
27
28 ;-------------------------------------------------------------------------------
29
30 cr equ 13
31 lf equ 10
32 bell equ 7
33
34
35 dseg
36
37 ;----------------------------------------------------------------------
38 ; output bytes to consecutive portaddresses
39 ;
40 ; hl: table with following structure:
41 ; db n, port1, val1, val2,... valn
42 ; db m, port1, val1, val2,... valm
43 ; ...
44 ; db 0 ; Terminate table
45
46 ioiniml:
47 push bc
48 xor a
49 ioml_lp:
50 ld b,(hl)
51 inc hl
52 cp b
53 jr z,ioml_e
54
55 ld c,(hl)
56 inc hl
57 otimr
58 jr ioml_lp
59 ioml_e:
60 pop bc
61 ret
62
63 ;----------------------------------------------------------------------
64 ; output bytes to ports
65 ;
66 ; hl: tables of port,value pairs:
67 ; db n, port1,val1, port2,val2,... portn,valn
68 ; ...
69 ; db 0 ; Terminate table
70
71 ioini1l:
72 push bc
73 jr io1_nxt
74 io1_lp:
75 ld c,(hl) ;port address
76 inc hl
77 otim
78 jr nz,io1_lp
79 io1_nxt:
80 ld b,(hl) ;count
81 inc hl
82 inc b
83 djnz io1_lp
84
85 pop bc
86 ret
87
88 cseg
89
90 ;--------------------------------------------------------------------
91 ; vectored CALL point
92
93 ijphl:
94 jp (hl)
95
96 dseg
97
98 ;--------------------------------------------------------------------
99 ; add a to hl
100 ;
101 ; return:
102 ; hl = hl + a
103 ; Flags undefined
104
105 add_hla:
106 add a,l
107 ld l,a
108 ret nc
109 inc h
110 ret
111
112 ;--------------------------------------------------------------------
113 ; rounded div 32 by 16 bit
114 ;
115 ; DEHL: Dividend (x)
116 ; BC: Divisor (y)
117 ; return:
118 ; HLDE: Rounded Quotient (q)
119 ; BC: Remainder (r)
120
121 div32_r:
122 push bc
123 srl b ;y/2
124 rr c
125 add hl,bc ;low x + y/2
126 pop bc
127 jr nc,div_r1
128 inc de
129 div_r1:
130 ;fall thru
131
132 ;--------------------------------------------------------------------
133 ; Divide 32 bit by 16
134 ;
135 ; DEHL: Dividend (x)
136 ; BC: Divisor (y)
137 ;
138 ; return:
139 ; DEHL: Quotient
140 ; BC: Reminder
141
142 div32_16:
143 exx ;low
144 push de ;save alternate registers (de,bc)
145 push bc
146 exx ;high
147 push hl ;lx
148 push bc ;ly
149 ld bc,0 ;bc = hy = 0
150 ld h,b ;hl = hr = 0
151 ld l,c
152 ;de = x, hl = r
153 exx ;low
154 pop bc ;bc' = ly
155 ex (sp),hl ;hl' = lx, save alternate hl
156 ld de,0 ;de' = lr = 0
157 ex de,hl ;de = x, hl = r
158 exx ;high
159 ld a,32 ;count
160 ;
161 ; start:
162 ; de: x (de: hx, de': lx)
163 ; bc: y (bc: hy, bc': ly)
164 ; hl: 0
165 ;
166 div_lp: ;do
167 exx ; low
168 ex de,hl ; x
169 add hl,hl ; x <<= 1
170 exx ; high
171 ex de,hl ; x
172 adc hl,hl ; x <<= 1
173 exx ; low
174 ex de,hl ; r
175 adc hl,hl ; r <<= 1
176 exx ; high
177 ex de,hl ; r
178 adc hl,hl ; r <<= 1
179 exx ; low
180 inc de ; x/q += 1
181 or a ;
182 sbc hl,bc ;
183 exx ; high
184 sbc hl,bc ;
185 jr nc,div_no_restore
186 exx ; low
187 dec de ;
188 add hl,bc ; r += y
189 exx ; high
190 adc hl,bc ;
191
192 div_no_restore: ;
193 dec a ;
194 jr nz,div_lp ;while (--count)
195
196 ; result:
197 ; de: q (de: hq, de': lq)
198 ; hl: r (hl: hr, hl': lr)
199
200 exx ;low
201 ex de,hl ;hl = lq, de = lr
202
203 ex (sp),hl ;lq
204 push de ;lr
205 exx ;high
206 pop bc ;bc = lr
207 pop hl ;de = lq
208
209 exx ;low
210 pop bc ;restore alternate registers
211 pop de
212 exx ;high
213 ret
214
215 ;-------------------------------------------------------------------------------
216 ; print message from table @<HL>, indexed by <A>
217 ; saves <BC> & <DE>
218
219 pr.idx:
220 push bc
221 push hl ; put pointer to first message on stack
222 ld b,a ; save message number
223 or a
224 jr z,pdc_done
225 xor a
226 pdc_skip:
227 bit 7,(hl)
228 inc hl
229 jr z,pdc_skip
230 cp (hl)
231 jr z,pdc_done ; End of List, msg not found. Print first msg.
232 djnz pdc_skip
233 ex (sp),hl ; Remove first msg from stack
234 pdc_done:
235 pop hl ; Get msg. to print
236 pop bc
237 ;fall thru
238
239 ;-------------------------------------------------------------------------------
240 ; print message @<HL> up to a null
241 ; saves <BC> & <DE>
242
243 ?pmsg:
244 ld a,(hl)
245 inc hl
246 and 07fh
247 ret z
248 call ?pchar
249 dec hl
250 bit 7,(hl)
251 inc hl
252 jr z,?pmsg
253 ret
254
255 ;-------------------------------------------------------------------------------
256 ; print message inline up to a null
257 ; saves <BC>, <DE>, <HL>
258
259 pr.inln:
260 ex (sp),hl
261 call ?pmsg
262 ex (sp),hl
263 ret
264
265 ;-------------------------------------------------------------------------------
266 ; print <CR><LF>
267 ; saves <BC>, <DE>, <HL>
268
269 pr.crlf:
270 call pr.inln
271 dc cr,lf
272 ret
273
274 ;-------------------------------------------------------------------------------
275 ; print hl as a 4 digit hexadecimal number
276 ; saves all registers
277
278 phex4:
279 ld a,h
280 call phex2
281 ld a,l
282 ; fall thru
283
284 ;-------------------------------------------------------------------------------
285 ; print a as a 2 digit hexadecimal number
286 ; saves all registers
287
288 phex2:
289 push af
290 rra
291 rra
292 rra
293 rra
294 call print.digit
295 pop af
296
297 print.digit:
298 daa
299 add a,0a0h
300 adc a,040h
301 ;fall thru
302
303 ;-------------------------------------------------------------------------------
304 ; print character in a
305 ; saves <BC>, <DE>, <HL>
306
307 ?pchar:
308 push bc
309 push de
310 push hl
311 ld c,a
312 call ?cono
313 pop hl
314 pop de
315 pop bc
316 ret
317
318 ;-------------------------------------------------------------------------------
319 ; print decimal 16 bit number from HL
320 ;
321 ; HL: unsigned binary number to print
322 ; C: minimum print field width
323 ; number is printed right-aligned
324 ; B: pad character, typically ' ' or '0'
325
326 pr.dec:
327 push de
328 ld de,0
329 call pr.decl
330 pop de
331 ret
332
333 ;-------------------------------------------------------------------------------
334 ; print decimal 32 bit number from DEHL
335 ;
336 ; DEHL: unsigned binary number to print
337 ; C: minimum print field width
338 ; number is printed right-aligned
339 ; B: pad character, typically ' ' or '0'
340
341 pr.decl:
342 push bc ;save width and fillchar
343 push bc
344 exx ;(alt)
345 ex (sp),hl ;save hl', get width and fill
346 push de ;save de'
347
348 xor a
349 ld d,a ;clear counter
350 ld e,a
351 push af ; string terminator
352 inc sp
353
354 prd_divloop: ;do
355 exx ; (main)
356 ld bc,10 ;
357 call div32_16 ; get a digit
358 ld a,c ;
359 add a,'0' ; make it printable
360 push af ;
361
362 ld a,h ;
363 or l ;
364 or d ;
365 or e ;
366 exx ; (alt)
367 inc sp ;
368 inc de ;
369 jr nz,prd_divloop ;
370
371 prd_filloop: ;h=filler, l=field width
372 ld a,e
373 cp l
374 jr nc,prd_out
375 push hl
376 inc sp
377 inc de
378 jr prd_filloop
379 prd_out:
380 ld hl,0
381 add hl,sp ;ptr to beginning of number string (hl==0 here)
382 call ?pmsg
383 ex de,hl
384 add hl,sp
385 ld sp,hl
386 inc sp ;remove string terminator
387 pop de
388 pop hl
389 exx ;(main)
390 pop bc
391 ret
392
393
394 ;-------------------------------------------------------------------------------
395
396 ?pderr:
397 ld a,(@adrv)
398 add a,'A'
399 ld (msg_drv),a
400 call pr.inln ; error header
401 db cr,lf,bell,'BIOS Error on '
402 msg_drv:
403 db 'A'
404 dc ': T-'
405 ld c,0
406 ld hl,(@trk)
407 call pr.dec ; track number
408 call pr.inln ; sector header
409 dc ', S-'
410 ld hl,(@sect)
411 jp pr.dec ; sector number
412
413 ;-------------------------------------------------------------------------------
414 ; get console input, echo it, and shift to upper case
415 ; save hl,de,bc
416
417 uciecho:
418 push hl
419 push de
420 push bc
421 u$c0:
422 call ?const
423 or a
424 jr z,u$c1 ; see if any char already struck
425 call ?conin
426 jr u$c0 ; yes, eat it and try again
427 u$c1:
428 call ?conin
429 push af
430 ld c,a
431 cp ' '-1
432 call nc,?cono
433 pop af
434 pop bc
435 pop de
436 pop hl
437 cp 'a'
438 ret c
439 sub 'a'-'A' ; make upper case
440 ret
441
442 ;-------------------------------------------------------------------------------
443 ;
444
445 pr.errors:
446
447 ; suppress error message if BDOS
448 ; is returning errors to application...
449
450 ld a,(@ermde)
451 inc a
452 jr nz,pre1
453 dec a ;return NZ, if @ermde == 0FFH
454 ret
455 pre1:
456 push hl
457 ld hl,pre2
458 ex (sp),hl
459 push hl
460
461 ; Had permanent error, print message like:
462 ; BIOS Err on d: T-nn, S-mm, <operation> <type>, Retry ?
463
464 call ?pderr ; print message header
465
466 ld hl,op$msg
467 ld a,(@op)
468 jp pr.idx ; last function (read or write)
469
470 pre2:
471 ; prompt for retry
472 call pr.inln
473 dc ' Retry (Y/N) ? '
474
475 call uciecho ; get operator response
476 cp 'Y'
477 ret ; return Z-flag for yes
478
479
480 op$msg:
481 dc ', Unknown op, '
482 dc ', Read, '
483 dc ', Write, '
484 db 0
485
486 end