]>
Commit | Line | Data |
---|---|---|
1 | ; This is a utility program to delete all data on a disk drive.\r | |
2 | ; The deletion is done by filling all directory sectors with 0E5h.\r | |
3 | ;\r | |
4 | ; The program can be used, to init a RAM disk after cold start.\r | |
5 | ;\r | |
6 | ; Copyright (C) 2010 Leo C.\r | |
7 | ;\r | |
8 | ; This program is free software: you can redistribute it and/or modify\r | |
9 | ; it under the terms of the GNU General Public License as published by\r | |
10 | ; the Free Software Foundation, either version 3 of the License, or\r | |
11 | ; (at your option) any later version.\r | |
12 | ;\r | |
13 | ; This program is distributed in the hope that it will be useful,\r | |
14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of\r | |
15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r | |
16 | ; GNU General Public License for more details.\r | |
17 | ;\r | |
18 | ; You should have received a copy of the GNU General Public License\r | |
19 | ; along with this program. If not, see <http://www.gnu.org/licenses/>.\r | |
20 | ;\r | |
21 | ; $Id$\r | |
22 | \r | |
23 | .Z80\r | |
24 | \r | |
25 | ; BIOS functions\r | |
26 | \r | |
27 | biosofs equ -3 ;offset\r | |
28 | \r | |
29 | wbootf equ biosofs+3*1 ;warm boot function\r | |
30 | homef equ biosofs+3*8 ;disk home function\r | |
31 | seldskf equ biosofs+3*9 ;select disk function\r | |
32 | settrkf equ biosofs+3*10 ;set track function\r | |
33 | setsecf equ biosofs+3*11 ;set sector function\r | |
34 | setdmaf equ biosofs+3*12 ;set dma function\r | |
35 | readf equ biosofs+3*13 ;read disk function\r | |
36 | writef equ biosofs+3*14 ;write disk function\r | |
37 | sectranf equ biosofs+3*16 ;sector translate\r | |
38 | \r | |
39 | ; BDOS functions\r | |
40 | \r | |
41 | pstring equ 9\r | |
42 | rstring equ 10\r | |
43 | seldsk equ 14\r | |
44 | \r | |
45 | cdisk equ 4\r | |
46 | bdos equ 5\r | |
47 | cr equ 13\r | |
48 | lf equ 10\r | |
49 | tab equ 9\r | |
50 | \r | |
51 | buf equ 80h\r | |
52 | \r | |
53 | \r | |
54 | aseg\r | |
55 | org 100h\r | |
56 | \r | |
57 | jp start\r | |
58 | \r | |
59 | rev: db '$Id$'\r | |
60 | usage: db 'Usage: WIPE [Options] d:',cr,lf\r | |
61 | db 'Delete all files on drive d: in all user areas.',cr,lf\r | |
62 | db cr,lf\r | |
63 | db 'Options:',cr,lf\r | |
64 | db ' -Y Don''t ask for confirmation.',cr,lf\r | |
65 | db '$'\r | |
66 | mdrvinval:\r | |
67 | db 'Invalid drive: '\r | |
68 | minvch: db '?:' ;filled in\r | |
69 | db cr,lf,'$'\r | |
70 | mnodrive:\r | |
71 | db 'Can not select drive '\r | |
72 | mnodrch:db '?:' ;filled in\r | |
73 | db cr,lf,'$'\r | |
74 | mnowipe:db 'Nothing done.'\r | |
75 | mcrlf: db cr,lf,'$'\r | |
76 | mconfirm:\r | |
77 | db 'Delete all files in all user areas on drive '\r | |
78 | mcfmchar:\r | |
79 | db '?: (Y/N)?','$'\r | |
80 | \r | |
81 | drive: db 0\r | |
82 | optyes:\r | |
83 | db 0\r | |
84 | transtbl:\r | |
85 | ds 2\r | |
86 | ccpret: ds 2\r | |
87 | conbuf: db conlen\r | |
88 | consiz: ds 1\r | |
89 | conlin: ds 15\r | |
90 | conlen equ $-consiz\r | |
91 | \r | |
92 | ; Get next character from commandline\r | |
93 | \r | |
94 | getchar:\r | |
95 | ld a,(hl)\r | |
96 | inc hl\r | |
97 | or a ;eol?\r | |
98 | ret\r | |
99 | \r | |
100 | ; Skip white space\r | |
101 | \r | |
102 | skipblank:\r | |
103 | ld a,(hl)\r | |
104 | inc hl\r | |
105 | or a ;eol?\r | |
106 | ret z\r | |
107 | cp ' '\r | |
108 | jp z,skipblank\r | |
109 | cp tab\r | |
110 | jp z,skipblank\r | |
111 | ret\r | |
112 | \r | |
113 | ; Setup command line. (Terminate with 0)\r | |
114 | \r | |
115 | setupcmdl:\r | |
116 | ld hl,buf\r | |
117 | ld e,(hl) ; get number of characters on command line\r | |
118 | ld d,0\r | |
119 | inc hl\r | |
120 | ex de,hl\r | |
121 | add hl,de\r | |
122 | ld (hl),0\r | |
123 | ex de,hl\r | |
124 | ret\r | |
125 | \r | |
126 | ; Parse commandline\r | |
127 | \r | |
128 | parsecmd: \r | |
129 | call skipblank\r | |
130 | jp z,pusage ; empty command line\r | |
131 | cp '-'\r | |
132 | jp nz,pcmdarg ; no option, parse agrument\r | |
133 | call getchar\r | |
134 | cp 'Y'\r | |
135 | jp nz,pusage\r | |
136 | ld (optyes),a\r | |
137 | call skipblank\r | |
138 | jp z,pusage ; no argument\r | |
139 | pcmdarg:\r | |
140 | ld b,'?' ; get argument (disk drive)\r | |
141 | cp ' ' ; non printable char?\r | |
142 | jp c,pcmd1\r | |
143 | ld b,a\r | |
144 | pcmd1:\r | |
145 | call getchar\r | |
146 | cp ':'\r | |
147 | ret nz\r | |
148 | ld a,b\r | |
149 | ld (drive),a\r | |
150 | call skipblank\r | |
151 | jp nz,pusage\r | |
152 | ret\r | |
153 | \r | |
154 | \r | |
155 | ; Fill buffer with E5\r | |
156 | \r | |
157 | fillbuf:\r | |
158 | ld hl,buf\r | |
159 | ld c,128\r | |
160 | ld a,0e5h\r | |
161 | fbl:\r | |
162 | ld (hl),a\r | |
163 | inc hl\r | |
164 | dec c\r | |
165 | jp nz,fbl\r | |
166 | ret\r | |
167 | \r | |
168 | ; Print messages on console\r | |
169 | \r | |
170 | pusage: ld de,usage ; address of usage text\r | |
171 | jp pmsgexit\r | |
172 | \r | |
173 | pdrvinval:\r | |
174 | ld (minvch),a\r | |
175 | ld de,mdrvinval ; \r | |
176 | jp pmsgexit\r | |
177 | \r | |
178 | pnodrive:\r | |
179 | ld a,(drive)\r | |
180 | ld (mnodrch),a\r | |
181 | ld de,mnodrive ; \r | |
182 | jp pmsgexit\r | |
183 | \r | |
184 | ; Ask for confirmation.\r | |
185 | \r | |
186 | confirm:\r | |
187 | ld a,(drive)\r | |
188 | ld (mcfmchar),a\r | |
189 | ld de,mconfirm ; \r | |
190 | ld c,pstring ; CP/M command for print\r | |
191 | call bdos\r | |
192 | ld de,conbuf\r | |
193 | ld c,rstring\r | |
194 | call bdos\r | |
195 | ld de,mcrlf\r | |
196 | ld c,pstring ; CP/M command for print\r | |
197 | call bdos\r | |
198 | ld a,(conlin) ; first char\r | |
199 | and 05fh ; toupper()\r | |
200 | cp 'Y'\r | |
201 | ret z\r | |
202 | ld de,mnowipe\r | |
203 | pmsgexit: \r | |
204 | ld c,pstring ; CP/M command for print\r | |
205 | call bdos ; print it\r | |
206 | \r | |
207 | ; Return to CCP (no warmboot).\r | |
208 | \r | |
209 | exitccp:\r | |
210 | ld hl,(ccpret)\r | |
211 | jp (hl)\r | |
212 | \r | |
213 | ; Call BIOS functions\r | |
214 | \r | |
215 | bseldsk:\r | |
216 | ld hl,(1)\r | |
217 | ld de,seldskf\r | |
218 | add hl,de\r | |
219 | jp (hl) \r | |
220 | bsetdma:\r | |
221 | ld hl,(1)\r | |
222 | ld de,setdmaf\r | |
223 | add hl,de\r | |
224 | jp (hl) \r | |
225 | bsettrk:\r | |
226 | ld hl,(1)\r | |
227 | ld de,settrkf\r | |
228 | add hl,de\r | |
229 | jp (hl) \r | |
230 | bsetsec:\r | |
231 | call bsectran\r | |
232 | ld c,l\r | |
233 | ld b,0\r | |
234 | ld hl,(1)\r | |
235 | ld de,setsecf\r | |
236 | add hl,de\r | |
237 | jp (hl) \r | |
238 | bwrite:\r | |
239 | ld c,1 ;write type = dir\r | |
240 | ld hl,(1)\r | |
241 | ld de,writef\r | |
242 | add hl,de\r | |
243 | jp (hl)\r | |
244 | bsectran:\r | |
245 | ld hl,(1)\r | |
246 | ld de,sectranf\r | |
247 | add hl,de\r | |
248 | ex de,hl\r | |
249 | ld hl,(transtbl)\r | |
250 | ex de,hl\r | |
251 | jp (hl) \r | |
252 | \r | |
253 | ; The main function \r | |
254 | \r | |
255 | start: \r | |
256 | pop hl ; Get return address;\r | |
257 | ld (ccpret),hl ; and save it for later\r | |
258 | ld sp,stack ; Setup local stack.\r | |
259 | call setupcmdl\r | |
260 | call parsecmd\r | |
261 | ld a,(drive) ; Was a drive specified?\r | |
262 | or a\r | |
263 | jp z,pusage ; If not, print message and return.\r | |
264 | cp 'A' ; valid drive letter?\r | |
265 | jp c,pdrvinval\r | |
266 | cp 'P'+1\r | |
267 | jp nc,pdrvinval\r | |
268 | \r | |
269 | ld a,(optyes) ; Was 'Y' option given?\r | |
270 | or a\r | |
271 | call z,confirm ; If no, ask for confirmation.\r | |
272 | \r | |
273 | ; Command is ok and confirmed, check drive\r | |
274 | \r | |
275 | ld a,(drive) ; Select the requested drive.\r | |
276 | sub 'A' ; Use the BIOS function for this,\r | |
277 | ld c,a ; as BDOS would initialize the drive\r | |
278 | call bseldsk ; and try to read the (broken) directory.\r | |
279 | ld a,l\r | |
280 | or h\r | |
281 | jp nz,getdpb\r | |
282 | \r | |
283 | ld a,(cdisk) ; Reselect current disk drive.\r | |
284 | and 0fh\r | |
285 | ld c,a\r | |
286 | call bseldsk\r | |
287 | jp pnodrive ; Msg, and return to CCP.\r | |
288 | \r | |
289 | ; Drive exists. Get disk parameter\r | |
290 | getdpb: \r | |
291 | ld a,(hl) ; sector translation table\r | |
292 | ld (transtbl),a\r | |
293 | inc hl\r | |
294 | ld a,(hl)\r | |
295 | ld (transtbl+1),a\r | |
296 | dec hl\r | |
297 | ld de,10 ; dpb ofset\r | |
298 | add hl,de\r | |
299 | ld e,(hl)\r | |
300 | inc hl\r | |
301 | ld d,(hl) ; de = dpb of selected drive\r | |
302 | \r | |
303 | ld hl,13 ; ofset to # of reserved tracks\r | |
304 | add hl,de\r | |
305 | ld c,(hl) ; Start track\r | |
306 | inc hl\r | |
307 | ld b,(hl) ; bc = track\r | |
308 | \r | |
309 | push bc ; save for later\r | |
310 | \r | |
311 | ; Compute number of sectors to fill.\r | |
312 | \r | |
313 | ld hl,7 ; drm ofset\r | |
314 | add hl,de\r | |
315 | ld a,(hl) ; get drm (# of dir entries - 1)\r | |
316 | add a,3+1 ; round up\r | |
317 | ld c,a\r | |
318 | inc hl\r | |
319 | ld a,(hl) ; Each sector holds 4 dir entries\r | |
320 | adc a,0\r | |
321 | rra \r | |
322 | ld b,a\r | |
323 | ld a,c\r | |
324 | rra\r | |
325 | ld c,a\r | |
326 | ld a,b\r | |
327 | or a ; clear carry\r | |
328 | rra\r | |
329 | ld b,a\r | |
330 | ld a,c \r | |
331 | rra\r | |
332 | ld c,a ; c = # of sectors ((drm+1+3)/4)\r | |
333 | \r | |
334 | ; Get sectors per track.\r | |
335 | \r | |
336 | ld a,(de) ; b = sectors per track\r | |
337 | ld b,a\r | |
338 | push bc \r | |
339 | \r | |
340 | ; Init fill loop.\r | |
341 | \r | |
342 | call fillbuf \r | |
343 | ld bc,buf\r | |
344 | call bsetdma\r | |
345 | \r | |
346 | ld bc,0 ; c = sec\r | |
347 | pop de ; d = spt, e = nsec\r | |
348 | pop hl ; hl = track\r | |
349 | nxtrk:\r | |
350 | push hl ; track\r | |
351 | push de ; spt, nsec\r | |
352 | push bc ; sec\r | |
353 | ld b,h \r | |
354 | ld c,l\r | |
355 | call bsettrk ;\r | |
356 | pop bc\r | |
357 | pop de\r | |
358 | nxtsec:\r | |
359 | push de ;\r | |
360 | push bc\r | |
361 | call bsetsec\r | |
362 | call bwrite\r | |
363 | pop bc ;sec\r | |
364 | pop de ;d = spt, e = nsec\r | |
365 | dec e\r | |
366 | jp z,done\r | |
367 | \r | |
368 | inc c ;next sector\r | |
369 | ld a,c\r | |
370 | cp d ;if sector >= spt then change tracks\r | |
371 | jp c,nxtsec\r | |
372 | \r | |
373 | ld c,b ;sec = 0\r | |
374 | pop hl\r | |
375 | inc hl ;next track\r | |
376 | jp nxtrk\r | |
377 | \r | |
378 | ; All directory sectors filled.\r | |
379 | done:\r | |
380 | pop hl\r | |
381 | jp 0 ; Boot (reinits disks)\r | |
382 | \r | |
383 | progend:ds (($+255) and 0ff00h)-$ ; Fill rest of page with zero\r | |
384 | \r | |
385 | stack equ progend+40\r | |
386 | \r | |
387 | end\r | |
388 | \r | |
389 | ; vim:set ts=8 noet nowrap\r | |
390 | \r |