; ; PROGRAM: XDIR III ; AUTHOR: RICHARD CONN ; VERSION: 2.0 ; DATE: 9 APR 84 ; PREVIOUS VERSIONS: 1.6 (19 NOV 83) ; PREVIOUS VERSIONS: 1.5 (9 JAN 83), 1.4 (6 JAN 83), 1.3 (7 DEC 82) ; PREVIOUS VERSIONS: 1.2 (2 NOV 82), 1.1 (30 OCT 82), 1.0 (20 OCT 82) ; vers equ 20 z3env SET 0f400h ; ; XDIR III -- Extended Disk Directory Program ; ZCPR3 Version ; ; XDIR III produces a formatted, alphabetized listing of the contents ; of the disk directory of the implied (current logged-in) or specified disk. ; ; XDIR III is invoked by a command line of the following form -- ; ; XDIR dir:filename.typ ooo... ; or ; ; XDIR /oooo... ; ; where: ; dir is an optional directory name or a disk/user specification (du) ; if dir is omitted, XDIR III defaults to the current disk/user ; filename.typ is an ambiguous file name and type (* and ? may be used) ; o are option letters as follows: ; Aa - Set the attributes of the files to be displayed; ; a=S for System Files, a=N for Non-System Files ; a=A for All Files (System and Non-System) ; D - Send Output to Disk as well as screen ; Ff - Engage File Name Buffer Facility ; f=L to Log File Names to Disk ; f=P to Print Names Logged to Disk ; f=S to Scan Disk for File Names and Compare to Logged ; I - Inspect files selected by FL option for inclusion ; N - Negate selection; select those files which do NOT ; match the ambiguous file name ; Oo - Set Output Parameters; ; o=A to Toggle File Attributes, o=F to Form Feed at end ; o=G to Toggle Grouping, o=H to Toggle Hor/Vert ; P - Print display as well as show it on the screen ; PF - Same as POF ; U - Select All User Areas ; ; Options may be combined as desired; note that AA is the same as AS and AN, ; but AS by itself negates AN and vice-versa, with AN taking precident ; ; ; CP/M Equates ; base equ 0 wboot equ base bdose equ base+5 fcb equ base+5ch buff equ base+80h ctrlc equ 'C'-'@' cr equ 0dh ff equ 0ch lf equ 0ah esize equ 16 ; size of directory entries optch equ '/' ; option char maxent equ 54 ; maximum number of entries/screen ; ; External Routines ; ext bdos ; BDOS ext dutdir ; convert DU to DIR form ext z3log ; log into DU or DIR ext z3init ; init buffers ext dbuffer ; disk routines ext dfree ext diralpha ext dirsload ext dirpack ext dirnpack ext dirsel ext dparam ext fsize ext fo0$open ; byte-oriented file output ext fo0$close ext f0$put ext fo1$open ext fo1$close ext f1$put ext fi1$open ext fi1$close ext f1$get ext bbline ; input line editor ext retud ; get current user and disk ext print ; print routines ext pstr ext lpstr ext lcrlf ext caps ; capitalize char ext cin ; console in char ext lout ; print char ext cout ; console out char ext crlf ; new line ext madc ; a as dec chars in memory ext mhldc ; hl as dec chars in memory ext fillb ; memory fill ext moveb ; memory move ext codend ; beginning of buffer area ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env jmp start0 ; ; Other Buffers (Set by GENINS) ; igrp: db 0ffh ; Group by file type and name ifmt: db 0 ; vertical format iatt: db 10000000b ; Non-System files only iscn: db 0 ; 0=dir display, 0ffh=scan for files by default fenab: db 0ffh ; enable F options (0=no) lenab: db 0ffh ; enable FL option (0=no) asenab: db 0ffh ; enable AS option (0=no) irs: db 0ffh ; enable attribute display (0=no) iff: db 0 ; enable form feed at end (0=no) ; ; Command Line Option Table ; optab: db 'A' dw opta db 'D' dw optd db 'F' dw optf db 'I' dw opti db 'N' dw optn db 'O' dw opto db 'P' dw optp db 'U' dw optu db 0 ; ; **** Start of XDIR III **** ; start0: ; ; Save stack ptr for return later ; lxi h,0 ; get stack dad sp shld stack ; save stack ptr for return call codend ; determine free space (CODEND also pts to Command ; Line Save Area) lxi d,100h ; block size to save dad d dad d ; allow for 256-byte stack shld buffer ; start of free buffer area sphl ; set stack ptr ; ; Save command line in CMDLNE buffer ; call codend ; pt to command line buffer xchg ; ... in DE lxi h,buff+1 ; copy input line into command line buffer start1: mov a,m ; get byte stax d ; put byte inx h ; pt to next inx d ora a ; end of line? jnz start1 ; ; Get and save current user number ; noext: call retud ; get current user and disk mov a,b ; get disk into A sta curdisk ; current disk number mov a,c ; set current user sta curuser ; ; Log into DU or DIR ; lxi d,fcb ; use data determined by ZCPR3 call z3log ; ZCPR3 command line interpretation call retud ; get current user and disk mov a,c ; set current user sta aflg mov a,b ; set disk sta disk ; ; Set flag values ; lda irs ; get RS display option sta rsflg ; set RS display option lda iff ; get form feed option sta ffflg ; set form feed option lda igrp ; set grouping (file name/type or type/name) sta gflg lda ifmt ; set listing format (vertical or horizontal, 0=vert) sta hflg lda iatt ; set file attributes mov c,a ; save in c lda aflg ; get current user number ora c ; mask in file attributes sta aflg ; save flag lda iscn ; set initial function (Scan or Dir) sta fflg xra a ; A=0 sta nflg ; set no negation sta dflg ; set no disk output sta pflg ; set no printer output sta iflg ; set no file name inspection (for /FP) ; ; Assume wild file name ; lxi h,fcb+1 ; store '?' chars mvi b,11 ; 11 chars mov a,m ; check for entry specified cpi ' ' ; test for space (means no entry) mvi a,'?' ; prepare for '?' fill cz fillb mov a,m ; check for option caught cpi optch ; test for option flag mvi a,'?' ; prepare for '?' fill cz fillb ; ; Scan command line for options ; call codend ; pt to first char call sblank ; skip over blanks ora a ; end of line? jz xdir ; begin main processing inx h ; prep for invalid option cpi optch ; option? jz opt ; process options dcx h ; ok to process for dir:filename.typ form ; ; skip over character of file name ; skipo1: mov a,m ; get char inx h ; pt to next cpi ' ' jz skipo2 ora a jnz skipo1 jmp xdir ; run XDIR if no options follow ; ; Scan complete -- look for possible following option char ; skipo2: call sblank ; skip over blanks mov a,m ; option char follows? cpi optch jnz opt inx h ; skip over option char ; ; Look for options -- main loop; HL pts to next char ; opt: mov a,m ; get option char inx h ; pt to next ora a ; end of line? jz xdir ; begin main processing cpi ' ' ; skip over spaces jz opt cpi optch ; option char? jz opterr ; loop back if so lxi d,optab ; pt to option table mov b,a ; option char in b ; ; Scan option table ; opt1: ldax d ; get option table char ora a ; end of table? jz opterr ; invalid option error cmp b ; compare to passed option jz opt2 ; process if match inx d ; skip address inx d inx d ; pt to next opt char jmp opt1 ; ; Process option found ; opt2: inx d ; pt to low-order address ldax d ; get it mov c,a ; low in C inx d ; pt to high-order address ldax d ; get it mov b,a ; high in B push b ; BC on stack ret ; Process option routine ; ; Option A -- File Attributes ; opta: mov a,m ; get next option letter cpi 'N' ; Non-System files? jz optan cpi 'S' ; System files? jz optas cpi 'A' ; All files? jnz opterr ; error if not ; ; Option AA -- All Files ; optaa: lda asenab ; enable system files? ora a ; 0=no jz optan mvi c,11000000b ; System and Non-system optaret: lda aflg ; get flag ani 3fh ; leave in user selection ora c ; mask in sys/non-sys sta aflg ; restore flag inx h ; pt to next jmp opt ; ; Option AS -- System Files ; optas: lda asenab ; enable system files? ora a ; 0=no jz optan mvi c,01000000b ; System Only jmp optaret ; ; Option AN -- Non-System Files ; optan: mvi c,10000000b ; Non-system Only jmp optaret ; ; Option F - select file name buffer functions ; optf: mvi a,0ffh ; set flag sta fflg mov a,m ; get option char sta fopt cpi 'L' ; log file names to disk jz optfok cpi 'P' ; print names of files jz optfok cpi 'S' ; scan disk for files jz optfok jmp opterr ; error otherwise optfok: inx h ; pt to next option letter jmp opt ; ; Option I -- enable it; inspect for FL option only ; opti: mvi a,0ffh ; ON sta iflg jmp opt ; ; Option D -- enable it; Disk output ; optd: mvi a,0ffh ; ON sta dflg jmp opt ; ; Option P -- enable it; Printer output ; optp: mvi a,0ffh ; ON sta pflg mov a,m ; get possible 2nd letter cpi 'F' ; set form feed if F jnz opt ; process as next option letter if not F inx h ; pt to next jmp optof ; ; Option O -- control Output parameters ; opto: mov a,m ; get 2nd letter inx h ; pt to next cpi 'A' ; attributes? jz optoa cpi 'F' ; form feed? jz optof cpi 'G' ; grouping? jz optog cpi 'H' ; horizontal/vertical? jz optoh dcx h ; adjust back jmp opterr ; ; Toggle File Attributes Flag ; optoa: lda rsflg ; flip flag cma sta rsflg jmp opt ; ; Toggle Form Feed Flag ; optof: lda ffflg ; flip flag cma sta ffflg jmp opt ; ; Toggle Grouping ; optog: lda gflg ; flip flag cma sta gflg ; 0=file name and type jmp opt ; ; Toggle Horizontal/Vertical Listing ; optoh: lda hflg ; flip flag cma sta hflg ; 0=vertical jmp opt ; ; Option N -- enable it; Negate Selection ; optn: mvi a,0ffh ; ON sta nflg jmp opt ; ; Option U - enable it; Select All User Areas ; optu: lda aflg ; get current attributes flag ori 20h ; select all user areas sta aflg ; put flag back jmp opt ; ; Option error message ; opterr: xra a ; set no disk or printer output sta dflg sta pflg call banner ; print banner call print db cr,lf,'Syntax:' db cr,lf,' XDIR dir:filename.typ ooo...' db cr,lf,'or XDIR /oooo...' db cr,lf,'Options:' db cr,lf,' Aa - File Attributes' db cr,lf,' a=S for System, a=N for Non-System' db cr,lf,' a=A for All Files (System and Non-System)' db cr,lf,' D - Send Output to Disk File XDIR.DIR' db cr,lf,' Ff - Enable a File Buffer Function' db cr,lf,' f=L for Log Names to FNAMES.DIR' db cr,lf,' f=P to Print Names stored in FNAMES.DIR' db cr,lf,' f=S to Scan Disk and Compare to FNAMES.DIR' db cr,lf,' I - Inspect Logged Files (FL Option Only)' db cr,lf,' N - Negate Selection' db cr,lf,' Oo - Toggle Output Features' db cr,lf,' o=A for File Attributes, o=F for Form Feed' db cr,lf,' o=G for Grouping, o=H for Horiz/Vert Format' db cr,lf,' P - Send Display to Printer' db cr,lf,' PF - Same as POF' db cr,lf,' U - Select All User Areas' db 0 ; ; Return to CP/M ; return: lda dflg ; disk output? ora a ; 0=no cnz fo0$close ; close file if so lhld stack ; get old stack ptr sphl ret ; return to CP/M ; ; Memory Overflow Error ; memerr: call printx db cr,lf,'TPA Error',0 jmp return ; ; Print banner of XDIR III ; banner: call printx db 'XDIR III, Version ' db vers/10+'0','.',(vers mod 10)+'0',0 ret ; ; Begin XDIR III processing ; xdir: ; ; This section disables the /Ff option and /FL option if default set ; lda fenab ; enable FFLG? (/Ff option) ora a ; 0=no jnz xdst1 xra a ; turn off FFLG sta fflg xdst1: lda lenab ; enable FL option? ora a ; 0=no jnz xdst2 lda fflg ; FFLG on? ora a ; 0=no jz xdst2 lda fopt ; check for L cpi 'L' jnz xdst2 mvi a,'P' ; switch L to P sta fopt xdst2: lda fflg ; file name buffer option? ora a ; 0=no jz xdirst xra a ; A=0 sta gflg ; group by file name and type lda fopt ; print immediately if P option cpi 'P' ; print? jnz xdirst call banner ; print banner jmp xdirfp ; print file names ; Check for Print Option and Ask for and Print Header if so xdirst: lda pflg ; printer output? ora a ; 0=no jz xdirgo call print ; message to user db cr,lf,'Please Input Header: ',0 xra a ; no caps call bbline ; input line from user ora a ; no chars? jz xdirgo call lcrlf ; new line call lpstr ; print header line call lcrlf ; new line ; Get Files from Disk xdirgo: lhld buffer ; end of code call dbuffer ; set buffers jz memerr ; memory overflow error? push h ; save regs push d call dfree ; compute amount of free space on disk xchg ; amount in hl shld freesiz ; save free space count pop d ; get regs pop h call dirsload ; load with sizing information jz memerr ; memory overflow error? push h ; save hl mov h,b ; HL=number of files loaded mov l,c shld totfil ; save total count push b ; save bc lda curdisk ; prepare to relog in disk mov e,a mvi c,14 ; select disk call bdos lda curuser ; prepare to relog in user mov e,a mvi c,32 ; select user call bdos ; Open disk file if necessary for disk output lda dflg ; disk output? ora a ; 0=no jz xdir0 lxi d,dskfcb ; open disk file for char output call fo0$open ; open file for output xdir0: pop b ; get count pop h ; get ptr ; Continue processing; select desired files lda aflg ; get file attributes lxi d,fcb ; get ptr to fcb call dirsel ; select files ; Now, pack and alphabetize directory lda nflg ; negate selection? ora a ; 0=no cz dirpack ; select marked entries cnz dirnpack ; select unmarked entries lda gflg ; get grouping flag call diralpha ; alphabetize directory shld firstf ; save ptr to first file mov h,b ; HL=file count mov l,c shld fcount ; save file count shld countf ; save file down count lxi h,0 ; set file size counter shld totsiz ; save counter lda dflg ; set temp flags sta dflgt lda pflg sta pflgt ; ; Major feature selection -- ; Two major features of XDIR are selected at this time: ; 1. Directory Display Functions ; 2. File Name Buffer Functions ; At this point, the following key values are know: ; FIRSTF - Pointer to First File ; FCOUNT, COUNTF - Number of Files ; lda fflg ; get flag ora a ; Z=Directory Display, NZ=File Name Buffer Fcts jnz xdirf ; Do File Name Buffer Fcts ; ; Main Directory Print Routine -- This routine displays the directory to ; the console, printer, or disk as desired ; ; Print header lines and one screen of entries xdir2: lda dflg ; save disk and print output flags sta dflgs lda pflg sta pflgs lda dflgt ; use temp flags sta dflg lda pflgt sta pflg xra a ; A=0 sta dflgt ; clear temp flags so no banner 2nd time around sta pflgt ; Print: Main Banner call banner ; print banner ; Print: Horizontal/Vertical Listing Message call printx db ' ',0 lda hflg ; get horizontal/vertical flag ora a ; 0=vertical jnz xdir2a call printx db 'Vertical',0 jmp xdir3 xdir2a: call printx db 'Horizontal',0 ; Print: Listing by File Name and Type or Type and Name Message xdir3: call printx db ' Listing by File ',0 lda gflg ; grouping flag ora a ; 0=name and type jnz xdir3a call printx db 'Name/Type',0 jmp xdir4 xdir3a: call printx db 'Type/Name',0 ; ; Print: Disk and User ; xdir4: call printx ; print everywhere db cr,lf,' Disk: ',0 lda disk ; get current disk adi 'A' ; convert to ASCII call coutx ; print everywhere call printx ; print everywhere db ' User: ',0 lda aflg ; get user number ani 20h ; all? jz xdir4b call printx db 'All',0 jmp xdir5 xdir4b: lda aflg ; get selected user ani 1fh ; select user number lxi d,numbuf ; store number in buffer call madc ; get number mvi b,3 ; 3 digits call prnumx ; print number everywhere ; ; Print: Directory Name ; xdir5: lda aflg ; check for all users mov c,a ; save in C ani 20h jnz xdir5fa mov a,c ; get user ani 1fh ; mask for just user mov c,a lda disk ; select disk mov b,a call dutdir ; determine if name available jz xdir5fa call printx db ' Name: ',0 mvi b,8 ; 8 chars to name xdir5n: mov a,m ; get char inx h ; pt to next cpi ' ' ; don't print spaces cnz coutx dcr b ; count down jnz xdir5n ; ; Print: Selected File Attributes ; xdir5fa: call printx db ', File Attributes: ',0 lda aflg ; get flag push psw ; save A ani 80h ; Non-system? jz xdir5a call printx db ' Non-System',0 xdir5a: pop psw ; get A ani 40h ; System? jz xdir5b call printx db ' System',0 ; See if any files selected xdir5b: lhld countf ; get file down count mov a,h ; any files? ora l jnz xdir6 call printx ; print everywhere db cr,lf,'No files selected -- ',0 jmp xdir11 ; ; This is the main looping entry point for each screen display ; xdir6: lda aflg ; all users selected? ani 20h jnz xdir6a ; ; This is the header which is printed if the files in only one user area are ; displayed ; call crlfx ; new line call hdr2 ; pt to header lda rsflg ora a ; Z=no cnz sp0 ; print RS call sp2 ; print leading spaces call hdr2 ; print header lda rsflg ora a ; Z=no cnz sp0 ; print RS call sp2 ; print leading spaces call hdr2 ; print header lda rsflg ora a cnz sp0 call crlfx ; new line call hdr1 ; print underlines lda rsflg ora a cnz sp1 call sp2 ; leading spaces call hdr1 ; underlines lda rsflg ora a cnz sp1 call sp2 ; leading spaces call hdr1 ; underlines lda rsflg ora a cnz sp1 jmp xdir6b ; ; General-Purpose Header Print Routines ; sp0: call printx db ' RS',0 ret sp1: call printx db ' --',0 ret sp2: call printx db ' ',0 ret spu: call printx db ' U ',0 ret spu1: call printx db ' ',0 ret spu2: call printx db ' - ',0 ret hdr1: call printx db '-------- --- ------',0 ret hdr2: call printx db 'Filename.Typ Size K',0 ret ; ; This is the header which is printed if the files in all user areas are ; displayed ; xdir6a: call crlfx call spu ; print U call hdr2 ; print header lda rsflg ora a cnz sp0 ; RS call spu1 call spu ; print U call hdr2 ; print header lda rsflg ora a cnz sp0 ; RS call spu1 call spu ; print U call hdr2 ; print header lda rsflg ora a cnz sp0 ; RS call crlfx call spu2 ; 1 underscore call hdr1 ; underscores lda rsflg ora a cnz sp1 call spu1 call spu2 ; 1 underscore call hdr1 ; underscores lda rsflg ora a cnz sp1 call spu1 call spu2 ; 1 underscore call hdr1 ; underscores lda rsflg ora a cnz sp1 ; ; Prepare Columnar Output ; xdir6b: lda dflgs ; restore disk and print flags sta dflg lda pflgs sta pflg lhld countf ; get file count down lxi d,maxent ; assume maxent entries to print mov a,h ; within range? ora a ; outside of range if not jnz xdir7 ; subtract entries to print from total entries mov a,l ; within range? cpi maxent ; less than maxent entries left? jnc xdir7 ; subtract entries to print from total entries mov d,h ; DE=HL=number of entries to print mov e,l xdir7: mov a,l ; subtract entries to print (DE) from total (HL) sub e mov l,a mov a,h sbb d mov h,a ; HL=result shld countf ; save new down count mov b,h ; BC=count mov c,l lhld firstf ; pt to first file ; ; At this point, BC=number of remaining entries, DE=number of entries to ; print, and HL pts to first entry to print ; shld ptr1 ; save ptr to 1st entry lda hflg ; horizontal listing? ora a ; 0ffh = yes jnz xdir7c ; don't worry about columns if horizontal push d ; save count call divde3 ; divide DE by 3, result*esize in BC, remainder in A lxi d,esize ; DE=ESIZE (size of entry) dad b ; add BC as a minimum ora a ; any remainder? jz xdir7a ; skip if none dad d ; add in ESIZE for additional length of 1st col xdir7a: shld ptr2 ; save ptr to col 2 dad b ; add BC as a minimum cpi 2 ; if remainder 2, add ESIZE for additional jc xdir7b dad d ; add in ESIZE xdir7b: shld ptr3 ; save ptr to col 3 pop d ; get count in de ; ; Main entry print routine ; xdir7c: mvi d,1 ; set 3's counter xdir8: lhld ptr1 ; pt to first entry call prentry ; print entry shld ptr1 ; put ptr lda hflg ; horizontal? ora a ; 0ffh = yes jnz xdir9 dcr e ; count down jz xdir10 lhld ptr2 ; get ptr call prentry ; print entry shld ptr2 ; put ptr dcr e ; count down jz xdir10 lhld ptr3 ; get ptr call prentry ; print entry shld ptr3 ; put ptr xdir9: dcr e ; count down jnz xdir8 ; continue if not zero shld firstf ; save ptr to first of next set of entries to print lhld countf ; get count of remaining entries ; ; At this point, HL=number of entries left ; mov a,h ; anything left? ora l jz xdir10 lda dflg ; no message if disk or printer output mov b,a lda pflg ora b jnz xdir6 call print ; screen break db cr,lf,' --> Screen Break -- Strike any char <-- ',0 call cin ; get response cpi ctrlc ; abort? jz return jmp xdir6 ; new screen display ; ; Print end statistics and exit ; xdir10: call crlfx ; new line lhld fcount ; print file count call prhlx ; print it everywhere call printx db ' Files Using ',0 lhld totsiz ; get total of file sizes call prhlx ; print it everywhere call printx db 'K, ',0 lhld totfil ; print total file count call prhlx ; print it everywhere call printx db ' Files on Disk and ',0 ; ; Print Amount of Free Space Left on Disk ; Entry Point if No Files Found ; xdir11: lhld freesiz ; get amount of free space call prhlx ; print it everywhere call printx db 'K Left',0 lda dflg ; if disk or printer output, new line mov b,a lda pflg ora b jz return call crlfx ; new line for disk and/or printer lda pflg ; print output mov b,a lda ffflg ; form feed ana b ; if print and form feed ... NZ is set mvi a,ff ; form feed char cnz lout ; form feed to printer jmp return ; ; File Name Buffer Functions ; xdirf: call banner ; print banner lda iscn ; just scan? ora a ; 0=no jnz xdirfs lda fopt ; get option of F command cpi 'L' ; log names to disk? jz xdirfl cpi 'S' ; scan names on disk? jz xdirfs ; ; File Name Print Option; /FP option ; xdirfp: call openin ; open FNAMES.DIR for input xdfp0: call printx db cr,lf,cr,lf db 'Printout of Recorded File Names --',cr,lf,' ',0 ; ; Extract File Name Count ; call f1$get ; get low count jnz geterr mov l,a ; save in L call f1$get ; get high count jnz geterr mov h,a ; save in H push h ; save HL call prhlx ; print HL everywhere call printx db ' File Names',cr,lf,0 call prfhdr ; print file name header pop h ; get HL mvi c,0 ; set entry counter ; ; Loop for extracting names from FNAMES.DIR and printing them ; xdfp1: mov a,h ; no more entries? ora l jz xdfp2 dcx h ; count down call getdfn ; get next disk file name from FNAMES.DIR call prfnfx ; print file name entry inr c ; increment count mov a,c ; new line time? ani 3 cz crlfx jmp xdfp1 xdfp2: call fi1$close call crlfx ; new line jmp return ; ; Log File Names to Disk; /FL option ; Structure of FNAMES.DIR file is: ; File Name Count, Low-Order Byte ; File Name Count, High-Order Byte ; File Names, stored as 12 bytes -- User Number, FN, and FT ; xdirfl: lxi d,fnfcb ; open file for output call fo1$open jz xdfl1 call printx db cr,lf,'Cannot Create FNAMES.DIR',0 jmp return ; Log Files to Disk with possible initial inspect and select by user xdfl1: lda iflg ; inspect? ora a ; 0=no cnz flinsp ; inspect if selected ; Print file count call printx db cr,lf,cr,lf db 'Logging File Names to Disk --',cr,lf,' ',0 lhld fcount ; get count call prhlx ; print it call printx db ' File Names',cr,lf,0 ; Check file count and print appropriate header lhld fcount ; get number of files mov a,h ; any files? ora l jz xdfl1a call prfhdr ; print file name header jmp xdfl1b xdfl1a: call printx ; no files db ' No Files to be Logged',0 ; Store file count to disk xdfl1b: mov a,l ; store low count call f1$put jnz puterr mov a,h ; store high count call f1$put jnz puterr xchg ; ... in DE lhld firstf ; pt to first file mvi c,0 ; set display counter ; Loop to store files names xdfl2: mov a,d ; done? ora e jz xdfl3 dcx d ; count down ; Write entry to disk push d ; save count push h ; save ptr to file mov a,m ; get user number call f1$put ; save it jnz puterr lxi d,numbuf ; print user number push d ; save ptr call madc pop d ; get ptr inx d ; pt to 1st digit ldax d ; get it call coutx inx d ; pt to last digit ldax d ; get it call coutx mvi a,' ' ; call coutx inx h ; pt to FN mvi b,8 ; 8 chars call xdput mvi a,'.' call coutx mvi b,3 ; 3 chars call xdput mvi a,' ' ; print call coutx call coutx inr c ; increment count mov a,c ; get count ani 3 cz crlfx pop h ; get ptr to first file pop d ; get count push b lxi b,esize ; pt to next file dad b pop b jmp xdfl2 ; Done with creation of FNAMES.DIR xdfl3: call fo1$close ; close file call crlfx jmp return ; Write B chars pted to by HL to FNAMES.DIR and user xdput: mov a,m ; get char call coutx ; print it everywhere call f1$put ; put it on disk jnz puterr inx h ; pt to next dcr b ; count down jnz xdput ret ; ; Inspect Files for Logging to Disk ; flinsp: lhld fcount ; get count of files xchg ; ... in DE mov a,d ; any files selected? ora e rz ; abort if none ; Inspection banner call printx db cr,lf,'Inspection of Files to be Logged',0 lhld firstf ; pt to first file ; Main inspection loop flil1: mov a,d ; any files selected? ora e jz flil3 ; done if not dcx d ; count down push d ; save count lxi d,dfnbuf ; copy file name to buffer mvi b,12 ; 12 bytes call moveb call printx db cr,lf,'Log ',0 call prfnfx ; print file name for prompt call printx db ' to Disk (Y/N)? ',0 call cin ; get response call caps ; capitalize call coutx cpi 'N' ; No? jz flil2 mov a,m ; mark user number ori 80h mov m,a flil2: lxi d,esize ; skip to next entry dad d pop d ; get count jmp flil1 flil3: lhld fcount ; get number of files mov b,h ; count in BC mov c,l lhld firstf ; pt to first file call dirpack ; pack directory mov h,b ; new count in HL mov l,c shld fcount ; set counts shld countf ret ; ; Error Message for Output ; puterr: call printx db cr,lf,'Disk Write Error',0 jmp return ; ; Scan Disk for File Names; /FS option ; xdirfs: call printx db cr,lf,'File Name Scanner',0 call openin ; open FNAMES.DIR for input xdfs1: call printx db cr,lf,'Files Named in FNAMES.DIR missing from Disk --',cr,lf,0 ; Get file name count call f1$get ; get file name count from disk jnz geterr mov c,a ; store low call f1$get jnz geterr mov b,a ; store high lhld fcount ; get count of number of files xchg ; ... in DE lhld firstf ; pt to first file xra a ; A=0 sta crcnt ; set counter for CRLF sta fmark ; mark no first file yet ; ; At this point, HL pts to first file in buffer, DE is number of files in ; buffer, and BC is number of files in FNAMES.DIR ; mov a,b ; any names in FNAMES.DIR? ora c jz xdfs5 ; mark all names in buffer if not call getdfn ; get first disk name xdfs2: mov a,b ; see if any more files in FNAMES.DIR ora c jz xdfs5 ; mark rest of files in buffer and continue mov a,d ; see if any more files in buffer ora e jz xdfs6 ; name rest of files in FNAMES.DIR as missing and cont call compfn ; compare to file name pted to by HL jz xdfs3a ; advance to next file if they match jc xdfs3 ; mark file name pted to by HL as additional lda fmark ; first file? ora a ; 0=yes jnz xdfs2a mvi a,0ffh ; set mark sta fmark call prfhdr ; print header xdfs2a: call prfnfx ; print file name in FNAMES.DIR dcx b ; count down mov a,b ; done? ora c jz xdfs2 call getdfn ; get next name lda crcnt ; get entry counter inr a ; increment sta crcnt ani 3 ; mask cz crlfx ; new line every 4 jmp xdfs2 xdfs3: mov a,m ; get user number ori 80h ; mark it mov m,a ; put it back jmp xdfs4 xdfs3a: call getdfn ; get next name dcx b ; count down on names xdfs4: push d ; save count lxi d,esize ; pt to next entry dad d pop d ; get count dcx d ; count down jmp xdfs2 ; continue ; Mark rest of files in buffer xdfs5: mov a,d ; check count ora e jz xdfs7 dcx d ; count down mov a,m ; get user number ori 80h ; mark it mov m,a ; put user number lxi b,esize ; skip to next file dad b jmp xdfs5 ; continue ; Name rest of files in FNAMES.DIR as missing xdfs6: call prfnfx ; print file name in FNAMES.DIR dcx b ; count down mov a,b ; done? ora c jz xdfs7 ; next phase lda crcnt ; get entry counter inr a ; increment sta crcnt ani 3 ; mask cz crlfx ; new line every 4 call getdfn ; get next name jmp xdfs6 ; Part 2 of Scan - Name Additional Files xdfs7: lda fmark ; no files printed? ora a ; 0=none jnz xdfs7a call printx db ' No Files Missing',0 xdfs7a: xra a ; A=0 sta fmark ; set mark for 2nd part call printx db cr,lf,'Additional Files on Disk NOT in FNAMES.DIR --',cr,lf,0 lhld fcount ; get count of files xchg ; ... in DE lhld firstf ; pt to first file xra a ; A=0 sta crcnt ; set counter xdfs8: mov a,d ; check count ora e jz xdfs9 ; done if zero dcx d ; count down mov a,m ; get user number ani 80h ; marked? jz xdfs8b ; skip if not mov a,m ; get user number ani 7fh ; mask mov m,a ; replace lda fmark ; first time? ora a ; 0=yes jnz xdfs8a mvi a,0ffh ; set mark sta fmark call prfhdr ; print header xdfs8a: push d ; save count lxi d,dfnbuf ; copy to buffer for print mvi b,12 ; 12 bytes call moveb ; copy pop d call prfnfx ; print file name lda crcnt ; count down inr a sta crcnt ani 3 ; new line? cz crlfx xdfs8b: lxi b,esize ; pt to next entry dad b jmp xdfs8 ; continue ; Done with Scan xdfs9: lda fmark ; no files printed? ora a ; 0=none jnz xdfs9a call printx db ' No Additional Files',0 xdfs9a: jmp return ; ; Compare file name pted to by HL with that in DFNBUF; return with Z if same, ; C if (HL)<(DFNBUF) ; compfn: push h ; save regs push d push b lxi d,dfnbuf ; pt to buffer xchg ; DE pts to file name, HL pts to DFNBUF push h ; save ptrs push d mvi b,11 ; compare FN and FT cfn1: inx h ; pt to next inx d mov a,m ; get char from DFNBUF ani 7fh ; mask MSB mov c,a ; save in C ldax d ; get name in memory buffer ani 7fh ; mask MSB cmp c ; compare to name in DFNBUF jnz cfn2 ; not same, so exit with flag set dcr b ; count down jnz cfn1 pop d ; same so far, so compare user numbers pop h mov a,m ; get user number ani 7fh ; mask MSB mov c,a ; save in C ldax d ; get user number ani 7fh ; mask MSB cmp c ; compare push h ; fill stack for ext push h cfn2: pop h ; clear stack pop h pop b ; get regs and exit pop d pop h ret ; ; General Utility Routines ; ; ; Print user and file name stored in DFNBUF for /Ff functions ; prfnfx: push h ; save regs push d push b lxi h,dfnbuf ; pt to first byte of buffer mov a,m ; get first byte (user number) lxi d,numbuf ; convert to chars in memory call madc lxi d,numbuf+1 ; pt to first char ldax d ; get it call coutx inx d ; pt to 2nd char ldax d ; get it call coutx mvi a,' ' ; call coutx inx h ; pt to FN mvi b,8 ; 8 chars for FN call prch mvi a,'.' call coutx mvi b,3 ; 3 chars for FT call prch call prfhs ; 2 pop b ; get regs pop d pop h ret ; ; Get next User Number, FN, and FT from disk and save it in buffer ; getdfn: push h ; save regs push d push b lxi h,dfnbuf ; pt to buffer mvi b,12 ; 12 bytes getdf1: call f1$get ; get user jnz geterr mov m,a ; store user inx h ; pt to next dcr b ; count down jnz getdf1 pop b ; restore regs pop d pop h ret ; ; Print File Buffer Names Header Everywhere ; prfhdr: mvi b,3 ; 3 times prfhd1: call prfh1 ; print header call prfhs ; print 2 spaces dcr b jnz prfhd1 call prfh1 call crlfx mvi b,3 ; 3 times prfhd2: call prfh2 ; print header call prfhs ; print 2 spaces dcr b jnz prfhd2 call prfh2 call crlfx ret prfhs: call printx db ' ',0 ret prfh1: call printx db ' U Filename.Typ',0 ret prfh2: call printx db ' - -------- ---',0 ret ; ; Get Error Message and Abort ; geterr: call printx db cr,lf,'Premature EOF',0 jmp return ; ; Open FNAMES.DIR for byte-oriented input ; openin: lxi d,fnfcb ; open file call fi1$open ; open for input rz call printx db cr,lf,'FNAMES.DIR Not Found',0 jmp return ; ; Print disk entry for normal directory display functions ; prentry: dcr d ; count counter jnz prent1 mvi d,3 ; reset count call crlfx prent1: shld entptr ; save entry ptr lda aflg ; all users selected? ani 20h jz prent2 ; ; The following prints the user number if all user numbers are selected ; push h ; save regs push d push b mov a,m ; get user number ani 1fh ; mask it lxi d,numbuf call madc ; convert to chars in memory lxi h,numbuf+1 ; pt to first char mov a,m ; get it call coutx inx h ; get 2nd char mov a,m call coutx mvi a,' ' ; print call coutx pop b ; get regs pop d pop h prent2: inx h ; pt to first char of file name mvi b,8 ; print 8 chars call prch mvi a,'.' ; print dot call coutx push h ; save RS ptr mvi b,3 ; print 3 chars call prch push d ; save de lhld entptr ; pt to entry mvi a,' ' ; skip 2 spaces call coutx call coutx call fsize ; compute file size lhld totsiz ; get total file size counter dad d ; add in new file shld totsiz ; save new total file size counter xchg ; get file size into HL call prhlx ; print HL value pop d ; get de pop h ; pt to RS lda rsflg ; print RS fields? ora a ; Z=no jz pren2a mvi a,' ' ; print 1 space call coutx mvi b,'R' ; letter call prletx ; print R if bit set inx h mvi b,'S' ; letter call prletx ; print S if bit set dcx h ; ... for following inx h pren2a: inx h ; point correctly mvi a,' ' ; 1 space call coutx lda aflg ; all users? ani 20h jnz prent3 ; ; The following prints 2 additional spaces if only one user area is selected ; mvi a,' ' ; 2 more spaces for not all users call coutx call coutx prent3: lxi b,6 ; pt to next entry dad b ret ; ; Print B chars pted to by HL ; prch: mov a,m ; get char inx h ; pt to next ani 7fh ; mask out msb cpi ' ' ; within range? jnc prch1 ; print special char if not valid char mvi a,'?' ; print ? if not valid char prch1: call coutx ; print it dcr b ; count down jnz prch ret ; ; Extended Print Routines ; prletx: mov a,m ; get byte ani 80h ; look at msb jz prlets mov a,b ; get letter call coutx ret prlets: mvi a,' ' ; print call coutx ret prhlx: lxi d,numbuf ; store in number buffer call mhldc ; hl into memory as decimal mvi b,5 ; 5 digits prnumx: lxi h,numbuf ; pt to buffer prnum: mov a,m ; get digit inx h ; pt to next call coutx ; print everywhere dcr b ; count down jnz prnum ret printx: xthl ; pt to string call prxl ; print string at HL xthl ret prxl: mov a,m ; get byte inx h ; pt to next ora a ; done? rz call coutx ; print everywhere jmp prxl coutx: push b ; save bc push psw ; save char ani 7fh ; mask out msb mov b,a ; char in B call cout ; print to screen lda pflg ; printer on? ora a ; 0=no mov a,b ; get char cnz lout ; printer output if on lda dflg ; disk on? ora a ; 0=no mov a,b ; get char cnz f0$put ; output to file pop psw ; get char pop b ; get bc ret crlfx: push psw ; save A call printx db cr,lf,0 pop psw ; get A ret ; ; Divide DE by 3; return with BC=result*esize, a=remainder ; divde3: push d ; save de, hl push h mvi d,0 ; make sure D=0 mov a,e ; value in A divd31: sui 3 ; subtract 3 jc divd32 jz divd33 inr d ; add 1 to result jmp divd31 divd32: adi 3 ; add back in jmp divd34 divd33: inr d ; add 1 for even division divd34: sta rem ; save remainder lxi b,esize lxi h,0 divd35: mov a,d ; done? ora a ; 0=yes jz divd36 dcr d dad b ; add in another ESIZE jmp divd35 divd36: mov b,h ; BC is result mov c,l lda rem ; A is remainder pop h ; restore regs pop d ret ; ; Skip blanks ; sblank: mov a,m ; pt to char cpi ' ' ; blank? rnz inx h ; pt to next jmp sblank ; ; Buffers ; aflg: ds 1 ; attibute flag dflg: ds 1 ; disk output on flag fflg: ds 1 ; 0=no file name buffer function gflg: ds 1 ; 0=group by name/type hflg: ds 1 ; 0=vertical list iflg: ds 1 ; 0=no inspect nflg: ds 1 ; 0=no negate pflg: ds 1 ; printer output on flag fopt: ds 1 ; file name buffer option crcnt: ds 1 ; entry counter fmark: ds 1 ; first file marker dflgt: ds 1 ; temp flags pflgt: ds 1 dflgs: ds 1 pflgs: ds 1 rsflg: ds 1 ; RS Display Flag ffflg: ds 1 ; form feed flag disk: ds 1 ; selected disk curdisk: ds 1 ; current disk curuser: ds 1 ; current user rem: ds 1 ; remainder buffer firstf: ds 2 ; ptr to first file of group to print totfil: ds 2 ; total number of files on disk fcount: ds 2 ; count of files countf: ds 2 ; down count of files freesiz: ds 2 ; amount of free space on disk totsiz: ds 2 ; total size of all files ptr1: ds 2 ; col output ptrs ptr2: ds 2 ptr3: ds 2 entptr: ds 2 ; current entry ptr numbuf: ds 6 ; number buffer dfnbuf: ds 12 ; disk file name buffer dskfcb: db 0 db 'XDIR DIR' db 0,0,0,0 ds 16 ds 4 fnfcb: db 0 db 'FNAMES DIR' db 0,0,0,0 ds 16 ds 4 cmdlne: ds 2 ; pointer to command line buffer: ds 2 ; pointer to free space buffer stack: ds 2 ; stack ptr end