.z80 title DISKSTAT Disk statistics name ('DISKST') ;------------------------------------------------------------------ ; Utility to display disc characteristics and file allocation ; ; Copyright 1983 D. Powys-Lybbe ; Author: D. Powys-Lybbe, MML Systems Ltd., London ; Date: 20th June 1983 ; ;------------------------------------------------------------------ ; Revisions ; ========= ; ;------------------------------------------------------------------ ;------------------------------------------------------------------------ page public def.dsk,dpb,dph2,dph3,dpb.ptr,dph.ptr,vers,vers.rel,vers.os public savesp public BADSEL,selmsg,badvers,vermsg,BIOS,badbios,jmpmsg public BIOSPB,BIOS.FUNC,BIOS.AREG,BIOS.BCREG,BIOS.DEREG,BIOS.HLREG public waitcr,waitbuff,waitlen,fetchdp public clearscrn,csnmsg,screen1,s1msg,s1dsk public option,optquit,optmsg,optbuf,optlen,optchr public makehex,wrdhex,dblhex,bythex,nblhex,testhex,nexthex public hexchr,hextxt public makedec,dec2,errdec,gigdec,megdec,wrddec,bytdec,txtdec,zrobcd public tobcd,bcd,testdec,nextdec,decchr,dectxt public makemax,makem1,makem2,makem3,makem4,makem5,makem6,makem8 public makem7,makem9,make01,make02,make03,make04,makem0 public makedir,dirdb,dbsize,maked0,maked1,maked2,maked3,maked4 public makedat,maked5,maked6 public maketot,maked7,maked8 public mmegx8,mmegx4,mmegx2,mgigx8,mgigx4,mgigx2,mgigx128 public showblk,posn,sdbmsg,sdbdsk,sdbhex,sdbdec,sdbmax public sdbdir,sdbdat,sdbtot public showhdr public showalv,salmsg,saldsk public showfil,sflmsg,sfldsk public showdir,sdrmsg,sdrdsk public goodvers,useccp,main,task1,table1,return ;------------------------------------------------------------------------ page ; =============== ; DISC DATA AREAS ; =============== ;-------------------------------------------------------------- ; ; CP/M disc parameters ; ;-------------------------------------------------------------- dseg def.dsk: db 0 ; Selected disc dpb: ; Drive disk parameter block dpb.spt: ds 2 dpb.bsh: ds 1 dpb.blm: ds 1 dpb.exm: ds 1 dpb.dsm: ds 2 dpb.drm: ds 2 dpb.al0: ds 1 dpb.al1: ds 1 dpb.cks: ds 2 dpb.off: ds 2 len.dpb2 equ $-dpb ; length of CP/M 2 dpb dpb.psh: ds 1 dpb.phm: ds 1 len.dpb3 equ $-dpb ; length of CP/M + dpb dph2: ; CP/M 2 disk parameter header dph2.xlt: ds 2 dph2.zro: ds 6 dph2.dir: ds 2 dph2.dpb: ds 2 dph2.csv: ds 2 dph2.alv: ds 2 len.dph2 equ $-dph2 ; length of CP/M 2 dph dph3: ; CP/M + disk parameter header dph3.xlt: ds 2 dph3.zro: ds 9 dph3.mf: ds 1 dph3.dpb: ds 2 dph3.csv: ds 2 dph3.alv: ds 2 dph3.dir: ds 2 dph3.dat: ds 2 dph3.hsh: ds 2 dph3.bnk: ds 1 len.dph3 equ $-dph3 ; length of CP/M + dph dpb.ptr: dw 0 ; address of dpb dph.ptr: dw 0 ; address of dph vers: ; O.S. Version number vers.rel: ds 1 ; O.S. Version/Release number vers.os: ds 1 ; O.S. number posn: dw 0 ; pointer to text string ; ------; ; stack ; ; ------; ds 64 ; dont know how much stack BIOS requires savesp: dw 0 ; ----------------; ; address equates ; ; ----------------; bdos equ 5 ; BDOS entry point deffcb equ 5ch ; CCP puts default FCB here defdma equ 80h ; CCP sets default DMA here ; -----------------; ; constant equates ; ; -----------------; bs equ 08h ; cr equ 0dh ; lf equ 0ah ; jump equ 0c3h ; JP instruction cseg ;-------------------------------------------------------------------------; page ;-------; ; start ; ;-------; cseg ld c,12 ; BDOS: RETURN VERSION NUMBER call bdos ld (vers),hl ld a,h cp 00h ; check for CP/M jp nz,badvers ; ld a,l cp 22h jp z,goodvers ; ld a,l cp 31h jp z,goodvers page ; ================= ; ; various utilities ; ; ================= ; ; -------------- ; ; Error routines ; ; -------------- ; BADSEL: ld de,selmsg ld c,9 ;BDOS: PRINT STRING call bdos ld c,0 ;BDOS: SYSTEM RESET jp bdos ; and crash out dseg selmsg: db 'FATAL ERROR - Unable to select drive','$' cseg badvers: ld de,vermsg ld c,9 ;BDOS: PRINT STRING jp bdos ; & RETURN dseg vermsg: db 'MUST USE CP/M 2.2 OR CP/M 3.1','$' cseg ; --------------------------- ; ; Direct calls to CP/M 2 BIOS ; ; --------------------------- ; BIOS: push de ; must save DE as sometimes passed to BIOS ex de,hl ld hl,(1) ; pointer to BIOS WARM BOOT ld a,(hl) cp jump ; check actually pointing to BIOS (not XSUB) jp nz,badbios add hl,de ; DE = offset from WARM BOOT to BIOS function pop de ld a,(hl) cp jump ; check actually pointing to BIOS (not XSUB) jp nz,badbios jp (hl) badbios: ; (NOTE DE may be on stack) ld de,jmpmsg ld c,9 ;BDOS: PRINT STRING call bdos ld c,0 ;BDOS: SYSTEM RESET jp bdos ; and crash out dseg jmpmsg: db 'FATAL ERROR - Unable to find BIOS','$' cseg ; --------------------------- ; ; Direct calls to CP/M 3 BIOS ; ; --------------------------- ; dseg BIOSPB: BIOS.FUNC: ds 1 ; BIOS function number (WARM BOOT = 1) BIOS.AREG: ds 1 ; A register contents BIOS.BCREG: ds 2 ; BC register contents BIOS.DEREG: ds 2 ; DE register contents BIOS.HLREG: ds 2 ; HL register contents cseg page ; ------------------------------ ; ; Conversion into HEX characters ; ; ------------------------------ ; ;-----------------------------------------------------------------------; ; HEXBYT ; ; Input: = Count of bytes to be converted ; ; -> first byte to be translated ; ; POSN = pointer to text field ; ; Destroys: All registers ; ; Function: Converts bytes starting at into 2 digit ; ; hexadecimal characters which are added to next ; ; hexadecimal field in the text string. POSN is updated ; ; to point to the end of this hexadecimal field. ; ;-----------------------------------------------------------------------; ;-----; hexbyt: ;-----; push hl push bc ld a,(hl) call bythex pop bc pop hl inc hl djnz hexbyt ret ;-----------------------------------------------------------------------; ; HEXTBL ; ; Input: = Count of bytes to be converted ; ; -> start of array of byte to be translated ; ; -> start of table of conversion formats ; ; 1 = single byte ; ; 2 = pair of bytes to be combined as one word ; ; 3 = pair of bytes to reversed in text fields ; ; POSN = pointer to text field ; ; Destroys: All registers ; ; Function: Converts bytes starting at according to ; ; format type in table pointed at by . Each entry ; ; in the table corresponds to field positions. ; ;-----------------------------------------------------------------------; ;-----; hextbl: ;-----; ld a,(de) push de cp 2 jp z,hextbl2 cp 3 jp z,hextbl3 ; byte ld a,(hl) push bc push hl call bythex jp nxttbl ; word hextbl2: dec b ; decrement as using two bytes push bc ld e,(hl) inc hl ld d,(hl) push hl ex de,hl call wrdhex ; -> text jp nxttbl ; double byte hextbl3: dec b ; decrement as using two bytes push bc inc hl ld a,(hl) ; display 2nd byte first dec hl push hl call bythex pop hl ld a,(hl) ; display 1st byte next inc hl push hl call bythex nxttbl: pop hl pop bc pop de inc de inc hl djnz hextbl ret ;-----------------------------------------------------------------------; ; WRDHEX ; ; Input: = word to converted into hexadecimal text ; ; POSN = pointer to text field ; ; Destroys: All registers ; ; Function: Converts word in into four hexadecimal characters ; ; which are added to next hexadecimal field in the ; ; text string. POSN is updated to point to the end ; ; of this hexadecimal field. ; ;-----------------------------------------------------------------------; ;-----; wrdhex: ; display hex word in into text ;-----; push hl ; must preserve HL call nexthex ; returns DE -> 'h' dec de dec de dec de dec de pop hl push hl ld a,h call outnbl pop hl ld a,l call outnbl ret ;-----------------------------------------------------------------------; ; DBLHEX ; ; Input: = word to converted into hexadecimal text ; ; POSN = pointer to text field ; ; Destroys: All registers ; ; Function: Converts word in into two pairs of hexadecimal ; ; characters with the high byte displayed first. Each is ; ; added to the next hexadecimal field in the text string. ; ; POSN is updated to point to the end of the second ; ; is hexadecimal field. ; ;-----------------------------------------------------------------------; ;-----; dblhex: ; display high hex byte into text ;-----; ld a,h push hl call bythex pop hl ; display high hex byte into text ld a,l jp bythex ;-----------------------------------------------------------------------; ; BYTHEX ; ; Input: = byte to converted into hexadecimal text ; ; POSN = pointer to text field ; ; Destroys: All registers ; ; Function: Converts byte in into two hexadecimal characters ; ; which are added to next hexadecimal field in the ; ; text string. POSN is updated to point to the end ; ; of this hexadecimal field. ; ;-----------------------------------------------------------------------; ;-----; bythex: ; converts byte in into hexadecimal text ;-----; push af call nexthex ; returns DE -> 'h' dec de dec de pop af call outnbl ret ;-----; outnbl: ; convert byte in into two hex chars at ;-----; push af rrca rrca rrca rrca call nblhex pop af ;-----; nblhex: ; convert nibble in A into hex char in (DE) ;-----; and 0fh ld c,a ld b,0 ld hl,hextxt add hl,bc ld a,(hl) ld (de),a inc de ret ;-----------------------------------------------------------------------; ; NEXTHEX ; ; Input: POSN = pointer to text field ; ; Returns: -> to end of hexadecimal filed ; ; Destroys: , , ; ; Function: Starting at location (POSN), scans text for hexadecimal ; ; field of the form ??h or ????h where ? is any valid ; ; hexadecimal character (0123456789ABCDEF). POSN is ; ; updated to point to the end of this hexadecimal field. ; ;-----------------------------------------------------------------------; testhex: cp cr ; check if end of line, as must not pass this ret z ; even if this means overwriting text. ;------; nexthex: ; find next hex location in text ;------; call hexchr ; find first hex character jp nz,testhex call hexchr ; find second hex character jp nz,testhex inc de ld a,(de) cp 'h' jp nz,testhex ret hexchr: ld hl,(posn) inc hl ld a,(hl) ld d,h ld e,l cp cr ; test for end of line ret z ld (posn),hl ; update POSN ld hl,hextxt ld b,16 nxt1: cp (hl) ret z inc hl djnz nxt1 or -1 ret dseg hextxt: db '0123456789ABCDEF' cseg page ; ================= ; ; various functions ; ; ================= ; ; ------------------------------ ; ; Wait for for keyboard ; ; ------------------------------ ; waitcr: ld de,crmsg ld c,9 ;BDOS: PRINT STRING call bdos ld c,10 ; DIRECT CONSOLE BUFFER ld de,waitbuff call bdos ld a,(waitlen) or a ret z jp waitcr dseg crmsg: db cr,lf,'Hit to continue ','$' waitbuff: db 1 waitlen: ds 1 ds 1 cseg ; ---------------------------- ; ; Fetch DPH and DPB for device ; ; ---------------------------- ; fetchdp: call getdpb ld a,(vers.rel) cp 22h call z,getdph2 ld a,(vers.rel) cp 31h call z,getdph3 ret ; ---------------- ; ; Fetch CP/M 2 DPH ; ; ---------------- ; getdph2: ld a,(def.dsk) ; Current selected disk ld c,a ; BIOS: Disk drive to select ld e,-1 ; Not first time login ld hl,001bh-0003h ; offset from WARM BOOT to select function call BIOS ld a,l or h jp z,badsel ld (dph.ptr),hl ; save address of DPH ld de,dph2 ld bc,len.dph2 ldir ret ; ---------------- ; ; Fetch CP/M + DPH ; ; ---------------- ; getdph3: ld a,(def.dsk) ; Current selected disk ld (BIOS.BCREG),a ; save in BIOSPB ld hl,-1 ; Not first time login ld (BIOS.DEREG),hl ; save in BIOSPB ld a,9 ; BIOS: select the sepcified disk drive ld (BIOS.FUNC),a ; save in BIOSPB ld c,50 ;BDOS: DIRECT BIOS CALL ld de,BIOSPB ; BIOS parameter block call bdos ; IMPORTANT: dont trace this as BDOS ; copies DPH into keyboard character buffer ld a,l ; BDOS returns address of its copy of DPH or h jp z,badsel ld (dph.ptr),hl ; save address of DPH but this is of no value ld de,dph3 ld bc,len.dph3 ldir ret ; --------- ; ; Fetch DPB ; ; --------- ; getdpb: ld c,31 ;BDOS: GET ADDR (DPB PARMS) call bdos ld (dpb.ptr),hl ; save address of DPB ld de,dpb ld bc,len.dpb3 ; copy maximum length regardless ldir ret ;--------; clearscrn: ; clear screen ;--------; ld de,csnmsg ld c,9 ;BDOS: PRINT STRING jp bdos ; & RETURN dseg csnmsg: db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf db cr,lf,lf,lf,lf,lf,'$' ; 25 line feeds cseg ;------; screen1: ; display menu ;------; ld a,(def.dsk) add a,'A' ld (s1dsk),a ld de,s1msg ld c,9 ;BDOS: PRINT STRING jp bdos ; & RETURN dseg s1msg: db cr,'MML:DISKSTAT DRIVE ' s1dsk: db 'A: CHARACTERISTICS ' db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf ; 10 line feeds db cr,lf,' 1 Display DPB statistics ' db cr,lf,' 2 Display DPH statistics ' db cr,lf,' 3 Display disk ALLOCATION ' db cr,lf;later,' 4 Display file ALLOCATION ' db cr,lf;later,' 5 Display directory ALLOCATION ' db cr,lf,' 9 Select new disk ' db cr,lf,lf,lf,lf,'$' ; 5 line feeds cseg ;-----; option: ; request option ;-----; ld de,optmsg ld c,9 ;BDOS: PRINT STRING call bdos ld de,optbuf ld c,10 ;BDOS: READ CONSOLE BUFFER call bdos ld a,(optlen) cp 0 jp z,optquit cp 1 jp nz,option ld a,(optchr) cp '1' jp c,option cp '9'+1 jp nc,option ; value in range 1 to 9 sub '0' ret optquit: or -1 ret dseg optmsg: db cr,' Enter your choice, or ',bs,bs,'$' optbuf: db 2 ; maximum length of buffer optlen: ds 1 ; number of characters returned optchr: ds 2 ; space for up to 2 characters cseg ;------; makehex: ; module in showblk ;------; ; ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ' ;sdbbyt ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h' ; ' SPT BSH BLM EXM DSM DRM AL0-AL1 CKS OFF PSH PHM' ;sdbhex ' 0000h 00h 00h 00h 0000h 0000h 00h 00h 0000h 0000h 00h 00h' ld hl,sdbbyt ld (posn),hl ld a,(vers.rel) cp 31h jp z,makeh3 xor a ; CP/M 2 does not have PSH & PHM ld (dpb.psh),a ; - set to zero ld (dpb.phm),a makeh3: ld hl,dpb ld b,17 call hexbyt ld hl,sdbhex ld (posn),hl ld hl,dpb ld b,17 ld de,hbtype call hextbl ret dseg hbtype: db 2,1,1,1,2,2,1,1,2,2,1,1 cseg ;------; makedec: ; module in showblk ;------; ld hl,sdbdec ld (posn),hl ld hl,(dpb.spt) call wrddec ; -> text ld a,(dpb.bsh) call bytdec ; -> text ld a,(dpb.blm) call bytdec ; -> text ld a,(dpb.exm) call bytdec ; -> text ld hl,(dpb.dsm) call wrddec ; -> text ld hl,(dpb.drm) call wrddec ; -> text ld a,(dpb.al0) call bytdec ; -> text ld a,(dpb.al1) call bytdec ; -> text ld hl,(dpb.cks) call wrddec ; -> text ld hl,(dpb.off) call wrddec ; -> text ld a,(vers.rel) cp 31h jp nz,dec2 ld a,(dpb.psh) call bytdec ; -> text ld a,(dpb.phm) call bytdec ; -> text ret dec2: xor a call bytdec ; -> text xor a call bytdec ; -> text ret errdec: ; fill display with 3 asterisks as error call nextdec ; -> leftmost digit ld a,'*' ; set 1st 3 digits to '*' ld (de),a dec de ld (de),a dec de ld (de),a ret bytdec: ; display byte in A as decimal characters ld h,0 ld l,a wrddec: ; display word in HL as decimal characters ld bc,0 jp txtdec megdec: ; display byte,word in C & HL as decimal characters ld b,0 gigdec: ; display double word in BC & HL as decimal characters txtdec: ex de,hl push de ; save 4 bytes of binary number push bc call nextdec ; -> leftmost digit pop bc pop de call tobcd ; converts , , , into bcd at BCD ld hl,(posn) ex de,hl ; recover -> leftmost digit ld a,'0' ; initialise 1st digit to a zero ld (de),a ; (just to make sure ) ld hl,bcdlsb ; start with least significent digit txtdec1: call txtbcd ret z dec hl jp txtdec1 ; continue till all 10 digits done txtbcd: ; HL -> bcd digit, -> txt postion call zrobcd ; zero when no more BCD digits (destroys , ) ret z ld a,(hl) add a,'0' ld (de),a dec de xor a ld (hl),a ; zero BCD byte ESSENTIAL to exit when done or -1 ret zrobcd: ; test for all bytes of BCD being zero ; this is important as eventually all bytes ; will be set to zero during transfer to text push hl ld hl,bcd xor a ld b,10 nxtzro: or (hl) inc hl djnz nxtzro pop hl ret ;----; tobcd: ; print binary number 0-65535 from ;----; ld hl,binary ld (hl),e ; least significant digit inc hl ld (hl),d inc hl ld (hl),c inc hl ld (hl),b ; most significent digit push bc ld hl,bcd ld b,10 xor a setbcd: ld (hl),a inc hl djnz setbcd ; first zero all digits pop bc ld a,b or a jp nz,upgig ld a,c or a jp nz,upmeg ld a,d or a jp nz,upwrd ld a,e or a jp nz,upbyt ret ; number is zero so return upbyt: ld bc,bcdbyt ; start of BCD pointer ld hl,byt10 jp upnxt upwrd: ld bc,bcdwrd ; start of BCD pointer ld hl,wrd10 jp upnxt upmeg: ld bc,bcdmeg ; start of BCD pointer ld hl,meg10 jp upnxt upgig: ld bc,bcdgig ; start of BCD pointer ld hl,gig10 ; upnxt: ld de,binary ; binary number to be converted push bc ; save BCD pointer ld c,-1 pdecl: push hl push de inc c xor a ld b,4 ndecl: ld a,(de) adc a,(hl) ld (de),a ; and reduce count inc de inc hl djnz ndecl ; this doesnt effect any flags pop de pop hl jp c,pdecl ; repeatedly subtract amount till carry set push hl push de xor a ld b,4 nincl: ld a,(de) sbc a,(hl) ld (de),a ; and increase inc de inc hl djnz nincl ; this doesnt effect any flags pop de inc sp inc sp ; loose (digits) saved on stack ld a,c pop bc ; pointer to BCD ld (bc),a inc bc ld a,(hl) or a jp nz,upnxt ret dseg bcd: ; 10 bytes, 10 digits of BCD text bcdgig: ; max number is 4294967295 bcd.0: db 4 bcd.1: db 2 bcdmeg: ; max number is 16777215 bcd.2: db 9 bcd.3: db 4 bcd.4: db 9 bcdwrd: ; max number is 65535 bcd.5: db 6 bcd.6: db 7 bcdbyt: ; max number is 255 bcd.7: db 2 bcd.8: db 9 bcdlsb: bcd.9: db 5 gig10: dw 13824,-15259 ; -1000000000 (C465 3600H) dw 7936, -1526 ; -100000000 (FA0A 1F00H) meg10: dw 27008, -153 ; -10000000 (FF67 6980H) dw -16960, -16 ; -1000000 (FFF0 BDC0H) dw 31072, -2 ; -100000 (FFFE 7960H) wrd10: dw -10000, -1 ; -10000 (FFFF D8F0H) dw -1000, -1 ; -1000 (FFFF FC18H) byt10: dw -100, -1 ; -100 (FFFF FF9CH) dw -10, -1 ; -10 (FFFF FFF6H) dw -1, -1 ; -1 (FFFF FFFFH) dw 0, 0 ; 0 (0000 0000H) this terminates all binary: db 0,0,0,0 ; binary number filled from E, D, C, & B cseg testdec: cp cr ret z nextdec: ; find next dec location in text and convert to space ; and return DE -> to end of 00h string call decchr ; find first dec character jp nz,testdec nxt3: ld a,' ' ; erase each digit as we go ld (de),a call decchr ; scan subsequent dec characters jp z,nxt3 dec de ld a,'0' ld (de),a ; initialise 1st digit to a zero ex de,hl ld (posn),hl ret decchr: ld hl,(posn) inc hl ld a,(hl) ld d,h ld e,l cp cr ret z ld (posn),hl ld hl,dectxt ld b,11 nxt2: cp (hl) ret z inc hl djnz nxt2 or -1 ret dseg dectxt: db '0123456789+*' ; + used for bit flag, * used for errors cseg ;------; makemax: ; module in showblk ;------; ;' BLOCK EXTENT MAX DISK DIRECTORY CHECK SUM SECTOR' ;' SIZE (K) FOLDS SIZE (K) ENTRIES ENTRIES SIZE' ;'DPB(DEC): 16K 15 1048576 65536 65536 32768' ld hl,sdbmax ld (posn),hl ld a,(dpb.bsh) ld hl,128 or a jp z,makem2 makem1: add hl,hl dec a jp nz,makem1 makem2: ld a,h ; /256 rrca ; /512 rrca ; /1024 push af ld a,(dpb.blm) ld bc,-128 or a jp z,makem4 makem3: add hl,bc dec a jp nz,makem3 makem4: add hl,bc pop af ; recover K ld b,a ; and save ld a,h or l ld a,b push af call nz,errdec pop af call z,bytdec ; -> text ld a,(dpb.blm) add a,1 ;+1 rra rra rra ;/8 ld b,a ; save EXM+1 ld hl,(dpb.dsm) xor a ; (there must be an easier way) sub h dec a ccf adc a,h ; a = 0 if H = 0, else a = -1 and b add a,b add a,-1 ;-1 (convert into EXM) ld b,a ; and save ld a,(dpb.exm) cp b push af call nz,errdec pop af call z,bytdec ; -> text xor a ld hl,(dpb.dsm) ld bc,1 add hl,bc ; increment dsm by 1 adc a,0 ld c,a ; and save in C ld a,(dpb.bsh) add a,-3 ld b,a or a ld a,c ; giga byte jp z,makem6 makem5: add hl,hl adc a,0 djnz makem5 makem6: ld c,a call megdec ; & -> text xor a ld hl,(dpb.drm) ld bc,1 add hl,bc ; increment drm by 1 adc a,0 ld c,a call megdec ; & -> text ld hl,(dpb.drm) ld a,h and a rra ld h,a ld a,l rra ld l,a ; /2 ld a,h and a rra ld h,a ld a,l rra ld l,a ; /4 ld d,h ld e,l inc de ; DE=HL+1 ld hl,(dpb.cks) ld a,h or l jp z,makem8 ; no check sum ld a,h and 7fh or l jp z,makem7 ; bit 15 set for non removable sbc hl,de ex de,hl jp z,makem8 call errdec jp makem9 makem8: ld c,0 call mmegx4 ; , * 4 call megdec ; & -> text jp makem9 makem7: xor a call nextdec dec de ld a,'+' ld (de),a inc de inc de makem9: ld a,(vers.rel) cp 31h jp nz,makem0 ld a,(dpb.psh) ld hl,128 or a jp z,make02 make01: add hl,hl dec a jp nz,make01 make02: push hl ld a,(dpb.phm) ld bc,-128 or a jp z,make04 make03: add hl,bc dec a jp nz,make03 make04: add hl,bc ld a,h or l pop hl push af call nz,errdec pop af call z,wrddec ; -> text ret makem0: ld hl,128 ; CP/M 2 sector size call wrddec ; -> text ret ;--------; makedir: ; module in showblk ;--------; ;' Data 1K 128 byte ' ;' Blocks Blocks Records Capacity' ;' Directory 65535 16777215 16777215 16777215 Entries' ;' Data 65535 16777215 16777215 4294967296 Bytes' ;' 65000 16777215 16777215' dseg dirdb: db 0 ; save number of director blocks dbsize: db 0 ; save data block size in K cseg ld hl,sdbdir ld (posn),hl ld hl,(dpb.al0) xor a ld b,16 maked0: add hl,hl adc a,0 djnz maked0 ; number of directory data blocks ld (dirdb),a call bytdec ; -> text ld a,(dpb.bsh) ld hl,128 or a jp z,maked2 maked1: add hl,hl dec a jp nz,maked1 maked2: ld a,h ; /256 rrca ; /512 rrca ; /1024 ld (dbsize),a ; save data block size in K ld c,a ld b,0 ld a,(dirdb) ld hl,0 or a jp z,maked4 maked3: add hl,bc dec a jp nz,maked3 maked4: push hl call wrddec ; -> text pop hl ld c,0 call mmegx8 ; multiply by 8 push hl push bc call megdec ; number of records ( & -> text) pop bc pop hl call mmegX4 ; multiply by 4 call megdec ; number of entries ( & -> text) ret ;--------; makedat: ; module in showblk ;--------; ;' Data 1K 128 byte ' ;' Blocks Blocks Records Capacity' ;' Directory 65535 16777215 16777215 16777215 Entries' ;' Data 65535 16777215 16777215 4294967296 Bytes' ;' 65000 16777215 16777215' ld hl,sdbdat ld (posn),hl ld hl,(dpb.dsm) ; total disk blocks ld a,(dirdb) ; blocks reserved for directory dec a ld c,a ld b,0 sbc hl,bc ; leaving number of data blocks push hl call wrddec ; -> text pop hl xor a ld b,a ld c,a ; BC = 0 ld a,(dpb.blm) inc a rrca rrca rrca ; /8 dec a or a jp z,maked6 maked5: push af call mgigx2 pop af dec a jp nz,maked5 maked6: push bc push hl call gigdec ; 1K blocks ( & -> text) pop hl pop bc call mgigx8 ; multiply B,C,H,& L by 8 push hl push bc call gigdec ; number of records ( & -> text) pop bc pop hl call mgigx128 ; multiply B,C,H,& L by 128 call gigdec ; number of bytes ( & -> text) ret ;--------; maketot: ; module in showblk ;--------; ;' Data 1K 128 byte ' ;' Blocks Blocks Records Capacity' ;' Directory 65535 16777215 16777215 16777215 Entries' ;' Data 65535 16777215 16777215 4294967296 Bytes' ;' 65000 16777215 16777215' ld hl,sdbtot ld (posn),hl xor a ld bc,1 ld hl,(dpb.dsm) ; total disk blocks add hl,bc adc a,a ld c,a push bc push hl call wrddec ; -> text pop hl pop bc ld a,(dpb.blm) inc a rrca rrca rrca ; /8 dec a or a jp z,maked8 maked7: push af call mgigx2 pop af dec a jp nz,maked7 maked8: push bc push hl call gigdec ; 1K blocks ( & -> text) pop hl pop bc call mgigx8 ; multiply B,C,H,& L by 8 call gigdec ; number of records ( & -> text) ret mmegx8: call mmegx2 ; multiply C,H,& L by 8 mmegx4: call mmegx2 ; multiply C,H,& L by 4 mmegx2: ld a,l ; multiply C,H,& L by 2 add a,a ld l,a ld a,h adc a,a ld h,a ld a,c adc a,a ld c,a ret mgigx8: call mgigx2 ; multiply B,C,H,& L by 8 mgigx4: call mgigx2 ; multiply B,C,H,& L by 4 mgigx2: ld a,l ; multiply B,C,H,& L by 2 add a,a ld l,a ld a,h adc a,a ld h,a ld a,c adc a,a ld c,a ld a,b adc a,a ld b,a ret mgigx128: ; multipy B,C,H,& L by 128 ld a,b and a rra ; we can only use lowest bit ld a,c rra ld b,a ld a,h rra ld c,a ld a,l rra ld h,a ld a,0 rra ld l,a ret ;------; showblk: ; menu 1 option 1 Display DPB statistics ;------; ld a,(def.dsk) add a,'A' ld (sdbdsk),a call makehex call makedec call makemax call makedir call makedat call maketot ld de,sdbmsg ld c,9 ;BDOS: PRINT STRING call bdos call waitcr ret dseg sdbmsg: db cr, ' DRIVE ' sdbdsk: db 'A: DISC PARAMETER BLOCK' db cr,lf db cr,lf,' ' db ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ' db cr,lf,'DPB: ' sdbbyt: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h' db cr,lf db cr,lf,' ' db ' SPT BSH BLM EXM DSM DRM AL0-AL1 CKS OFF PSH PHM' db cr,lf,'DPB(HEX):' sdbhex: db ' 0000h 00h 00h 00h 0000h 0000h 00h 00h 0000h 0000h 00h 00h' db cr,lf,'DPB(DEC):' sdbdec: db ' 65535 255 255 255 65535 65535 255 255 65535 65535 255 255' db cr,lf db cr,lf,' BLOCK EXTENT MAX DISK DIRECTORY CHECK SUM SECTOR' db cr,lf,' ' db 'SIZE (K) FOLDS SIZE (K) ENTRIES ENTRIES SIZE' db cr,lf,'DPB(DEC): ' sdbmax: db ' 16K 15 1048576 65536 65536 32768' sdberr: db cr,lf,' ' db cr,lf db cr,lf,'ALLOCATION OF DISK BLOCKS' db cr,lf,' Data 1K 128 byte ' db cr,lf,' Blocks Blocks Records Capacity' db lf sdbdir: db cr,lf,' Directory 65535 16777215 16777215 16777215 Entries' sdbdat: db cr,lf,' Data 65535 16777215 16777215 4294967296 Bytes' db cr,lf,' -------- -------- --------' sdbtot: db cr,lf,' 65000 16777215 16777215' db lf db '$' cseg ;------; makedph3: ; menu 1 option 2 Display DPH statistics ;------; ; ' 0 1 2 3 4 5 6 7 8 9 10 11 ' ;s3byt1 ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' ; ' 12 13 14 15 16 17 18 19 20 21 22 23 24 ' ;s3byt2 ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' ; ' XLT -0- -0- -0- -0- -0- -0- -0- -0- -0- MF ' ;s3hex1 ' 0000h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' ; ' DPB CSV ALV DIRBCB DTABCB HASH HBANK' ;s3hex2 ' 0000h 0000h 0000h 0000h 0000h 0000h 00h ' ld hl,s3byt1 ld (posn),hl ld hl,dph3 ld b,12 call hexbyt push hl ld hl,s3byt2 ld (posn),hl pop hl ld b,13 call hexbyt ld hl,s3hex1 ld (posn),hl ld hl,dph3 ld de,h3type ld b,12 call hextbl push hl ld hl,s3hex2 ld (posn),hl pop hl ld b,13 call hextbl ret dseg h3type: db 2,1,1,1,1,1,1,1,1,1,1 db 2,2,2,2,2,2,1 cseg ;------; makedph2: ; menu 1 option 2 Display DPH statistics ;------; ; ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ' ;s2byt ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' ; ' XLT -0- -0- -0- -0- -0- -0- DIRBCB DPB CSV ALV ' ;s2hex ' 0000h 00h 00h 00h 00h 00h 00h 0000h 0000h 0000h 0000h ' ld hl,s2byt ld (posn),hl ld hl,dph2 ld b,16 call hexbyt ld hl,s2hex ld (posn),hl ld hl,dph2 ld de,h2type ld b,16 call hextbl ret dseg h2type: db 2,1,1,1,1,1,1,2,2,2,2 ; 11 fields cseg ret ;------; showhdr: ; menu 1 option 2 Display DPH statistics ;------; ld a,(vers.rel) cp 31h call z,outdph3 ld a,(vers.rel) cp 22h call z,outdph2 ret ;------; outdph3: ; menu 1 option 2 Display DPH statistics ;------; ld a,(def.dsk) add a,'A' ld (sh3dsk),a call makedph3 ld de,sh3msg ld c,9 ;BDOS: PRINT STRING call bdos call waitcr ret dseg sh3msg: db cr,' DRIVE ' sh3dsk: db 'A: DISK PARAMETER HEADER' db cr,lf db cr,lf,' ' db ' 0 1 2 3 4 5 6 7 8 9 10 11 ' db cr,lf,'DPH(HEX):' s3byt1: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' db cr,lf db cr,lf,' ' db ' 12 13 14 15 16 17 18 19 20 21 22 23 24 ' db cr,lf,'DPH(HEX):' s3byt2: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' db cr,lf db cr,lf,' ' db ' XLT -0- -0- -0- -0- -0- -0- -0- -0- -0- MF ' db cr,lf,'DPH(HEX):' s3hex1: db ' 0000h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' db cr,lf db cr,lf,' ' db ' DPB CSV ALV DIRBCB DTABCB HASH HBANK' db cr,lf,'DPH(HEX):' s3hex2: db ' 0000h 0000h 0000h 0000h 0000h 0000h 00h ' db cr,lf db lf,lf,lf,lf,lf,lf,lf,lf db '$' cseg ;------; outdph2: ; menu 1 option 2 Display DPH statistics ;------; ld a,(def.dsk) add a,'A' ld (sh2dsk),a call makedph2 ld de,sh2msg ld c,9 ;BDOS: PRINT STRING call bdos call waitcr ret dseg sh2msg: db cr,' DRIVE ' sh2dsk: db 'A: DISK PARAMETER HEADER' db cr,lf db cr,lf,' ' db ' 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ' db cr,lf,'DPH(HEX):' s2byt: db ' 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h 00h ' db cr,lf db cr,lf,' ' db ' XLT -0- -0- -0- -0- -0- -0- DIRBCB DPB CSV ALV ' db cr,lf,'DPH(HEX):' s2hex: db ' 0000h 00h 00h 00h 00h 00h 00h 0000h 0000h 0000h 0000h ' db cr,lf,lf,lf,lf,lf,lf,lf db lf,lf,lf,lf,lf,lf,lf,lf db '$' cseg page ; -------------------------------------------- ; ; utilities used in allocation vector analysis ; ; -------------------------------------------- ; dseg lenalv: ds 2 ; length of allocation vector in bytes alvdir: ds 2 ; datablocks allocated to directory alvdat: ds 2 ; datablocks allocated to data alvzro: ds 2 ; datablocks not allocated alvera: ds 2 ; datablocks allocated to erased data alvlst: ds 2 ; datablocks allocated to overwritten data alvbad: ds 2 ; datablocks with duplicated data access alvrng: ds 2 ; datablocks outside maximum number alvlen equ $-lenalv user: db 0 ; save user number cseg ;--; alv: ; return = /8, & = mod 7 ;--; ld c,0 call alv1 ; /2 call alv1 ; /4 call alv1 ; /8 ld a,c rlca rlca rlca ld c,a ret alv1: ld a,h and a rra ld h,a ld a,l rra ld l,a ; = / 2 ld a,c rra ld c,a ; C contains lost bits ret tstbit: ; tst bit number at offset from ALLOC ; return CF=NZ if bit already set push bc push hl ld hl,bitmap ld b,0 add hl,bc ld a,(hl) ; bit to set ld bc,alloc pop hl push hl add hl,bc ld b,a ; save bit to set ld a,(hl) and b ; test if bit set pop hl pop bc ret ; 0 = if not set, > 0 if set setbit: ; set bit number at offset from ALLOC ; return CF=NZ if bit already set push bc push hl ld hl,bitmap ld b,0 add hl,bc ld a,(hl) ; bit to set ld bc,alloc pop hl push hl add hl,bc ld b,a ; save bit to set ld a,(hl) ld c,a ; save byte before setting bit or b ld (hl),a ; set bit ld a,c and b ; test if bit set pop hl pop bc ret ; 0 = if not set, > 0 if set bitmap: db 10000000b ;0 db 01000000b ;1 db 00100000b ;2 db 00010000b ;3 db 00001000b ;4 db 00000100b ;5 db 00000010b ;6 db 00000001b ;7 updat: jp nz,errbit ; bit already set push hl ld hl,(alvdat) inc hl ld (alvdat),hl ; increment count of data pop hl ret errbit: ; flag bit already set push hl ld hl,(alvbad) inc hl ld (alvbad),hl ; increment count of duplicate data pop hl ret upera: jp nz,lstbit ; bit already set push hl ld hl,(alvera) inc hl ld (alvera),hl ; increment count of erased data pop hl ret lstbit: push hl ld hl,(alvlst) inc hl ld (alvlst),hl ; increment count of overwritten data pop hl ret uprng: push hl ld hl,(alvrng) inc hl ld (alvrng),hl ; increment count of blocks outside range pop hl ret ;------; showalv: ; menu 1 option 3 Display disk ALLOCATION ;------; ld a,(def.dsk) add a,'A' ld (saldsk),a ld hl,lenalv ; start of datablock counts ld d,h ld e,l inc de ld bc,alvlen-1 ; length of datablock counts ld (hl),0 ldir ; and zero all ld hl,(dpb.dsm) ; number of data blocks less 1 call alv ; return = /8, & = mod 7 inc hl ld (lenalv),hl ; length of ALV in bytes ld de,alloc ; start of ALV add hl,de ; end of ALV ex de,hl ld hl,(BDOS+1) ; base of BDOS dec hl and a sbc hl,de ; = top of TPA - top of ALLOC jp nc,alvok ld de,alverr ld c,9 ;BDOS: PRINT STRING call bdos jp waitcr ; wait for then return dseg alverr: db cr,lf,'TPA too small for allocation vector','$' cseg ; ---------------------------- ; ; initialise allocation vector ; ; ---------------------------- ; alvok: ld hl,(lenalv) ld b,h ld c,l ld hl,alloc ld d,h ld e,l inc de dec bc ld (hl),0 ldir ; set allocation vector to 0 ld hl,(dpb.al0) ; directory ALV0 and ALV1 ld (alloc),hl ; and fill alloc bits with these ; ----------------------- ; ; count directory entries ; ; ----------------------- ; ld b,16 ld de,0 cntalv: add hl,hl jp nc,nocnt inc de nocnt: djnz cntalv ex de,hl ld (alvdir),hl ; number of directory entries ; -------------- ; ; scan directory ; ; -------------- ; ld de,deffcb ld a,'?' ld (de),a ld c,17 ;BDOS: SEARCH FOR FIRST call bdos nextdir: cp -1 jp z,doera ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ld de,defdma add hl,de ld a,(hl) and not 00011111b ; test for high bits set jp nz,nxtdcb ld de,16 add hl,de ex de,hl ; -> first data block allocation ld hl,(dpb.dsm) ld a,h or a jp nz,wrdalv ; test 16 file data block bytes ld b,16 ; byte wide data blocks nxtdb: push hl ld a,(de) or a jp z,nuldb cp l ; check range jp z,updb jp nc,errdb updb: ld l,a ld h,0 call alv ; return = /8, =MOD(,7) call setbit ; returns CF=NZ if bit already set call updat jp nuldb errdb: call uprng ; data block outside range nuldb: pop hl ; recover DSM inc de ; increment to next data block allocation djnz nxtdb jp nxtdcb ; test 8 file data block words wrdalv: ex de,hl ; move back to HL ld b,8 nxtdw: push hl ld e,(hl) inc hl ld d,(hl) ld a,e or d jp z,nuldw ld hl,(dpb.dsm) xor a sbc hl,de jp c,errdw ex de,hl call alv ; return = /8, =MOD(,7) call setbit ; returns CF=NZ if bit already set call updat jp nuldw errdw: call uprng ; data block outside range nuldw: pop hl ; recover data block pointer inc hl inc hl ; increment to next data block allocation djnz nxtdw jp nxtdcb nxtdcb: ld de,deffcb xor a ld (de),a ; set default drive ld c,18 ;BDOS: SEARCH FOR NEXT call bdos jp nextdir ; -------------- ; ; scan era files ; ; -------------- ; erabyt equ 0e5h ; CP/M byte for erased file doera: ld e,-1 ; to fetch user code ld c,32 ; BDOS: SET/GET USER CODE call bdos ld (user),a ; save user number ld e,5 ; set user = 5 ld c,32 ; BDOS: SET/GET USER CODE call bdos ld de,deffcb ld a,'?' ld (de),a ld c,17 ;BDOS: SEARCH FOR FIRST call bdos nextera: cp -1 jp z,erased ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ld de,defdma add hl,de ld a,(hl) and not 00011111b ; test for high bits set jp z,nxtera ld a,(hl) cp erabyt jp nz,nxtera push hl ld b,32 tstera: ld a,(hl) cp erabyt jp nz,notera inc hl djnz tstera ;(doesnt change flags) notera: pop hl jp z,erased ; as all 0e5's must be at end ld de,16 add hl,de ex de,hl ; -> first data block allocation ld hl,(dpb.dsm) ld a,h or a jp nz,wrdera ; test 16 erased file data block bytes ld b,16 nxtedb: push hl ; save DSM ld a,(de) or a jp z,nuledb cp l ; check range jp z,upedb jp nc,erredb upedb: ld l,a ld h,0 call alv ; return = /8, =MOD(,7) call setbit ; returns CF=NZ if bit already set call upera jp nuledb erredb: call uprng ; data block outside range nuledb: pop hl ; recover DSM inc de ; increment to next data block byte djnz nxtedb jp nxtera ; test 8 erased file data block words wrdera: ex de,hl ; move back to HL ld b,8 nxtedw: push hl ld e,(hl) inc hl ld d,(hl) ld a,e or d jp z,nuledw ld hl,(dpb.dsm) xor a sbc hl,de jp c,erredw ex de,hl call alv ; return = /8, =MOD(,7) call setbit ; returns CF=NZ if bit already set call upera jp nuledw erredw: call uprng ; data block outside range nuledw: pop hl ; recover data block pointer inc hl inc hl ; increment to next data block word djnz nxtedw nxtera: ld de,deffcb ld a,erabyt and 11100000b ; ignore water mark, ld (de),a ; (only works when user=5) ld c,18 ;BDOS: SEARCH FOR NEXT call bdos jp nextera erased: ; reached end of file ld a,(user) ; recover user number ld e,a ld c,32 ; BDOS: SET/GET USER CODE call bdos ; --------------------------- ; ; calculate unused datablocks ; ; --------------------------- ; ld hl,(lenalv) ld b,h ld c,l ld hl,(dpb.dsm) ld de,alloc nxtcnt: push bc ld a,(de) ld b,8 next8: add a,a jp nc,notalc dec hl ; reduce count by 1 notalc: djnz next8 inc de pop bc dec bc ld a,b or c jp nz,nxtcnt inc hl ; as started with dsm, not dsm+1 ld (alvzro),hl ; ---------------------- ; ; fill text with results ; ; ---------------------- ; ld hl,alv01 ld (posn),hl xor a ld hl,(dpb.dsm) ld de,1 add hl,de adc a,0 ld c,0 call megdec ; write total number of datablocks ld hl,alv02 ld (posn),hl ld hl,(alvdir) ; datablocks allocated to directory call wrddec ld hl,alv03 ld (posn),hl ld hl,(alvdat) ; datablocks allocated to data call wrddec ld hl,alv04 ld (posn),hl ld hl,(alvera) ; datablocks allocated to erased data call wrddec ld hl,alv05 ld (posn),hl ld hl,(alvlst) ; datablocks allocated to overwritten data call wrddec ld hl,alv06 ld (posn),hl ld hl,(alvbad) ; datablocks with duplicated data access call wrddec ld hl,alv07 ld (posn),hl ld hl,(alvzro) ; datablocks not allocated call wrddec ld hl,alv08 ld (posn),hl ld hl,(alvdir) xor a ld c,a ex de,hl ld hl,(alvdat) add hl,de adc a,c ex de,hl ld hl,(alvera) add hl,de adc a,c ex de,hl ld hl,(alvzro) add hl,de adc a,c ld c,a call megdec ld hl,alv09 ld (posn),hl ld hl,(alvrng) ; datablocks with duplicated data access call wrddec ; ------------ ; ; display text ; ; ------------ ; ld de,salmsg ld c,9 ;BDOS: PRINT STRING call bdos jp waitcr ; wait for then return dseg salmsg: db cr,' DRIVE ' saldsk: db 'A: DISK ALLOCATION' db cr,lf db cr,lf,' DATA BLOCKS ' db cr,lf db cr,lf,' TOTAL (DRM+1) ' alv01: db ' 65536 ' db cr,lf db cr,lf,' Directory ' alv02: db ' 16 ' db cr,lf,' Data ' alv03: db ' 65535 ' db cr,lf,' Erased and recoverable ' alv04: db ' 65535 ' db cr,lf,' Unused ' alv07: db ' 65535 ' db cr,lf,' ' db ' ----- ' db cr,lf,' ' alv08: db ' 65536 ' db cr,lf db cr,lf,' Erased and reused ' alv05: db ' 65535 ' db cr,lf,' Duplicated data ' alv06: db ' 65535 ' db cr,lf,' Blocks outside range ' alv09: db ' 65535 ' db cr,lf,lf,lf,lf,lf,lf,lf db '$' cseg ;------; showfil: ; menu 1 option 4 Display file ALLOCATION ;------; ld a,(def.dsk) add a,'A' ld (sfldsk),a ld de,sflmsg ld c,9 ;BDOS: PRINT STRING jp bdos ; & RETURN dseg sflmsg: db cr,' DRIVE ' sfldsk: db 'A: FILE ALLOCATION' db lf db cr,lf,lf,lf,lf,lf,'$' ; 10 line feeds cseg ;------; showdir: ; menu 1 option 5 Display directory ALLOCATION ;------; ld a,(def.dsk) add a,'A' ld (sdrdsk),a ld de,sdrmsg ld c,9 ;BDOS: PRINT STRING jp bdos ; & RETURN dseg sdrmsg: db cr,' DRIVE ' sdrdsk: db 'A: DIRECTORY ALLOCATION' db lf db cr,lf,lf,lf,lf,lf,'$' ; 10 line feeds cseg page ;-----; select: ; menu 1 option 9 Select new disk ;-----; ld a,(def.dsk) ld (olddsk),a ; save in case of error ld de,sldmsg ld c,9 ;BDOS: PRINT STRING call bdos ; ---------------------- ; ; Request new drive name ; ; ---------------------- ; sel0: ld de,logmsg ld c,9 ;BDOS: PRINT STRING call bdos ld de,selbuff ld c,10 ;BDOS: DIRECT CONSOLE BUFFER call bdos ld a,(sellen) or a ret z ; nothing selected cp 1 jp z,sel1 cp 2 jp nz,sel0 ld a,(seldb2) cp ':' jp nz,sel0 sel1: ld a,(seldb1) cp 'a' jp c,sel2 cp 'z'+1 jp nc,sel0 add a,'A'-'a' ; convert to lower case sel2: sub 'A' cp 15+1 jp nc,sel0 ; outside range 0-15 ld (def.dsk),a ; Current selected disk ld c,13 ;BDOS: RESET DISK SYSTEM call bdos ld a,(def.dsk) ld e,a ld c,14 ;BDOS: SELECT DISK call bdos or a jp nz,selerr call fetchdp ; fetch dpb and dph for drive ret selerr: ld a,(olddsk) ; recover previously selecte disk ld (def.dsk),a ld e,a ld c,14 ;BDOS: SELECT DISK call bdos or a jp nz,badsel call fetchdp ; fetch dpb and dph for drive ld de,oldmsg ld c,9 ;BDOS: PRINT STRING call bdos call waitcr ret dseg sldmsg: db cr,lf,lf,lf,lf,lf ; 5 line feeds db cr,lf,lf,lf,lf,lf ; 5 line feeds db cr,lf,lf,lf,lf,lf ; 5 line feeds db cr,lf,lf,lf,lf,lf ; 5 line feeds db cr,' SELECT NEW DISK' db lf db cr,lf,lf,lf,lf,lf,'$' ; 5 line feeds olddsk: db 0 logmsg: db cr,'Enter drive name (A:, B:, etc ) ? ',bs,bs,bs,'$' selbuff: db 3 sellen: ds 1 seldb1: ds 1 seldb2: ds 2 oldmsg: db cr,lf,'--- Unable to select new disk ---' db cr,lf,lf,lf,lf,lf,'$' ; 5 line feeds cseg page ;-------; goodvers: ;-------; ld a,(deffcb) dec a cp -1 jp nz,useccp ; use ccp disk ld c,25 ;BDOS: RETURN CURRENT DISK call bdos useccp: ld (def.dsk),a ; Current selected disk ld c,13 ;BDOS: RESET DISK SYSTEM call bdos ld a,(def.dsk) ld e,a ld c,14 ;BDOS: SELECT DISK call bdos or a jp nz,badsel ld (savesp),sp ; must use local stack as BIOS may be hungry ld sp,savesp call fetchdp ; fetch dpb and dph for drive call main ; now display as requested ld sp,(savesp) ld c,0 ;BDOS: SYSTEM RESET jp bdos ; & exit ;---; main: ;---; call clearscrn ; clear screen call screen1 ; display menu call option ; request option cp -1 ret z call task1 jp main ;----; task1: ;----; ld c,a ld b,0 dec bc ld hl,table1 add hl,bc add hl,bc ld a,(hl) inc hl ld h,(hl) ld l,a jp (hl) table1: dw showblk ; menu 1 option 1 Display DPB statistics dw showhdr ; menu 1 option 2 Display DPH statistics dw showalv ; menu 1 option 3 Display disk ALLOCATION dw showfil ; menu 1 option 4 Display file ALLOCATION dw showdir ; menu 1 option 5 Display directory ALLOCATION dw return dw return dw return dw select ; menu 1 option 9 Select new disk return: ret dseg alloc equ $ ; allocation vector placed at end of program end