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