; ; PROGRAM: XD III ; AUTHOR: RICHARD CONN ; VERSION: 1.2 ; DATE: 8 Apr 84 ; PREVIOUS VERSIONS: 1.1 (14 Jan 84), 1.0 (19 Nov 83) ; DERIVATION: XDIR III, Version 1.6 (19 Nov 83) ; vers equ 12 z3env SET 0f400h ; ; XD III -- Simple Extended Disk Directory Program ; ZCPR3 Only ; ; XD III produces a formatted, alphabetized listing of the contents ; of the disk directory of the implied (current logged-in) or specified disk. ; ; XD III is invoked by a command line of the following form -- ; ; XD dir:filename.typ ooo... ; or ; ; XD /oooo... ; ; where: ; dir is an optional directory name or a disk/user specification (du) ; if dir is omitted, XD 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) ; 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 ; 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 cr equ 0dh ff equ 0ch lf equ 0ah esize equ 16 ; size of directory entries optch equ '/' ; option char maxent equ 60 ; maximum number of entries/screen ; ; External Routines ; ext bdos ; BDOS ext z3init ; init ZCPR3 environment descriptor ptr ext z3log ; log into ZCPR3 DU/DIR ext dirqs ; quick directory load with sizes ext dfree ; free space computer ext dparam ; disk parameter extractor ext fsize ; compute file size ext retud ; get current user and disk ext print ; print routines ext pstr ext lcrlf ; CRLF to printer ext caps ; capitalize char ext cin ; console in char ext lout ; print char ext cout ; console out char ext crlf ; new line ext fillb ; memory fill ext moveb ; memory move ext codend ; beginning of buffer area ext sctlfl,sout,scrlf,sprint,spstr,shldc,sadc ; S-output ext dutdir ; DU to DIR form ; ; 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 ; ; Branch to Start of Program ; 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 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' ; Attribute Selection dw opta db 'O' ; Output Control dw opto db 'P' ; Print Control dw optp db 0 ; ; **** Start of XD 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 ; log into DU or DIR lxi d,fcb ; extract file name into fcb, and get user and disk call z3log ; ZCPR3 command line interpretation ; Get and save current user number noext: call retud ; get current user and disk mov a,c ; get user into A sta aflg ; current user number ; 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 xra a ; A=0 sta pflg ; set no printer output inr a ; A=1 for console only sta sctlfl ; set switched output flag ; 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,'?' ; prep for '?' fill cz fillb mov a,m ; check for option caught cpi optch ; test for option flag mvi a,'?' ; prep 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 characters 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: 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: mvi c,01000000b ; System Only jmp optaret ; ; Option AN -- Non-System Files ; optan: mvi c,10000000b ; Non-system Only jmp optaret ; ; Option P -- enable it; Printer output ; optp: mvi a,0ffh ; ON sta pflg sta sctlfl ; set S-output control 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 error message ; opterr: mvi a,1 ; set console only sta sctlfl ; set output control flag call banner ; print banner call print db cr,lf,'Syntax:' db cr,lf,' XD dir:filename.typ ooo...' db cr,lf,'or XD /oooo...' db cr,lf,'Option letters are:' db cr,lf,' Aa - Set and Display of 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,' Oo - Toggle Output Control Options' 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 0 ; Return to CP/M return: lhld stack ; get old stack ptr sphl ret ; return to CP/M ; Memory Overflow Error memerr: call sprint db 'TPA Error',0 jmp return ; Print banner of XD III banner: call sprint db 'XD III Version ' db vers/10+'0','.',(vers mod 10)+'0',0 ret ; ; Begin XD III processing ; xdir: lxi d,fcb ; pt to FCB xra a stax d ; select current disk ; Check for Print Option and Print New Line if so xdirst: lda pflg ; printer output? ora a ; 0ffH=yes cnz lcrlf ; new line ; Get Files from Disk push d ; save ptr to FCB call dparam ; get disk parameters for DFREE call dfree ; compute amount of free space on disk xchg ; amount in hl shld freesiz ; save free space count pop d ; get regs lhld buffer ; pt to free space lda gflg ; get grouping flag ani 20h ; mask for sort bit (0=name/type) mov c,a lda aflg ; get attributes flag ora c ; mask in grouping bit call dirqs ; quick directory load with file sizes jz memerr ; memory overflow error? 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 pflg ; set temp flag sta pflgt ; ; 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 pflg ; save printer output flag sta pflgs lda pflgt ; use temp flag sta pflg xra a ; A=0 sta pflgt ; clear temp flag ; Print: Main Banner call banner ; print banner ; Check for any files lhld countf ; get file down count mov a,h ; any files? ora l jnz xdir6 call sprint ; print everywhere db cr,lf,'No files selected',0 jmp xdir10 ; ; This is the main looping entry point for each screen display ; xdir6: ; ; This is the header which is printed if the files in only one user area are ; displayed ; call scrlf ; specific user selected call hdr2 lda rsflg ora a ; Z=no cnz sp0 call sp2 call hdr2 lda rsflg ora a ; Z=no cnz sp0 call sp2 call hdr2 lda rsflg ora a cnz sp0 call scrlf call hdr1 lda rsflg ora a cnz sp1 call sp2 call hdr1 lda rsflg ora a cnz sp1 call sp2 call hdr1 lda rsflg ora a cnz sp1 jmp xdir6b sp0: call sprint db ' RS',0 ret sp1: call sprint db ' --',0 ret sp2: call sprint db ' ',0 ret hdr1: call sprint db '-------- --- ------',0 ret hdr2: call sprint db 'Filename.Typ Size K',0 ret ; ; Prepare Columnar Output ; xdir6b: lda pflgs ; restore print flag 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 prentsp ; print entry with 2 leading spaces shld ptr2 ; put ptr dcr e ; count down jz xdir10 lhld ptr3 ; get ptr call prentsp ; print entry with 2 leading spaces 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 pflg ; printer output? ora a ; 0=no jnz xdir6 call print ; screen break db cr,lf,' --> Screen Break -- Strike any char <-- ',0 call cin ; get response cpi 3 ; abort? jz return jmp xdir6 ; new screen display ; ; Print end statistics and exit ; xdir10: ; ; Print DU ; call sprint ; print everywhere db cr,lf,' ',0 call retud ; get current disk mov a,b ; ... in A adi 'A' ; convert to ASCII call sout ; print everywhere mov a,c ; user in A call sadc ; get number call sprint db ': ',0 call dutdir ; convert to DIR form jz xdir11 ; ; Print DIR Name ; mvi b,8 ; output name dirout: mov a,m ; get char cpi ' ' ; don't print spaces cnz sout inx h ; pt to next dcr b ; count down jnz dirout ; ; Print Selected File Statistics ; xdir11: call sprint db ' --',0 lhld fcount ; print file count call shldc ; print it everywhere call sprint db ' Files Using ',0 lhld totsiz ; get total of file sizes call shldc ; print it everywhere call sprint db 'K',0 ; ; Print Space Remaining on Disk ; Entry Point if No Files Found ; call sprint db ' (',0 lhld freesiz ; get amount of free space call shldc ; print it everywhere call sprint db 'K Left)',0 lda pflg ; new line if printer output ora a jz return call scrlf ; new line for 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 ; ; General Utility Routines ; ; ; Print disk entry for normal directory display functions ; prentsp: call sp2 ; print entry with 2 leading spaces prentry: dcr d ; count counter jnz prent1 mvi d,3 ; reset count call scrlf prent1: shld entptr ; save entry ptr inx h ; pt to first char of file name mvi b,8 ; print 8 chars call prch mvi a,'.' ; print dot call sout push h ; save RS ptr mvi b,3 ; print 3 chars call prch push d ; save de lhld entptr ; pt to entry call sp2 ; skip 2 spaces 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 shldc ; 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 sout 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 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 sout ; 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 jmp sout prlets: mvi a,' ' ; print jmp sout ; ; 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 gflg: ds 1 ; 0=group by name/type hflg: ds 1 ; 0=vertical list pflg: ds 1 ; printer output on flag crcnt: ds 1 ; entry counter fmark: ds 1 ; first file marker pflgt: ds 1 pflgs: ds 1 rsflg: ds 1 ; RS Display Flag ffflg: ds 1 ; form feed flag rem: ds 1 ; remainder buffer firstf: ds 2 ; ptr to first file of group to print 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 buffer: ds 2 ; pointer to free area stack: ds 2 ; stack ptr end