]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame - cbios/utils.180
WIP
[z180-stamp-cpm3.git] / cbios / utils.180
CommitLineData
6dd88c25
L
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 ?pmsg ; print message
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
30cr equ 13
31lf equ 10
32bell 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
46ioiniml:
47 push bc
48 xor a
49ioml_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
59ioml_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
71ioini1l:
72 push bc
73 jr io1_nxt
74io1_lp:
75 ld c,(hl) ;port address
76 inc hl
77 otim
78 jr nz,io1_lp
79io1_nxt:
80 ld b,(hl) ;count
81 inc hl
82 inc b
83 djnz io1_lp
84
85 pop bc
86 ret
1c7e3963
L
87
88 cseg
89
6dd88c25
L
90;--------------------------------------------------------------------
91; vectored CALL point
92
93ijphl:
94 jp (hl)
95
1c7e3963
L
96 dseg
97
6dd88c25
L
98;--------------------------------------------------------------------
99; add a to hl
100;
101; return:
102; hl = hl + a
103; Flags undefined
104
105add_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
121div32_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
129div_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
142div32_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;
166div_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
192div_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 @<HL> up to a null
217; saves <BC> & <DE>
218
219?pmsg:
220 push bc
221 push de
222pmsg$loop:
223 ld a,(hl)
224 inc hl
225 or a
226 jr z,pmsg$exit
227 ld c,a
228 push hl
229 call ?cono
230 pop hl
231 jr pmsg$loop
232pmsg$exit:
233 pop de
234 pop bc
235 ret
236
237;-------------------------------------------------------------------------------
238; print message from table @<HL>, indexed by <A>
239; saves <BC> & <DE>
240
241pr.idx:
242 push bc
243 push de
244 push hl ; put pointer to first message on stack
245 ld e,a ; save message number
246 xor a
247 ld b,a
248 ld c,a
249 inc e
250pdc_nxt_str:
251 dec e
252 ex (sp),hl
253 jr z,pdc_found
254 ex (sp),hl
255 cpir
256 cp (hl)
257 jr nz,pdc_nxt_str
258 ; End of List, msg not found.
259 ; Print first msg.
260pdc_found:
261 pop hl
262 call ?pmsg
263 pop de
264 pop bc
265 ret
266
267;-------------------------------------------------------------------------------
268; print message inline up to a null
269; saves all registers
270
271pr.inln:
272 ex (sp),hl
273 push af
274 call ?pmsg
275 pop af
276 ex (sp),hl
277 ret
278
279;-------------------------------------------------------------------------------
280; print <CR><LF>
281; saves all registers
282
283pr.crlf:
284 call pr.inln
285 db cr,lf,0
286 ret
287
288;-------------------------------------------------------------------------------
289; print hl as a 4 digit hexadecimal number
290; saves all registers
291
292phex4:
293 ld a,h
294 call phex2
295 ld a,l
296 ; fall thru
297
298;-------------------------------------------------------------------------------
299; print a as a 2 digit hexadecimal number
300; saves all registers
301
302phex2:
303 push af
304 rra
305 rra
306 rra
307 rra
308 call print.digit
309 pop af
310
311print.digit:
312 push hl
313 push de
314 push bc
315 push af
316 and 00fh
317 cp 10
318 jr c,prd_1
319 add a,007h
320prd_1:
321 add a,'0'
322
323 ld c,a
324 call ?cono
325 pop af
326 pop bc
327 pop de
328 pop hl
329 ret
330
331
332;-------------------------------------------------------------------------------
333; print decimal 16 bit number from HL
334;
335; HL: unsigned binary number to print
336; C: minimum print field width
337; number is prined right-aligned
338; B: pad character, typically ' ' or '0'
339
340pr.dec:
341 push de
342 ld de,0
343 call pr.decl
344 pop de
345 ret
346
347;-------------------------------------------------------------------------------
348; print decimal 32 bit number from DEHL
349;
350; DEHL: unsigned binary number to print
351; C: minimum print field width
352; number is prined right-aligned
353; B: pad character, typically ' ' or '0'
354
355pr.decl:
356 push bc ;save width and fillchar
357 push bc
358 exx ;(alt)
359 ex (sp),hl ;save hl', get width and fill
360 push de ;save de'
361
362 xor a
363 ld d,a ;clear counter
364 ld e,a
365 push af ; string terminator
366 inc sp
367
368prd_divloop: ;do
369 exx ; (main)
370 ld bc,10 ;
371 call div32_16 ; get a digit
372 ld a,c ;
373 add a,'0' ; make it printable
374 push af ;
375
376 ld a,h ;
377 or l ;
378 or d ;
379 or e ;
380 exx ; (alt)
381 inc sp ;
382 inc de ;
383 jr nz,prd_divloop ;
384
385prd_filloop: ;h=filler, l=field width
386 ld a,e
387 cp l
388 jr nc,prd_out
389 push hl
390 inc sp
391 inc de
392 jr prd_filloop
393prd_out:
394 ld hl,0
395 add hl,sp ;ptr to beginning of number string (hl==0 here)
396 call ?pmsg
397 ex de,hl
398 add hl,sp
399 ld sp,hl
400 inc sp ;remove string terminator
401 pop de
402 pop hl
403 exx ;(main)
404 pop bc
405 ret
406
407
408;-------------------------------------------------------------------------------
409
410?pderr:
411 ld hl,drive$msg
412 call ?pmsg ; error header
413 ld a,(@adrv)
414 add a,'A'
415 ld c,a
416 call ?cono ; drive code
417 ld hl,track$msg
418 call ?pmsg ; track header
419 ld c,0
420 ld hl,(@trk)
421 call pr.dec ; track number
422 ld hl,sector$msg
423 call ?pmsg ; sector header
424 ld hl,(@sect)
425 jp pr.dec ; sector number
426
427 ; error message components
428drive$msg: db cr,lf,bell,'BIOS Error on ',0
429track$msg: db ': T-',0
430sector$msg: db ', S-',0
431
432
433;-------------------------------------------------------------------------------
434; get console input, echo it, and shift to upper case
435; save hl,de,bc
436
437uciecho:
438 push hl
439 push de
440 push bc
441u$c0:
442 call ?const
443 or a
444 jr z,u$c1 ; see if any char already struck
445 call ?conin
446 jr u$c0 ; yes, eat it and try again
447u$c1:
448 call ?conin
449 push af
450 ld c,a
451 cp ' '-1
452 call nc,?cono
453 pop af
454 pop bc
455 pop de
456 pop hl
457 cp 'a'
458 ret c
459 sub 'a'-'A' ; make upper case
460 ret
461
462;-------------------------------------------------------------------------------
463;
464
465pr.errors:
466
467 ; suppress error message if BDOS
468 ; is returning errors to application...
469
470 ld a,(@ermde)
471 inc a
472 jr nz,pre1
473 dec a ;return NZ, if @ermde == 0FFH
474 ret
475pre1:
476 push hl
477 ld hl,pre2
478 ex (sp),hl
479 push hl
480
481 ; Had permanent error, print message like:
482 ; BIOS Err on d: T-nn, S-mm, <operation> <type>, Retry ?
483
484 call ?pderr ; print message header
485
486 ld hl,op$msg
487 ld a,(@op)
488 jp pr.idx ; last function (read or write)
489
490pre2:
491 ; prompt for retry
492 call pr.inln
493 db ' Retry (Y/N) ? ',0
494
495 call uciecho ; get operator response
496 cp 'Y'
497 ret ; return Z-flag for yes
498
499
500op$msg:
501 db ', Unknown op, ',0
502 db ', Read, ',0
503 db ', Write, ',0
504 db 0
505
506 end