]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame - cbios/utils.180
Make ASCI1 the default console device after cold boot.
[z180-stamp-cpm3.git] / cbios / utils.180
CommitLineData
4cd9d981
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 add_hla ; add a to hl\r
10 public div32_16,div32_r ; divide 32 bit by 16 bit number (rounded)\r
11\r
12 ; print utils\r
13\r
14 public ?pmsg ; print message\r
15 public pr.inln,pr.crlf ; print message inline, print newline\r
16 public phex2,phex4 ; print 2 digit hex (A) or 4 digit hex (HL)\r
17 public pr.dec,pr.decl ; print 16 or 32 bit decimal number\r
18 public ?pderr ; print BIOS disk error message header\r
19\r
20\r
21\r
22 extrn ?cono\r
23 extrn @adrv,@trk,@sect ; used by disk error message\r
24\r
25;-------------------------------------------------------------------------------\r
26\r
27cr equ 13\r
28lf equ 10\r
29bell equ 7\r
30\r
31\r
32 dseg\r
33\r
34;----------------------------------------------------------------------\r
35; output bytes to consecutive portaddresses\r
36;\r
37; hl: table with following structure:\r
38; db n, port1, val1, val2,... valn\r
39; db m, port1, val1, val2,... valm\r
40; ...\r
41; db 0 ; Terminate table\r
42\r
43ioiniml:\r
44 push bc\r
45 xor a\r
46ioml_lp:\r
47 ld b,(hl)\r
48 inc hl\r
49 cp b\r
50 jr z,ioml_e\r
51\r
52 ld c,(hl)\r
53 inc hl\r
54 otimr\r
55 jr ioml_lp\r
56ioml_e:\r
57 pop bc\r
58 ret\r
59\r
60;----------------------------------------------------------------------\r
61; output bytes to ports\r
62;\r
63; hl: tables of port,value pairs:\r
64; db n, port1,val1, port2,val2,... portn,valn\r
65; ...\r
66; db 0 ; Terminate table\r
67\r
68ioini1l:\r
69 push bc\r
70 jr io1_nxt\r
71io1_lp:\r
72 ld c,(hl) ;port address\r
73 inc hl\r
74 otim\r
75 jr nz,io1_lp\r
76io1_nxt:\r
77 ld b,(hl) ;count\r
78 inc hl\r
79 inc b\r
80 djnz io1_lp\r
81\r
82 pop bc\r
83 ret\r
84\r
85;--------------------------------------------------------------------\r
86; add a to hl\r
87;\r
88; return:\r
89; hl = hl + a\r
90; Flags undefined\r
91\r
92add_hla:\r
93 add a,l\r
94 ld l,a\r
95 ret nc\r
96 inc h\r
97 ret\r
98\r
99;--------------------------------------------------------------------\r
100; rounded div 32 by 16 bit\r
101;\r
102; DEHL: Dividend (x)\r
103; BC: Divisor (y)\r
104; return:\r
105; HLDE: Rounded Quotient (q)\r
106; BC: Remainder (r)\r
107\r
108div32_r:\r
109 push bc\r
110 srl b ;y/2\r
111 rr c\r
112 add hl,bc ;low x + y/2\r
113 pop bc\r
114 jr nc,div_r1\r
115 inc de\r
116div_r1:\r
117 ;fall thru\r
118\r
119;--------------------------------------------------------------------\r
120; Divide 32 bit by 16\r
121;\r
122; DEHL: Dividend (x)\r
123; BC: Divisor (y)\r
124;\r
125; return:\r
126; DEHL: Quotient\r
127; BC: Reminder\r
128\r
129div32_16:\r
130 exx ;low\r
131 push de ;save alternate registers (de,bc)\r
132 push bc\r
133 exx ;high\r
134 push hl ;lx\r
135 push bc ;ly\r
136 ld bc,0 ;bc = hy = 0\r
137 ld h,b ;hl = hr = 0\r
138 ld l,c\r
139 ;de = x, hl = r\r
140 exx ;low\r
141 pop bc ;bc' = ly\r
142 ex (sp),hl ;hl' = lx, save alternate hl\r
143 ld de,0 ;de' = lr = 0\r
144 ex de,hl ;de = x, hl = r\r
145 exx ;high\r
146 ld a,32 ;count\r
147;\r
148; start:\r
149; de: x (de: hx, de': lx)\r
150; bc: y (bc: hy, bc': ly)\r
151; hl: 0\r
152;\r
153div_lp: ;do\r
154 exx ; low\r
155 ex de,hl ; x\r
156 add hl,hl ; x <<= 1\r
157 exx ; high\r
158 ex de,hl ; x\r
159 adc hl,hl ; x <<= 1\r
160 exx ; low\r
161 ex de,hl ; r\r
162 adc hl,hl ; r <<= 1\r
163 exx ; high\r
164 ex de,hl ; r\r
165 adc hl,hl ; r <<= 1\r
166 exx ; low\r
167 inc de ; x/q += 1\r
168 or a ;\r
169 sbc hl,bc ;\r
170 exx ; high\r
171 sbc hl,bc ;\r
172 jr nc,div_no_restore\r
173 exx ; low\r
174 dec de ;\r
175 add hl,bc ; r += y\r
176 exx ; high\r
177 adc hl,bc ;\r
178\r
179div_no_restore: ;\r
180 dec a ;\r
181 jr nz,div_lp ;while (--count)\r
182\r
183; result:\r
184; de: q (de: hq, de': lq)\r
185; hl: r (hl: hr, hl': lr)\r
186\r
187 exx ;low\r
188 ex de,hl ;hl = lq, de = lr\r
189\r
190 ex (sp),hl ;lq\r
191 push de ;lr\r
192 exx ;high\r
193 pop bc ;bc = lr\r
194 pop hl ;de = lq\r
195\r
196 exx ;low\r
197 pop bc ;restore alternate registers\r
198 pop de\r
199 exx ;high\r
200 ret\r
201\r
202;-------------------------------------------------------------------------------\r
203; print message @<HL> up to a null\r
204; saves <BC> & <DE>\r
205\r
206?pmsg:\r
207 push bc\r
208 push de\r
209pmsg$loop:\r
210 ld a,(hl)\r
211 inc hl\r
212 or a\r
213 jr z,pmsg$exit\r
214 ld c,a\r
215 push hl\r
216 call ?cono\r
217 pop hl\r
218 jr pmsg$loop\r
219pmsg$exit:\r
220 pop de\r
221 pop bc\r
222 ret\r
223\r
224;-------------------------------------------------------------------------------\r
225; print message inline up to a null\r
226; saves all registers\r
227\r
228pr.inln:\r
229 ex (sp),hl\r
230 push af\r
231 call ?pmsg\r
232 pop af\r
233 ex (sp),hl\r
234 ret\r
235\r
236;-------------------------------------------------------------------------------\r
237; print <CR><LF>\r
238; saves all registers\r
239\r
240pr.crlf:\r
241 call pr.inln\r
242 db cr,lf,0\r
243 ret\r
244\r
245;-------------------------------------------------------------------------------\r
246; print hl as a 4 digit hexadecimal number\r
247; saves all registers\r
248\r
249phex4:\r
250 ld a,h\r
251 call phex2\r
252 ld a,l\r
253 ; fall thru\r
254\r
255;-------------------------------------------------------------------------------\r
256; print a as a 2 digit hexadecimal number\r
257; saves all registers\r
258\r
259phex2:\r
260 push af\r
261 rra\r
262 rra\r
263 rra\r
264 rra\r
265 call print.digit\r
266 pop af\r
267\r
268print.digit:\r
269 push hl\r
270 push de\r
271 push bc\r
272 push af\r
273 and 00fh\r
274 cp 10\r
275 jr c,prd_1\r
276 add a,007h\r
277prd_1:\r
278 add a,'0'\r
279\r
280 ld c,a\r
281 call ?cono\r
282 pop af\r
283 pop bc\r
284 pop de\r
285 pop hl\r
286 ret\r
287\r
288\r
289;-------------------------------------------------------------------------------\r
290; print decimal 16 bit number from HL\r
291;\r
292; HL: unsigned binary number to print\r
293; C: minimum print field width\r
294; number is prined right-aligned\r
295; B: pad character, typically ' ' or '0'\r
296\r
297pr.dec:\r
298 push de\r
299 ld de,0\r
300 call pr.decl\r
301 pop de\r
302 ret\r
303\r
304;-------------------------------------------------------------------------------\r
305; print decimal 32 bit number from DEHL\r
306;\r
307; DEHL: unsigned binary number to print\r
308; C: minimum print field width\r
309; number is prined right-aligned\r
310; B: pad character, typically ' ' or '0'\r
311\r
312pr.decl:\r
313 push bc ;save width and fillchar\r
314 push bc\r
315 exx ;(alt)\r
316 ex (sp),hl ;save hl', get width and fill\r
317 push de ;save de'\r
318\r
319 xor a\r
320 ld d,a ;clear counter\r
321 ld e,a\r
322 push af ; string terminator\r
323 inc sp\r
324\r
325prd_divloop: ;do\r
326 exx ; (main)\r
327 ld bc,10 ;\r
328 call div32_16 ; get a digit\r
329 ld a,c ;\r
330 add a,'0' ; make it printable\r
331 push af ;\r
332\r
333 ld a,h ;\r
334 or l ;\r
335 or d ;\r
336 or e ;\r
337 exx ; (alt)\r
338 inc sp ;\r
339 inc de ;\r
340 jr nz,prd_divloop ;\r
341\r
342prd_filloop: ;h=filler, l=field width\r
343 ld a,e\r
344 cp l\r
345 jr nc,prd_out\r
346 push hl\r
347 inc sp\r
348 inc de\r
349 jr prd_filloop\r
350prd_out:\r
351 ld hl,0\r
352 add hl,sp ;ptr to beginning of number string (hl==0 here)\r
353 call ?pmsg\r
354 ex de,hl\r
355 add hl,sp\r
356 ld sp,hl\r
357 inc sp ;remove string terminator\r
358 pop de\r
359 pop hl\r
360 exx ;(main)\r
361 pop bc\r
362 ret\r
363\r
364\r
365;-------------------------------------------------------------------------------\r
366\r
367?pderr:\r
368 ld hl,drive$msg\r
369 call ?pmsg ; error header\r
370 ld a,(@adrv)\r
371 add a,'A'\r
372 ld c,a\r
373 call ?cono ; drive code\r
374 ld hl,track$msg\r
375 call ?pmsg ; track header\r
376 ld c,0\r
377 ld hl,(@trk)\r
378 call pr.dec ; track number\r
379 ld hl,sector$msg\r
380 call ?pmsg ; sector header\r
381 ld hl,(@sect)\r
382 call pr.dec ; sector number\r
383 ret\r
384\r
385 ; error message components\r
386drive$msg: db cr,lf,bell,'BIOS Error on ',0\r
387track$msg: db ': T-',0\r
388sector$msg: db ', S-',0\r