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