TITLE "ZSDOS EXtended Directory Lister" ;========================================================================== ; Z X D Z-System eXtended Directory Lister ;-------------------------------------------------------------------------- ; Derived from XD III Ver 1.2, 8 Apr 84 by Richard Conn. ; Changes Copyright (C) 1988 by Harold F. Bower, All Rights Reserved ;-------------------------------------------------------------------------- ; ZXD was modified from XD III to take advantage of the Date Stamping ; capabilities of ZSDOS. Features of Rick Conn's full-blown XDIR were ; added, as well as modified formats for Date Stamp displays. Version 4 ; of "The Libraries" MUST be used to link this program due to the added ; files tailored for Date/Time Stamping support. ; ; Link as: ZLINK ZXD,DSLIB/,Z3LIB/,SYSLIB/ ; ; Revisions: ; 1.66 - 3 May 92 - Use GETNAME/PRTNAME for Help. HFB ; 1.65 - 4 Apr 92 - Modified to use 3 bytes of size of ZSDOS2 . HFB ; 1.64 - 11 Jul 91 - Corrected bug in No-Date Listing HFB ; 1.63 - 14 Oct 90 - Changed to use pointers instead of recs HFB ; 1.62 - 21 May 89 - Added embedded Config tag for ZCNFG HFB ; 1.61 - 20 May 89 - Corrected default DU under vanilla CP/M HFB ; 1.60 - 15 May 89 - Added Parse routine to work w/o ZCPR 3 HFB ; 1.6 - 13 May 89 - Maximized Library usage HFB ; 1.50 - 9 Jan 89 - Added CP/M Plus free space calc HFB ; 1.5 - 27 Dec 88 - Added CP/M Plus Time/Date in header HFB ; 1.4 - 10 Dec 88 - Corrected glitch in hilite on/off HFB ; 1.3a - 5 Dec 88 - Print Create date if no Modify exists, check only ; DOS clock, Not DateStamper if ZDDOS. HFB ; 1.3 - 30 Nov 88 - Final release HFB ; 1.2a - 25 Nov 88 - Added DateStamper (tm) clock if no ZS HFB ; 1.2 - 17 Nov 88 - Formal release version HFB ; 1.1b - 11 Nov 88 - Fixed select glitch for /as Option. HFB ; 1.1a - 5 Nov 88 - Added WHEEL sensing & Disabling HFB ; 1.1 - 26 Sep 88 - Added video attributes under ZCPR3 HFB ; 1.0 - 17 Sep 88 - Initial Release HFB ;========================================================================== VERS EQU 16 ; Released Version rev equ '6' DATE MACRO DEFB '3 May 92' ENDM ;--------- ; ZXD -- Simple Extended Disk Directory Program ; ZXD produces a formatted, alphabetized listing of the contents of ; the disk directory of the implied (current logged-in) or specified disk. ; ZXD is invoked by a command line of the following form -- ; ZXD [dir:]fn.ft [/]ooo... ; or ; ZXD /oooo... ; Where: ; dir = optional directory name or disk/user specification (du) ; If dir is omitted, ZXD defaults to the current disk/user ; fn.ft = optional ambiguous file name and type (* and ? may be used) ; o = option letters as: ; 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=H to Toggle Hor/Vert ; P - Print display as well as show it on the screen ; PF - Same as POF ; U - Print all user areas ; W - Print both Created and Modified dates ; D - Toggle display of Date (US/European) from default ; T - Toggle Method of Time Stamps to use (P2Dos/DateStamper) ; S - Sort with reversed parameters (Name then Type or reversed) ; N - Toggle Date/No-Date in listing ; 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 precedence ; ; If the User does not have WHEEL privileges, options A, P and U are not ; recognized, and do not appear in the on-line Help message. ;..... ; CP/M Equates BDOS EQU 0005H FCB EQU 005CH BUFF EQU 0080H CR EQU 0DH FF EQU 0CH LF EQU 0AH FNSIZE EQU 16 ; Basic File Name & Type Size ESIZE EQU FNSIZE+15 ; Entry Size + Create, Access & Modify times OPTCH EQU '/' ; Option char MAXENT EQU 40 ; Maximum number of entries/screen (20 lines) PUBLIC COUT ; Call to BOUT will be COUT to SYSLIB routines ; External Library references: EXT DDIRQS, FINDCK, RDCLK, P2UTIM, TIMINI, RCLOCK ; Dslib EXT RCLOCK, GETDOS, DOSTYP, DOSVER ; " EXT Z3VINIT, STNDOUT, STNDEND, TINIT, DINIT ; Vlib EXT Z3LOG, WHRENV, DUTDIR, GETWHL, ZPRSFN ; Z3lib EXT GETNAME, PRTNAME ; " EXT DFREE, DPARAM, FSIZE, LCRLF, CIN, LOUT, FILLB ; Syslib EXT CODEND, RETUD, LOGUD, COMPHD, SCTLFL, SOUT, BOUT ; " EXT SCRLF, SHLDC, SADC, SAFDC, SPRINT, SPSTR ; " ;================================================================= ; S T A R T T H E P R O G R A M ;================================================================= JP START ; Bypass header and start execution DEFB 'Z3ENV' ; This is a ZCPR3 Utility DEFB 1 ; External Environment Descriptor Z3EADR: DEFW 0001 ; Set Non-zero to force search DEFW 0000 ; Filler for Type 4 Header DEFB 'ZXD ',0 ; Use this Configuration File ;..... ; Default Flags IUSR: DEFB 0 ; All users (0 = no, FF = All users) IFMT: DEFB 0 ; 0=Vertical format, FF= Horizontal format IFF: DEFB 0 ; enable form feed at end (0=no) ISORT: DEFB 0 ; 0=Sort Name then Type, FF=Type then Name INDATE: DEFB 0 ; 0=Print With Dates, FF=Print without Dates WIDE: DEFB 0 ; 0=only modified dates, FF=create/modified STMODE: DEFB 0FFH ; 0=P2Dos Stamps, FF=DateStamper Stamps USEUR: DEFB 0 ; 0=US Date Format, FF=European Date Format IATT: DEFB 10000000B ; Non-System files only BLNKYR: DEFB 0 ; 0=Always print Year, FF=Blank Year if current ; ********* Start of ZXD ********* START: LD (STACK),SP ; Save stack ptr for return CALL CODEND ; Determine free space LD DE,100H ; Allow 1 page for command line & stack EX DE,HL ADD HL,DE LD (BUFFER),HL ; Start of free Buffer area LD SP,HL ; Set local stack PUSH DE ; Save page addr for command line copy LD HL,(Z3EADR) ; Pt to candidate ZCPR3 environment CALL WHRENV ; ..and find a valid one LD (Z3EADR),HL CALL Z3VINIT ; Initialize the ZCPR3 Env CALL GETNAME ;1.66 Get name by which invoked CALL RETUD ; Get entry DU for later restoration LD (ENTRUD),BC ; .on exit LD (FCB+13),BC ; ..and default DU if no args CALL TIMINI ; Initialize Clock and Dos Typeing CALL TINIT ; Initialize the Terminal CALL GETWHL ; Get any existing Wheel byte OR A ; ..setting flags LD (WHEEL),A ; Save it locally for later testing JR NZ,START0 ; ..jump if User has wheel LD (IUSR),A ; Disable "All User" w/Null in A LD A,10000000B ; ..and set for only Non-System files LD (IATT),A START0: CALL SPRINT ; Print the opening banner DEFB 'ZXD Ver ',VERS/10+'0','.',VERS MOD 10 + '0',rev,0 ; Save command line in CMDLNE buffer POP DE ; Restore page addr to DE LD HL,BUFF+1 ; Copy input line into command line buffer START1: LD A,(HL) ; Get byte LDI ; Move a byte and advance ptrs OR A ; End of Line? JR NZ,START1 ; Parse Filename per ZCPR3 specifications LD HL,BUFF+1 FLOOP: LD A,(HL) ; Scan over spaces INC HL ; ..point to next OR A ; End-of-Line? JR Z,FLOOPX ; ..jump if so CP ' ' ; Space? JR Z,FLOOP ; ..jump if so DEC HL ; Back down to first char LD DE,FCB ; Parse to this location PUSH DE ; Save FCB addr LD B,11 LD A,'?' FLOOP1: INC DE ; Fill FN & FT fields w/"?" LD (DE),A DJNZ FLOOP1 ; ..loop til done POP DE ; Restore FCB addr LD A,1 ; Do DU: before DIR: CALL ZPRSFN ; ..do it ; Try to display time and set current year if found w/ZSDOS or DateStamper FLOOPX: CALL PRTOD ; Print Time of Day (NZ ret is Ok) JR NZ,ISZS1 ; ..jump if no clock present w/0FE in A LD A,(BUFF) ; Else get Current Year ISZS1: LD (CURYR),A ; ..and save ; Log into DU or DIR LD DE,FCB ; Get file name into FCB, and get user and disk CALL Z3LOG ; ZCPR3 command line interpretation ; Get and save current user number CALL RETUD ; Get current user and disk LD (SELUD),BC LD A,C ; ..User to A AND 1FH ; Mask all but user bits LD (AFLG),A ; current user number ; Transfer default Flag values to working flags LD HL,IUSR ; Move eight default regs.. LD DE,UFLG ; ..to working locations LD BC,8 LDIR LD C,(HL) ; Get file attributes (IATT) to C LD A,(AFLG) ; Get current user number OR C ; Mask in file attributes LD (AFLG),A ; ..and save XOR A ; A=0 LD (PFLG),A ; Set NO Printer output INC A ; A=1 for console only LD (SCTLFL),A ; Set switched output flag ; Assume wild file name LD HL,FCB+1 ; store '?' chars LD B,11 ; 11 chars LD A,(HL) ; check for entry specified CP ' ' ; test for space (means no entry) JR Z,FILLQ ; ..jump to fill if no entry CP OPTCH ; test for option flag FILLQ: LD A,'?' ; prep for '?' fill CALL Z,FILLB ; Scan command line for options CALL CODEND ; Pt to first char in buffer DEC HL ; ..precompensate for search increments SKIP00: INC HL ; Advance to next char LD A,(HL) ; Get char CP ' ' ; Is it a space? JR Z,SKIP00 ; ..loop if not to check next OR A ; end of line? JP Z,ZXDIR ; ..begin main processing if so INC HL ; Prepare for option CP OPTCH ; Is it an Option? JR Z,OPT ; ..jump to process options if so DEC HL ; Ok to process for DIR:filename.typ form ; Skip over characters of file name SKIPO1: LD A,(HL) ; Get char INC HL ; ..point to next OR A ; Is it the end of string? JP Z,ZXDIR ; ..jump to run ZX if no options follow CP ' ' ; Is it a space? JR NZ,SKIPO1 ; ..loop if not space ; Scan complete -- look for possible following option char SKIPO2: LD A,(HL) ; Get char INC HL ; ..point to next CP ' ' ; Is it a space? JR Z,SKIPO2 ; ..loop if so CP OPTCH JR Z,OPT ; Have option Char, so jump DEC HL ; Else back up since this is Option Char ; Look for options -- main loop; HL pts to next char OPT: LD A,(HL) ; get option char INC HL ; pt to next LD (PTR1),HL ; Save option line ptr OR A ; end of line? JP Z,ZXDIR ; begin main processing CP ' ' ; skip over spaces JR Z,OPT ; Scan option table CP 'O' ; Output Control JR Z,OPTO CP 'S' ; Sort Order control JR Z,OPTS CP 'N' ; Date/No Date control JR Z,OPTN CP 'W' ; Wide Display control JR Z,OPTW CP 'D' ; Date Display (US/European) control JR Z,OPTD CP 'T' ; Time Stamp method control JR Z,OPTT PUSH AF ; Save char while we check for Wheel LD A,(WHEEL) OR A JR Z,OPTER0 ; ..jump if user is not a Wheel POP AF ; Else restore byte and continue CP 'P' ; Print Control JR Z,OPTP CP 'U' ; User Select control JR Z,OPTU CP 'A' ; Attribute Control JR NZ,OPTERR ; ..list Help if not ;..else fall thru ; Option A -- File Attributes LD A,(HL) ; get next option letter LD C,10000000B ; ..Prepare for non-system CP 'N' ; Non-System files? JR Z,OPTRET LD C,01000000B ; ..Prepare for System CP 'S' ; System files? JR Z,OPTRET LD C,11000000B ; ..Prepare for All files CP 'A' ; All files? JR NZ,OPTERR ; ..jump to Help if Error (not A,N,S) OPTRET: LD A,(AFLG) ; Else Set File Attribute Options AND 00111111B ; Mask any existing bits OR C ; mask in sys/non-sys LD (AFLG),A ; restore flag INC HL ; pt to next JR OPT ; Option P -- enable it; Printer output OPTP: LD A,0FFH ; ON LD (PFLG),A LD (SCTLFL),A ; set S-output control LD A,(HL) ; get possible 2nd letter CP 'F' ; set form feed if F JR NZ,OPT ; process as next option letter if not F INC HL ; pt to next LD (PTR1),HL ; Save current addr OPTOF: LD HL,FFFLG ; Toggle FF Flag DEFB 0DDH ; Trash IX and fall thru ; Option W -- Wide (create and modify dates) display OPTW: LD HL,WFLG ; Set for user flag DEFB 0DDH ; Trash IX and fall thru ; Option U -- Control User Selection parameter OPTU: LD HL,UFLG ; Set pointer for user flag DEFB 0DDH ; Trash IX and fall thru ; Option S -- Sort Order Selection parameter OPTS: LD HL,SFLG ; Set pointer for Sort order flag DEFB 0DDH ; Trash IX and fall thru ; Option D -- Swap to alternate Date display mode (US/European) OPTD: LD HL,DFLG ; Set pointer for Date Flag DEFB 0DDH ; Trash IX and fall thru ; Option T -- Swap to alternate Time Stamp Method (P2Dos/DateStamper) OPTT: LD HL,TFLG ; Set pointer for TimeStamp Flag DEFB 0DDH ; Trash IX and fall thru ; Option N -- Toggle between prints With Dates and Without Dates OPTN: LD HL,NFLG ; Set pointer for No Date Flag OPFLIP: LD A,(HL) ; Get byte CPL LD (HL),A ; ..and save it again LD HL,(PTR1) ; Restore buffer pointer JP OPT ; ..and continue ; Option O -- control Output parameters OPTO: LD A,(HL) ; get 2nd letter INC HL ; pt to next LD (PTR1),HL ; Save pointer address CP 'F' ; form feed? JR Z,OPTOF CP 'H' ; horizontal/vertical? JR NZ,OPTERR ; ..jump to Help on Error (Not F or H) LD HL,HFLG ; Else flip Horiz/Vert flag JR OPFLIP ;..... OPTER0: POP AF ; Clear stack for Error entry OPTERR: LD A,1 ; set console only LD (SCTLFL),A ; set output control flag CALL SPRINT DEFB CR,LF,LF,'Syntax: (' DATE DEFB ' Ver)',CR,LF,' ',0 CALL COMNAM ;1.66 CALL SPRINT ;1.66 DEFB ' - List per Defaults' DEFB CR,LF,' ',0 CALL COMNAM ;1.66 CALL SPRINT ;1.66 DEFB ' // - Print this message' DEFB CR,LF,' ',0 CALL COMNAM ;1.66 CALL SPRINT ;1.66 DEFB ' /o[o..] - List per options' DEFB CR,LF,' ',0 CALL COMNAM ;1.66 CALL SPRINT ;1.66 DEFB ' [dir:][fn[.ft]] [/][o[o..]] - List selected w/opts' DEFB CR,LF,'Options:' DEFB CR,LF,' Oo - Toggle Output Control Options' DEFB CR,LF,' ',0 LD A,(WHEEL) ; Does user have Wheel privileges? OR A JR Z,OPTER1 ; ..bypass a line if so CALL SPRINT DEFB 'o=F for Form Feed, ',0 OPTER1: CALL SPRINT DEFB 'o=H for Horiz/Vert Format' DEFB CR,LF,' S - Toggle Sort (Name/Type or Type/Name)' DEFB CR,LF,' N - Toggle No-Date/Date display' DEFB CR,LF,' W - Wide display with both Create/Modify Dates' DEFB CR,LF,' D - Display Date in alternate form' DEFB CR,LF,' T - Use alternate (P2Dos/DateStamper) Stamps',0 LD A,(WHEEL) ; Does user have Wheel privileges? OR A JP Z,RETURN ; ..exit if not, Else fall thru.. CALL SPRINT DEFB CR,LF,' Aa - Set and Display of file attributes' DEFB CR,LF,' a=S for System, a=N for Non-System' DEFB CR,LF,' a=A for All Files (System and Non-System)' DEFB CR,LF,' U - Toggle User select (Current or All)' DEFB CR,LF,' P - Send display to Printer' DEFB CR,LF,' PF - Same as POF' DEFB CR,LF,0 RETURN: CALL DINIT ; De-initialize the Terminal LD BC,(ENTRUD) ; Get entry DU CALL LOGUD ; ..and restore LD SP,(STACK) ; get old stack ptr RET ; return to Dos ;..... ;1.66 Print name by which invoked or default name COMNAM: LD A,(Z3EADR+1) ;1.66 Get high byte of ENV OR A ;1.66 Anything there? JP NZ,PRTNAME ;1.66 ..jump to print "real" name if so CALL SPRINT ;1.66 Else print default name DEFB 'ZXD',0 ;1.66 RET ;1.66 ;..... ; Memory Overflow Error MEMERR: CALL SPRINT DEFB '- TPA Overflow -',0 JR RETURN ;================================================================ ; ..Begin ZX processing ZXDIR: LD DE,FCB ; Point to the File Control Block ; Check for Print Option and Print New Line if so LD A,(PFLG) ; printer output? OR A ; 0ffH=yes CALL NZ,LCRLF ; new line ; Get Files from Disk CALL DPARAM ; get disk parameters for DFREE LD BC,(SELUD) CALL LOGUD LD A,(TFLG) ; Which mode of Stamps do we want? AND 00000001B ; ..(keeping only LSB) LD C,A ; ..(Set search flag as well) LD A,(SFLG) ; AND B7 of Sort Order Flag AND 10000000B OR C ; ..with Time Stamp Method LD C,A LD HL,(BUFFER) ; Pt to free space LD A,(UFLG) ; get users flag AND 20H ; mask for user select bit (0=name/type) LD B,A LD A,(AFLG) ; get attributes flag OR B ; mask in grouping bit PUSH DE ; Save the FCB Pointer CALL DDIRQS ; quick directory load with file sizes LD (FIRSTF),DE ; Store the start of pointer table POP DE ; ..and restore FCB pointer JR Z,MEMERR ; memory overflow error? LD (FCOUNT),BC ; save file count LD (COUNTF),BC ; save file down count CALL GETDOS ; Get the Dos Version in operation LD A,(DOSTYP) CP 'S' ; Is it ZSDOS? JR NZ,DOCPMS ; ..to CP/M sizing way if not LD A,(DOSVER) CP 20H ; Is the Version # >= 2.0? JR C,DOCPMS ; ..do CP/M sizing way if < 2.0 LD DE,BUFF ; Else this is ZSDOS2 LD C,26 ; Set DMA to Default Buffer CALL BDOS LD A,(SELUD+1) ; Get Desired drive LD E,A LD C,46 CALL BDOS ; Get Free space in K in BUFF..BUFF+3 LD A,(BUFF+2) ; Get third byte in Size LD (FREESZ+2),A ; Save Byte 3 LD DE,(BUFF) ; .get bytes 1 and 2 JR DOCPMT ; ..and rejoin code DOCPMS: CALL DFREE ; compute amount of free space on disk DOCPMT: LD (FREESZ),DE ; save 16-bits of free space count LD DE,0000 ; set file size counter LD (TOTSIZ),DE ; save counter XOR A ; Clear third byte of size too LD (TOTSIZ+2),A LD A,(PFLG) ; set temp flag LD (PFLGT),A LD HL,PFLGS ; Address Save Flags location LD A,(PFLG) ; save printer output flag LD (HL),A ; ..in Save locn DEC HL ; Point to PFLGT LD A,(HL) ; Use Temp Flag LD (PFLG),A ; ..in Real pointer LD (HL),00 ; ...and clear Temp Flag ; Check for any files LD HL,(COUNTF) ; get file down count LD A,H ; any files? OR L JP Z,NFMSG ; ..jump to No Files message if Not ; Everything set up now. Set flag for number of columns in display LD A,(NFLG) ; Are we listing Without Dates? LD B,3 OR A JR NZ,ZX2A ; ..jump to set 3 cols if so LD A,(WFLG) ; Are we listing both dates? DEC B OR A JR Z,ZX2A ; ..jump to set 2 cols if Not DEC B ; Else set to 1 col ZX2A: LD A,B ; Get the number LD (NCOLS),A ; ..and Store ; This is the main looping entry point for each screen display ; Display the Screen Header Information ZX6: CALL SCRLF ; specific user selected CALL STNDOUT ; ..Give some video highlighting LD A,(NCOLS) ; Get number of columns LD B,A ; ..and put in Reg PUSH BC ; Save count for second header line DOHDR0: LD A,(UFLG) ; Display all User Areas? LD HL,HDR1 ; ..prepare for a Yes OR A ; Z=no JR NZ,DOHDR1 ; ..jump if so LD HL,HDR1A DOHDR1: CALL SPSTR ; Print Header Text Entry LD A,(NCOLS) ; Get Number of Columns in listing LD HL,HDR1B ; ..prepare for both dates CP 2 ; Are we printing with just Modified? JR C,DOHDR2 ; ..jump if both dates JR NZ,DOHDR7 ; ...or here if No dates LD HL,HDR1C ; Else set for just Modified dates DOHDR2: CALL SPSTR ; Print Date Entries DOHDR7: CALL HDRSEP ; Print Header separator if required DEC B ; More entries? INC B JR NZ,DOHDR0 ; ..loop if more than 1 column entry CALL STNDEND ; Turn Highlighting off for new line POP BC ; Restore for second header line CALL SCRLF ; ..and advance to next line CALL STNDOUT ; Turn Highlighting on for new line DOHDR3: LD A,(UFLG) ; Are we printing all User Areas? LD HL,HDR2 ; ..prepare for a Yes OR A ; Z=no JR NZ,DOHDR4 ; ..jump if so LD HL,HDR2A DOHDR4: CALL SPSTR ; Print Header Text Entry LD A,(NCOLS) ; Get Number of Columns in listing LD HL,HDR2B ; ..prepare for Yes CP 2 ; Are we printing with just Modified? JR C,DOHDR5 ; ..jump if both dates JR NZ,DOHDR6 ; ...or here if No dates LD HL,HDR2C ; Else set for just Modified dates DOHDR5: CALL SPSTR ; Print Date Entries DOHDR6: CALL HDRSEP ; Print Header separator if required DEC B ; More entries? INC B JR NZ,DOHDR3 ; ..loop if more than 1 column entry CALL STNDEND ; End Reverse video ; Prepare Columnar Output LD A,(PFLGS) ; restore print flag LD (PFLG),A LD DE,MAXENT/2 ; Calculate # of entries LD HL,0 LD A,(NCOLS) ; Get number of cols in display LD B,A ZX6B: ADD HL,DE ; Add in # Entries per column DJNZ ZX6B ; ..loop til done EX DE,HL ; Put result in DE LD HL,(COUNTF) ; Get file count Remaining CALL COMPHD ; check for HL > DE JR NC,ZX7 ; subtract entries to print from total entries LD D,H ; DE=HL=number of entries to print LD E,L ZX7: XOR A ; subtr entries to print (DE) from total (HL) SBC HL,DE ; HL=result LD (COUNTF),HL ; save new down count LD B,H ; BC=count LD C,L LD HL,(FIRSTF) ; Point to First Record Pointer ; At this point, BC=number of remaining entries, DE=number of entries to ; print, and HL pts to first entry to print LD (PTR1),HL ; Save ptr to 1st entry LD A,(HFLG) ; Are we listing horizontally? LD B,A LD A,(WFLG) ; ..or showing Wide Display? OR B JR NZ,ZX7C ; ..jump if either and don't worry about cols PUSH DE ; save count LD A,(NFLG) ; Are we listing with No Dates? OR A JR Z,ZX70 ; ..jump if listing Dates CALL DIVDE3 ; Else div DE by 3, result * 2 in BC, A = Rem JR ZX72 ; ..and rejoin code ; Divide DE by 2, result * 2 in BC (Ptr size), remainder in A ZX70: SRL D ; divide by 2 RR E LD A,0 ; Get remainder in A ADC A,A PUSH HL ; Preserve HL LD L,E ; Copy result to HL LD H,D ADD HL,HL ; Double for 2-byte ptrs LD C,L ; ..and put result in BC LD B,H POP HL ZX72: ADD HL,BC ; Add offset (in BC) to 2nd Col Start OR A ; Any remainder? JR Z,ZX7A ; ..skip if none INC HL ; Else advance 1 Ptr to next entry INC HL ZX7A: LD (PTR2),HL ; ..Save ptr to Col 2 ADD HL,BC ; Add offset (in BC) to 3rd Col Start CP 2 ; If remainder 2, advance one more Ptr JR C,ZX7B INC HL INC HL ZX7B: LD (PTR3),HL ; ..Save ptr to Col 3 POP DE ; Get count back in DE ; Main entry print routine ZX7C: LD D,1 ; set Columns counter to initial value ZX8: LD HL,(PTR1) ; Pt to first entry CALL PRENTRY ; Print entry LD (PTR1),HL ; Put pointer LD A,(WFLG) ; Wide print? OR A JR NZ,ZX9 ; ..jump if so LD A,(HFLG) ; Horizontal Display? OR A JR Z,ZX8A ; ..jump if Not DEC D ; Last entry in line? CALL NZ,SP2 ; ..print 2 spaces if so INC D ; ...correct counter JR ZX9 ; Continue below ZX8A: DEC E ; count down JR Z,ZX10 LD HL,(PTR2) ; get ptr CALL PRENTSP ; Print entry with 2 leadin spaces LD (PTR2),HL ; put ptr LD A,(NFLG) ; Are we listing with No Dates? OR A JR Z,ZX9 ; ..jump if listing Dates DEC E ; Count down JR Z,ZX10 ; ..jump exit if done with screen LD HL,(PTR3) ; Get ptr to 3rd list CALL PRENTSP ; ..and list LD (PTR3),HL ; Save ptr ZX9: DEC E ; count down JR NZ,ZX8 ; continue if not zero LD (FIRSTF),HL ; Save ptr to next set of entries to print LD HL,(COUNTF) ; get count of remaining entries ; At this point, HL=number of entries left LD A,H ; anything left? OR L JR Z,ZX10 LD A,(PFLG) ; printer output? OR A ; 0=no JP NZ,ZX6 CALL SPRINT ; screen break DEFB CR,LF,'[more] ',0 CALL CIN ; get response CP 3 ; abort? JP Z,RETURN JP ZX6 ; new screen display ; No files were found. Print message and fall thru to exit stats NFMSG: CALL SPRINT ; print everywhere DEFB CR,LF,'-- No files --',0 ;..fall thru.. ; Print end statistics and exit ; Print DU ZX10: CALL SCRLF ; Print everywhere CALL SP2 ; Give some space CALL RETUD ; Get current disk LD A,B ADD A,'A' ; convert to ASCII CALL SOUT ; print everywhere LD A,(UFLG) ; Are we printing all users? OR A PUSH AF LD A,C CALL Z,SAFDC ; ..print user # if not LD A,':' CALL SOUT ; Print Colon POP AF JR NZ,ZX11 ; Jump if printing all users CALL DUTDIR ; Convert to DIR form JR Z,ZX11 ; ..bypass if error LD B,8 ; Print DIR name DIROUT: LD A,(HL) ; get char CP ' ' ; don't print spaces CALL NZ,SOUT INC HL ; pt to next DJNZ DIROUT ; Print Selected File Statistics ZX11: CALL SPRINT DEFB ' -- ',0 LD HL,(FCOUNT) ; print file count XOR A ; .dummy a 3-byte value CALL PRBIG ; ..and use common routine CALL SPRINT DEFB ' Files Using ',0 LD HL,(TOTSIZ) ; Get total of file sizes LD A,(TOTSIZ+2) ; ..including 3rd byte CALL PRBIG ; Print it everywhere CALL SPRINT DEFB 'K',0 ; Print Space Remaining on Disk ; Entry Point if No Files Found CALL SPACE CALL STNDOUT ; Highlight this LD A,'(' CALL SOUT LD HL,(FREESZ) ; Get amount of free space LD A,(FREESZ+2) CALL PRBIG ; Print it everywhere CALL SPRINT DEFB 'K Free)',0 CALL STNDEND LD A,(PFLG) ; new line if printer output OR A JP Z,RETURN CALL SCRLF ; new line for printer LD A,(PFLG) ; print output LD B,A LD A,(FFFLG) ; form feed AND B ; if print and form feed ... NZ is set LD A,FF ; form feed char CALL NZ,LOUT ; form feed to printer JP RETURN ;********* General Utility Routines ******** ; Print one or two spaces SP2: LD A,' ' CALL SOUT SPACE: LD A,' ' JP SOUT ;..... ; Print BCD digits as two ASCII digits ; ENTER: BCD digits in A OUTBCD: PUSH AF RRA RRA RRA RRA CALL PT1 POP AF PT1: AND 0FH ADD A,'0' JP SOUT ;..... ; Print B chars pted to by HL PRCH: LD A,(HL) ; get char INC HL ; pt to next BIT 7,A ; Check MSB, print lowercase if set JR Z,PRCH0 AND 7FH ; Mask out MSB CP 'A' ; Convert char to Lower case JR C,PRCH2 ; ..jump if less than "A" CP 'Z'+1 ; Greater than "Z"? JR NC,PRCH2 ; ..jump if so OR 20H ; Else Make lowercase Alpha char PRCH2: CP ' ' ; Within printable range? JR NC,PRCH3 ; ..jump if so LD A,'?' PRCH3: SET 7,A ; Set MSB again JR PRCH1 PRCH0: CP ' ' ; Within printable range? JR NC,PRCH1 ; ..jump to print if so LD A,'?' ; Print "?" if not valid char PRCH1: BIT 7,A ; Is MSB Set? PUSH AF CALL NZ,STNDOUT ; ..set reverse video if so POP AF PUSH AF AND 7FH ; ...and mask MSB CALL SOUT ; Print it POP AF CALL NZ,STNDEND ; ..set normal video if so DJNZ PRCH ; ..and loop til done RET ;..... ; Print individual file entry per established flags: UFLG, NFLG, WFLG, DFLG ; Enter: HL --> Addresses element in sorted DDIRQS entry ; D = Number of entries per line remaining ; E = Number of entries remaining until end or screen break ; Exit : HL --> Start of Next entry ; D = # entries/line remaining + 1 ; E = Unaffected PRENTSP: CALL SP2 ; Print entry with 2 leading spaces PRENTRY: DEC D ; Count counter JR NZ,PRFENT LD A,(NCOLS) ; Get count of columns LD D,A ; ..and Reset Count CALL SCRLF ; Print a single file entry PRFENT: LD (ENTPT0),hl ; Save entry pointer to Ptr Table LD A,(HL) ; Get Record Addr pointed to INC HL LD H,(HL) LD L,A ; We now point to Record LD (ENTPTR),HL ; ..and Save LD A,(UFLG) ; Are we to print all users? OR A JR Z,PREN1A ; ..jump if not LD A,(HL) ; If so, get user # AND 1FH ; ..mask other bits CALL SADC ; Print user # LD A,':' ; ..and colon separator CALL SOUT PREN1A: INC HL ; Pt to first char of File Name LD B,8 ; ..print 8 chars CALL PRCH LD A,'.' ; Print dot CALL SOUT LD B,3 ; Print 3 chars CALL PRCH PUSH DE ; save Counts PUSH HL ; ..and pointer LD HL,(ENTPTR) ; Restore Ptr to entry CALL FSIZE ; compute file size LD HL,(TOTSIZ) ; Get total file size counter LD A,(TOTSIZ+2) ; ..including 3rd byte ADD HL,DE ; Add in new file ADC A,0 ; ..into 3rd byte LD (TOTSIZ),HL ; Save new total file size counter LD (TOTSIZ+2),A ; ..for 3 bytes EX DE,HL ; Get file size into HL CALL SHLDC ; ..and print (HL) value in decimal LD A,'k' CALL SOUT POP HL ; pt to Extent LD BC,4 ; ..offset to date/time fields ADD HL,BC LD A,(NFLG) ; Are we printing Dates? OR A LD BC,ESIZE-FNSIZE ; ..(set offset to next entry in case not) CALL Z,PRDDAT ; Print date entry(s) if Not NFLG POP DE ; Restore counters LD HL,(ENTPT0) ; Get entry pointer INC HL ; .advance INC HL ; ..to next entry LD A,(UFLG) ; Are we working with all users? OR A RET NZ ; ..return if So DEC D ; Last entry in line? CALL NZ,SPACE ; ..Print a space if not INC D RET ;..... ; Print appropriate separator based on value of DFLG (US/European) PRSEP: LD A,(DFLG) OR A ; Get separator for Date LD A,'.' ; ..set European for default JR NZ,EUR1 ; Jump if European LD A,'/' EUR1: JP SOUT ;..... ; Print Date field in display in " HH:MM-DD.MM.YY" or " HH:MM-MM/DD/YY" ; form depending on USEUR flag. ; Enter: HL --> Created time field of sorted DDIRQS Directory list ; = 0 if just Modified desired, FF for both Create and Modified PRDDAT: LD A,(WFLG) ; Check for Wide Display LD B,3 ; ..preset for 3 Date entries OR A JR NZ,DATTIM ; jump if both dates DEC B ; ..else just one.. DEC B LD DE,10 ADD HL,DE ; ..and offset to modified DATTIM: PUSH BC ; Save pass counter CALL SP2 ; ..and give some space LD A,(HL) ; Get Years byte INC HL ; ..advance to Month field OR (HL) ; "Or" Years and Months JR NZ,DATTI0 ; ..jump to print if Ok LD A,(WFLG) ; Are we printing wide? OR A JR NZ,NULDAT ; ..jump to Null date if so DEC HL ; Else back up to field start PUSH HL ; Save regs PUSH BC EX DE,HL ; Put Mod date addr in DE LD HL,-10 ; Back up to Create date ADD HL,DE LD BC,5 LDIR ; Copy Create to Modify POP BC POP HL LD A,(HL) ; Check for validity INC HL OR (HL) JR Z,NULDAT ; ..print blank field if no date stamp DATTI0: PUSH HL ; Save Ptr to Month INC HL ; ..and advance to Hours INC HL BIT 7,(HL) ; Is it a Relative count? JR NZ,TIME0 ; ..jump if so CALL PR2DIG ; Else Print 2-digit time JR TIME1 ; ..and continue below TIME0: CALL PRREL ; Print Relative time TIME1: LD A,'-' ; Separate Time from Date CALL SOUT POP HL ; Restore ptr to Month LD A,(DFLG) ; US or Eur formats? OR A JR NZ,EUR0 ; ..jump if European format EUR2: LD A,(HL) CALL OUTBCD ; Print BCD digits for Month LD A,(DFLG) OR A ; Get separator for Date JR NZ,PRYEAR ; ..and jump to year if European CALL PRSEP ; Else print appropriate separator EUR0: INC HL ; Advance to Day LD A,(HL) DEC HL ; Back up to Month CALL OUTBCD ; Print BCD digits for Day LD A,(DFLG) OR A ; Get separator for Date PUSH AF CALL NZ,PRSEP ; Print Seperator if Not current year POP AF JR NZ,EUR2 ; ..and jump if European form for Month PRYEAR: DEC HL ; Back up from Month to Year LD A,(BLNKYR) ; Blank current Year? OR A JR Z,PRYEA0 ; ..jump if not LD A,(CURYR) ; Get current year CP (HL) ; Is this file from the same year? JR NZ,PRYEA0 ; ..jump if not CALL SP2 ; Else fill in with spaces CALL SPACE JR PRYEA1 PRYEA0: CALL PRSEP ; Not current year, print seperator LD A,(HL) CALL OUTBCD ; Print Year BCD digits PRYEA1: LD BC,5 ; Offset to after current date field ADD HL,BC POP BC DJNZ DATTIM ; ..loop for second date if necessary RET ; Print Date and Time field as all spaces for Null date NULDAT: LD B,14 ; 14 for entry NULDA0: CALL SPACE ; Print a space DJNZ NULDA0 DEC HL ; Back up to Year byte JR PRYEA1 ; Exit thru above code ;..... ; Read and Print Time of day in default form as indicated by USEUR flag PRTOD: CALL SPRINT ; Give some space DEFB ' ',0 LD HL,BUFF ; Read time here CALL RCLOCK ; ..using Library routine RET NZ ; Return if Invalid Clock PRTOD1: CALL STNDOUT ; Print it in reverse video LD A,(BUFF+2) ; Get Day CALL OUTBCD ; ..and print CALL SPACE ; Space off one LD A,(BUFF+1) ; Get Month CP 10H ; See if >SEPT JR C,PRDMJ0 SUB 6 ; If so, Get rid of BCD bias PRDMJ0: LD E,A LD D,0 ; Put month in DE LD HL,MONTHS-3 ADD HL,DE ADD HL,DE ADD HL,DE ; Index into month table LD B,3 PRDMJL: LD A,(HL) INC HL CALL SOUT DJNZ PRDMJL CALL SPACE ; Space off one LD A,(BUFF) PUSH AF CP 78H ; See which century (78-99 are 19xx) LD A,20H ; ..(00-77 are 20xx) JR C,PRDMJ1 ; If 21st LD A,19H PRDMJ1: CALL OUTBCD ; Print prefix POP AF CALL OUTBCD ; Now last two digits CALL SP2 ; Separate time from date LD HL,BUFF+3 ; Point to Hours BIT 7,(HL) ; ..MSB Set for Relative time JR NZ,PRREL ; Use different print routine for rel time LD A,(HL) ; Get Hours INC HL CALL OUTBCD ; Output hour LD A,':' CALL SOUT ; Separate with a colon CALL PR2DIG ; ..then print minutes & seconds CALL STNDEND ; Turn off reverse vid XOR A ; Insure Zero flag set RET ; ..and return PR2DIG: LD A,(HL) ; Get Minutes INC HL CALL OUTBCD ; ..and output LD A,':' CALL SOUT ; Separate with a colin LD A,(HL) ; Get Seconds CALL OUTBCD ; ..and output RET ; Print Relative Stamp PRREL: LD A,'+' CALL SOUT ; Prefix with a + LD D,(HL) RES 7,D ; Clear Rel count flag for dsp INC HL LD E,(HL) ; Get Rel count EX DE,HL ; Put count in HL LD DE,-1000 CALL SUBTR LD DE,-100 CALL SUBTR LD DE,-10 CALL SUBTR LD A,L ; Remainder ADD A,'0' ; Ascii bias CALL SOUT ; Display XOR A ; Ensure Zero Set when returning RET SUBTR: LD C,'0'-1 ; Ascii count SUBT2: INC C ADD HL,DE ; Really subtract JR C,SUBT2 ; Keep going SBC HL,DE ; One too many,add back LD A,C ; Ascii count JP SOUT ; Else display MONTHS: DEFB 'JanFebMarAprMayJunJulAugSepOctNovDec' ;..... ; Dummy routine to use DOS IO instead of BIOS IO COUT: JP BOUT ; Use DOS character output ;..... ; Print separator spaces between header entries HDRSEP: LD HL,SPCS ; Point to three spaces LD A,(UFLG) ; Are we printing all user areas? OR A JR Z,HDRSE0 ; ..jump if not INC HL ; Else advance for just 2 spaces HDRSE0: DEC B ; Count down entries CALL NZ,SPSTR ; Print if Not last entry RET ;..... ; Header strings used for formatting HDR1: DEFB ' UU ' HDR1A: DEFB 'Filename.Typ Size',0 HDR2: DEFB ' -- ' HDR2A: DEFB '-------- --- ----',0 HDR1B: DEFB ' Created ' DEFB ' Last Access ' HDR1C: DEFB ' Modified ',0 HDR2B: DEFB ' ------- ' DEFB ' ---- ------ ' HDR2C: DEFB ' -------- ',0 SPCS: DEFB ' ',0 ;..... ; Divide DE by 3 and Return: BC = Result * 2 (ptr size); A = Remainder DIVDE3: PUSH HL LD D,0 ; Make sure D=0 LD A,E ; Value to A DIVD31: SUB 3 JR C,DIVD32 ; Jump if too much JR Z,DIVD33 ; ..or exactly INC D ; Add 1 to Result JR DIVD31 DIVD32: ADD A,3 ; Add back for underflow DEC D ; (prepare for next INC) DIVD33: INC D ; Add 1 for even division LD E,D ; Prepare for 16-bit Add LD D,0 LD L,E ; Copy the result to HL LD H,D ADD HL,HL ; ..and double for Pointer size (2 bytes) DIVD36: LD B,H ; BC is result LD C,L POP HL ; Restore regs RET ;..... ; Print Sizes in decimal with provisions for 3-byte values up to 999,999 ; Enter: A,H,L contains 24-bit value to print ; Exit : None. Value printed as up to 6 decimal digits PRBIG: LD E,A ; Save MSB XOR A ; Set flag for no digits yet LD (BIGFLG+1),A ; ..and save LD A,E ; Restore flag LD DE,86A0H ; 100,000 = 0186A0H, set lower 2 bytes LD B,01 ; ..and MSB CALL DIVBIG ; Divide and print LD DE,10000 ; Set 10k lower 2 bytes LD B,0 ; and MSB CALL DIVBIG ; Divide and print BIGFLG: LD B,00 ; .to register (inline modified) LD DE,1000 CALL DECDSP ; Print if non-0 or previous print LD DE,100 CALL DECDSP ; Print if non-0 or previous print LD DE,10 CALL DECDSP ; Print if non-0 or previous print LD A,L ; Get 1's JR DECDS0 ; ..and print DIVBIG: LD C,-1 ; Set initial result OR A ; Clear Carry DIVBL: INC C ; Bump count SBC HL,DE ; .subtract lower 2 bytes SBC A,B ; ..and upper byte JR NC,DIVBL ; ...looping til done ADD HL,DE ; Correct for underflow ADC A,B LD E,A ; .(save MSB) LD A,C ; Get Result OR A ; Is digit 0? JR NZ,DIVBP ; ..jump if Not LD A,(BIGFLG+1) ; Get Prior digit print flag OR A ; Anything printed yet? JR Z,DIVBX ; ..jump if Not XOR A ; Else print a Zero DIVBP: ADD A,'0' ; Make digit Ascii LD (BIGFLG+1),A ; ..save as new flag CALL SOUT ; Print digit DIVBX: LD A,E ; Get MSB back RET ; ..and quit ;..... ; Divide HL by DE converting remainder to ascii digit and printing it if ; the number is Non-Zero or a digit was previously printed DECDSP: OR -1 ; Clear flag and set initial count DECDSL: SBC HL,DE ; Divide by subtraction INC A ; .adjust counter JR NC,DECDSL ; ..loop til done ADD HL,DE ; Compensate for underflow JR NZ,DECDS0 ; ..jump if Non-zero div result OR B ; Else check for previous print RET Z ; ..return if No prev char & Zero result XOR A ; Otherwise print a Zero DECDS0: ADD A,'0' ; Convert to Ascii digit LD B,A ; ..and set flag for next pass JP SOUT ; Jump to switched output routine & return ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Uninitialized Buffer Space DSEG ; Put this in Data Segment ;----- ; The Next Eight entries MUST remain in the listed order UFLG: DEFS 1 ; 0=Select current user, 0FFH=Select all users HFLG: DEFS 1 ; 0=vertical list FFFLG: DEFS 1 ; Form Feed flag SFLG: DEFS 1 ; Sort order flag NFLG: DEFS 1 ; No Dates flag WFLG: DEFS 1 ; Wide Display flag TFLG: DEFS 1 ; Mode. 0=P2Dos Stamps, FF=DateStamper Stamps DFLG: DEFS 1 ; European/US. 0=US Dates, FF=European Dates AFLG: DEFS 1 ; Attribute Flag ;----- PFLG: DEFS 1 ; Printer Output ON Flag WHEEL: DEFS 1 ; Storage for Wheel byte from ZCPR3 CURYR: DEFS 1 ; Storage for current year from clock SELUD: DEFS 2 ; Selected Drive/User from command line PFLGT: DEFS 1 PFLGS: DEFS 1 NCOLS: DEFS 1 ; Storage for Number of columns in output ; 3 if NFLG, 2 if Not WFLG, else 1 if WFLG FIRSTF: DEFS 2 ; ptr to first file of group to print FCOUNT: DEFS 2 ; count of files COUNTF: DEFS 2 ; down count of files FREESZ: DEFS 3 ; Amount of Free Space on Disk (3-bytes worth) TOTSIZ: DEFS 3 ; Total Size of All files listed (up to 3 byes) PTR1: DEFS 2 ; col output ptrs PTR2: DEFS 2 PTR3: DEFS 2 ENTPTR: DEFS 2 ; current entry ptr ENTPT0: DEFS 2 ; Current Pointer to Pointer BUFFER: DEFS 2 ; pointer to free area ENTRUD: DEFS 2 ; Entry DU for restoration on exit STACK: DEFS 2 ; stack ptr END