-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmscat.asm
More file actions
532 lines (465 loc) · 16.3 KB
/
mscat.asm
File metadata and controls
532 lines (465 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
;
; Slowdos Source Code
;
;
; $Id: mscat.asm,v 1.3 2003/06/17 19:08:03 dom Exp $
; $Author: dom $
; $Date: 2003/06/17 19:08:03 $
;
; Disc cataloging routines
MODULE catalogue
INCLUDE "slowdos.def"
INCLUDE "syntaxdefs.def"
INCLUDE "printing.def"
;; External routines
EXTERN clfilen
;; Error handling
EXTERN errorn
EXTERN getsec
EXTERN sros
EXTERN sros1
EXTERN swos
EXTERN swos1
EXTERN rdnxft
EXTERN r_hxfer
EXTERN uftofin
PUBLIC hook_catmem
PUBLIC hook_mscat
PUBLIC cat
PUBLIC mslog
PUBLIC ncats3
PUBLIC discan
PUBLIC disca0
PUBLIC cksub
PUBLIC rdfat
PUBLIC wrfata
PUBLIC wrifat
PUBLIC cfile1
catdon: defb 0 ; VARIABLE - number of root dir slots catalogued
clusno: defb 0 ; VARIABLE - catalogue cluster count
cursec: defw 0 ; VARIABLE - current sector being catalogued
discou: defb 0 ; VARIABLE, saved file number within dir
dispos: defw 0 ; VARIABLE, saved addy within dir
hook_catmem:
ex de,hl
ld (dumadd2+1),hl
inc hl
ld (dumadd+1),hl
ld hl,flags3
set 7,(hl)
hook_mscat:
call r_hxfer
call uftofin
jp ncats3
; Catalogue disc routine
; Syntax:
cat: call syntax ; Check for syntax, if !syntax then set stuff up
jr z,cat1
ld a,2 ; Set the default channel
ld (chanel),a
call clfilen ; Clear the filename, hl = filen
ld a,'*' ; Set up wild card checking
ld (hl),a
ld (filen+9),a
cat1: call rout32 ; Look for a channel identifier
cp '#'
jr nz,ncatcd
set 7,(iy+1)
call e32_1n ; Expect one number
cp ',' ; And then a comma or a semicolon
jr z,catcom
cp ';'
jp nz,error_nonsense
catcom: call syntax ; More bit fiddling in syntax mode
jr nz,catco1
res 7,(iy+1)
catco1: call rout32
call syntax ; If in syntax mode, don't get the number off
jr z,ncatcd
call getnum ; Get the stream off the stack
ld a,b
or c
jr nz,stinra
set 7,c
stinra: ld a,c
ld (chanel),a
ncatcd: call gdrive ; Get the drive number
call ckenqu ; Check for end of statement
jr z,ncatc1
cp ';' ; If not end of statement we must have a ';'
jp nz,error_nonsense
call rout32
call exptex ; And then we want a string
call ckend ; So this really is the end
ld hl,filen ; Get the BASIC string into filen
call getstr
jr ncats3
ncatc1: call ckend ; If no string then we must check for the end
; The main catalogue routine itself
ncats3: ld a,(chanel) ; Direct output to the selected channel
call setchan
msccat: call mslog ; Log the disc in
call gsubst ; Setup for subdirectories
xor a ; Initialise num file slots done
ld (catdon),a
ld hl,flags
res 2,(hl) ; Set no files seen flag
msclop: ld de,(cursec)
call chdpr ; Read in and display directory for this sector
call nxdsec ; Get next sector
jr c,msclop ; Loop if there is a next sector
ld hl,flags ; If no files found, print the message
bit 2,(hl)
jr nz,root4
call messag
defm "No files found"
defb 13, 255
root4: ld a,13
call print ; Print a blank line
call free ; Calculate disc space free
ld b,255 ; And then display it b = 255 indicates space
call prhund
call messag
defm "K free"
defb 13, 255
ret
;Find number of free entries in FAT table
;Entry: none
;Exit: hl=number of free K
free: ld bc,713 ;FIXME? Number of clusters available?
ld de,2 ; First free cluster
ld hl,0 ; Set 0 clusters free initially
free1: push de ; Save all parameters
push hl
push bc
call rdnxft ; Get next cluster for de
pop bc
pop hl
ld a,d ; If 0 then it's empty, inc free cluster count
or e
jr nz,free2
inc hl
free2: pop de
inc de ; Increment the cluster
dec bc ; Loop over bc
ld a,b
or c
jr nz,free1
ld de,(diskif+13) ; Get number of sectors in a cluster
ld d,0
call rhlxde ; Multiply the two together
srl h ; Divide by two (since 1 sector=512 bytes)
rr l
ret
;
; Log a disc in - check the boot sector and read the FAT in
;
mslog: ld de,0 ; MSDOS sector 0
call sros
ld hl,sector ; Copy the sector to the diskif area
ld de,diskif
push de ; Save diskif
ld bc,30
ldir
pop hl ; Get it back
ld a,(hl) ; Check the first few bytes for a signature
cp 0Ebh
jr z,mscat2
mscat1: call errorn
defb 67 ;unrecognised disc format
mscat2: inc hl ; skip over second byte since M$ changed it
inc hl ; go to third byte
ld a,(hl)
cp 090h
jr nz,mscat1 ; Invalid, say unrecognised disc format
ld hl,(diskif+17) ; Find number of sectors in root directory
ld b,4
mscat3: srl h
rr l
djnz mscat3
ld (rotlen),hl ; And save the number
ld hl,(diskif+22) ; Sectors per FAT
ld de,(diskif+16) ; Number of FAT copies
ld d,0
call rhlxde
ld de,(diskif+14) ; Number of reserved sectors
ld d,0
add hl,de
ld (rotsta),hl ; Save start of root directory
ld a,(flags3) ; If we're not in subdir
bit 3,a
jr nz,rdfat
ld (cursec),hl ; Set current dir sector to the start of rootdir
;Read in the FAT table
rdfat: ld hl,sros1
jp wrfata
; Write the FAT table
; This function writes it twice
wrifat: ld hl,swos1
call wrfata
jr wrfat0
; Read/write the FAT table
; Entry: hl = sector read/write routine
; Exit: de = next sector after FAT table
wrfata: ld (fatch+1),hl ; Save which routine to use
ld de,(diskif+14) ; Number of reserved sectors
wrfat0: ld b,3 ; Number of sectors in a FAT table
ld hl,fattab ; Address of where the table is
wrfat1: push bc
push hl
push de
fatch: call swos1
pop de
pop hl
pop bc
inc h ; Increment writing position
inc h
inc de ; Increment the MSDOS sector
djnz wrfat1
ret
;Scan a disc for the filename. The filename is stored in filen
;Entry: none
;Exit: nc = no file found
; c = file found and hl = filename
; a = position in dirsector
disca0: ld hl,flags2 ; If reset then start from the start
bit 4,(hl)
jr z,discan
ld de,(dirsol) ; Reread last sector and pick up old values
call sros
ld a,(discou) ; Pick up saved values
ld b,a
ld hl,(dispos)
jr discar ; And jump to end of loop
discan: ld hl,flags2 ; Indicate start from start
res 4,(hl)
ld hl,0
ld (fileno),hl ; Initialise fileno + frepos
ld (catdon),hl ; Initialiase catdon + clusno
call gsubst ; Setup for sub directories
disca1: ld hl,flags2 ; If we're continuing, don't log the disc in
bit 4,(hl)
call z,mslog
disca2: ld de,(cursec) ; Save the current sector
ld (dirsol),de
call sros ; Read it in
ld b,16 ; Number of dir entries per sector
ld hl,sector
disca3: push bc
push hl
call chffil ; Check if this file match spec in filen
jr z,disca5 ; We matched it
pop hl
pop bc
discar: ld de,32 ; Skip to next dir entry
add hl,de
djnz disca3
call nxdsec ; Get the next directory sector
jr c,disca2 ; Keep looping if there is one
ret
; If we matched a file then exit out of the scanning routine
disca5: pop hl ; Get dir entry address back
pop bc ; And count into sector
ld a,b ; Save them so we can be called again
ld (discou),a
ld (dispos),hl
ld a,16 ; Calculate directory number
sub b
scf ; Indicate that we matched a file
ret
; Set up directory variables for subdirectories
; Entry: none
; Exit: none
gsubst: call cksub
ret z
ld de,(sdclus)
jp nxdse6 ;place in curfat, get sector etc..
; Check to see we're inside a subdirectory
; Entry: none
; Exit: z = in subdir, nz = not in
; hl = flags3
cksub: ld hl,flags3
bit 3,(hl)
ret
;Get the next sector - this bit
;of code is often needed so
;dump into subroutine?!?
;Entry: none
;Exit: c = more sectors..
; nc = no more sectors
; hl = sector to read next
nxdsec: call cksub ; Check for being in subdir
jr nz,nxdse2 ; If in subdir then do things differently
call nxdse3 ; hl = (cursec)
ld a,(catdon) ; Add 16 to number of file entries already done
add a,16
ld (catdon),a
ld hl,diskif+17 ; Max number of root directory entries
cp (hl)
ret c ; There is a next sector
nxdse1: and a ; Indicate no more sectors to read
ret
; Now, handle subdirectories
nxdse2: ld hl,clusno ; Add one to current sector within cluster
inc (hl)
ld a,(diskif+13) ; Number of sectors per cluster
cp (hl)
jr nz,nxdse3 ; Not matched, increment cursec and return
ld (hl),0 ; Start at sector 0 within the cluster
ld de,(curfat) ; Get current cluster number
call rdnxft ; And then get the next
jr c,nxdse1 ; There was no next, return and indicate so
nxdse6: ld (curfat),de ; Save the current cluster number
call getsec ; Convert to sector number
ld (cursec),de ; Save it
scf ; Indicate that we have another sector
ret
; Increment the current sector count
; Entry: none
; Exit: c = set
; hl = next sector to read
nxdse3: ld hl,(cursec)
inc hl
ld (cursec),hl
scf
ret
; Handles displaying a directory
; Entry: de = current directory sector
; Exit: none
chdpr: call sros ; Read the sector
ld b,16 ; Number of files per sector
ld hl,sector ; Start of directory
chdpr0: push bc ; Save some registers
push hl
call chffil ; Check the filename
jr nc,chdpr1 ; No file there
call z,pricae ; Print if it matches
chdpr1: pop hl ; Restore registers
pop bc
ld de,32 ; Step to next directory entry
add hl,de
djnz chdpr0 ; And loop
ret
;Checks the directory entry to see it matches the pattern in filen
;Entry: hl = addy of filename in sector
;Exit: hl = unchanged
;Flags:
; c = file at entry
; z = file is match
; nz = file no match
; nz+nc = no file present
; z+nc = end of dir + no file - not valid
chffil: ld a,(fileno) ; Increment position within directory
inc a
ld (fileno),a
ld a,(hl) ; Check to see if file is deleted
cp 0E5h
jr z,chffi2
and a ; Alternate check for deleted file
jr z,chffi2
push hl ; Save address
ld bc,11 ; Go to flags
add hl,bc
bit 3,(hl) ; Check for volume name
pop hl ; Get address back
jr nz,nomatch ; Volume names shouldn't match
push hl ; Save address
call cfilen ; Check filename, return z/nz for matching
pop hl ; Restore address
chffi3: scf ; Indicate that there was a file here
ret
; Exit if there's no file at the position
chffi2: ld a,(frepos) ; If we've no free dir position marked then set
and a ; FIXME: should set to -1 really
ret nz ; (frepos) already contains a file position
ld a,(fileno)
ld (frepos),a ; Save free slot
ld de,(dirsol) ; Save sector where free position is
ld (dirsec),de
nomatch: and a ; nc means no file at position
ret
;Put the CAT o/p into memory
dumadd: ld hl,0
ld bc,12
ex de,hl
ldir ;copy filename + type
ld c,15
add hl,bc
ld c,6
ldir ;copy start cluster & filelength
ex de,hl
ld (dumadd+1),hl
ld a,(fileno)
dumadd2: ld (0),a
pop hl
ret
; Print or dump the directory entry into a buffer
; Entry: hl = directory entry
pricae: push hl ; Save
ld de,flags3
ex de,hl ; de = dir entry, hl = flags3
bit 7,(hl) ; If we're dumping into a buffer, go there
jr nz,dumadd
dec hl
dec hl ; hl = flags
set 2,(hl) ; Indicate that we matched a file
ld bc,8 ; Print out the main part of the filename
call string
ld a,'.'
call print
ld c,3 ; And now the extension
call string
ex de,hl ; hl = dir entry, pointing at dir flags
bit 4,(hl) ; Test to see if directory
jr z,prica1 ; No its not
call messag
defm "<DIR>"
defb 255
jr prica2 ; Skip over file size priting
prica1: ld a,32 ; Print a space
call print
ld c,17 ; Step to filesize in dir entry
add hl,bc
inc hl ; Ignore bits 24-32 since it can't be used
ld e,(hl) ; Pick up bits 8 - 23 of file size
inc hl
ld d,(hl)
srl d ; Divide by 4
rr e
srl d
rr e
ex de,hl
ld b,255 ; Display leading spaces
call prhund
ld a,'K' ; It's always in K
call print
prica2: ld a,13 ; Print a line feed
call print
pop hl ; Restore dir entry
ret
;Check the filename to see it matches the spec in filen
;Entry: hl = filename in direc
;Exit: z = file is match
; nz = file doesn't match
cfilen: push hl ; Save address in directory
ld de,filen ; filen contains the file pattern
ld b,8 ; Compare 8 characters
call cfile1
pop hl ; Get dir address back
ret nz ; We didn't match at all
ld bc,8 ; Matched, skip to extension
add hl,bc
ld de,filen+9 ; Load up filen extension
ld b,3 ; Extensions have 3 characters
cfile1: ld a,(de) ; If matching pattern contains a '*' then match
cp '*'
ret z
cp '?' ; A '?' matches any character
jr z,cfile2
xor (hl) ; Does a case insensitive match
and 223
ret nz ; Doesn't match
cfile2: inc de ; We matched carry on looping
inc hl
djnz cfile1
ret ; Will return z if we get to the end