; SD95 - SUPER DIRECTORY PROGRAM - 11/27/84 ; ; ASEG ; Needed for M80, ignore error made with MAC ; ; NOTE: This version can be assembled with ASM, LASM, ; MAC, RMAC or M80. The name has been slightly ; changed as M80 cannot use names with a dash. ; ;======================================================================= ; ; Displays the directory of a CP/M disk, sorted alphabetically, with the ; file size in k, rounded to the nearest CP/M block size. Also displays ; library files with the file size in k if the '$L' option is used. ; ;======================================================================= ; ; 11/27/84 Would not assemble with ASM or M80. Now it will. Replaced ; v95 22 'PUSH A' and 'POP A' with conventional 'PUSH PSW' and ; 'POP PSW'. Found four instances of labels being used more ; than once with the same name. MAC didn't mind but ASM and ; M80 bombed. Many nested conditionals changed to enable nor- ; rmal assembly with ASM or M80 in addition to MAC. Surprised ; this has not been done some time ago. Name slightly changed ; as M80 doesn't seem to accept names with a dash (like SD-95). ; - Irv Hoff ; ;======================================================================= ; Current versions of SD automatically adjust for any block size and di- ; rectory length under CP/M 1.4 or 2.x or MP/M (any version). They also ; automatically adjust for any number of disk drives and work satisfac- ; torily even if no disk is in that drive at the moment. Provisions are ; made for: ; ; (1) automatic pauses when the screen fills up ; (2) searching individual or multiple drives and/or user areas ; (3) unconditional or optional resetting the disk system before ; execution begins ; (4) directing output to a disk file called SD.DIR and appending ; to that file on subsequent runs ; (5) summary line output giving drive and user information, num- ; ber of files matched and how much space they consume, and ; the amount of free space remaining on the disk ; (6) displaying or suppressing "system" files ; (7) accepting ambiguous filenames with or without a drive name ; (8) printer output ; (9) can make a disk file of the results called DISKMENU.DIR ; ; ; See SD.DOC for detailed instructions on configuring and running SD.ASM ; ;======================================================================= ; ; 11/24/84 Fixed a display bug, also removed a colon from a macro line. ; v94 - Steve Sanders ; ; 11/20/84 In previous versions of SD "SD $L" gave a size of "0K" for ; v93 any library member file which was exactly 255 records in ; length. This bug is fixed in SD-93, with code supplied by ; Gene Head. - Paul Foote ; ; 07/27/84 Some systems do not have contiguous disk drives. The XEROX ; v92 820 hard disk system for example assigns the only floppy ; drive as A: and the hard disk as drives E:, F:, G: & H: ; Code has been added to skip any drive whose maximum user ; area in the 'Drive code/user area lookup table' is set ; to a negative value. - Gene Head (N6NN/7) ; ; 07/25/84 Added routine to allow the command line or MAXCL option for ; v91 names per line to function with VCODE. (After several ; threats from my friends.) Also fixed a few small bugs in ; the display format I found after releasing SD-90. The ; state of MAXCL now has no affect on the drive status lines. ; They now follow the value of MNPL or MAXCL automatically. ; Because of this, the status line appears as it did prior to ; SD-90. The NPL equate now sets the default number of names ; per line if no command line option for columns is specified ; unless MAXCL = YES. - John Ray ; ;======================================================================= ; ; NO EQU 0 YES EQU NOT NO ; M80 will not work with 0FFH ; CR EQU 0DH LF EQU 0AH ESC EQU 1BH ; ;*********************************************************************** ; ; USER OPTION SPECIFICATIONS ; ;*********************************************************************** ; DIRCON EQU NO ; Yes for direct console output LOWCCP EQU NO ; Yes only if you are running with BYELOW BDOSPG EQU 0CEH ; Set properly if LOWCCP is yes ; TIMEON EQU NO ; If yes, add your clock reader code at ; start of label time: and store binary ; values in CHOUR and CMIN QUITE EQU NO ; Yes if "Time on System is xx minutes" suppressed CHOUR EQU 043H ; Some BIOS clocks keep time CMIN EQU 044H ; Here anyway LHOUR EQU 050H ; Set by BBS (or BYE) in binary LMIN EQU 051H ; When user logs on STATUS EQU 053H ; And his status MAXMIN EQU 60 ; Minutes for maximum file transfer time ; This should be set to 60. (99 max) ; ; ; ZCPR options ; ZCPR2 EQU NO ; Yes if NZCPR/ZCPR2 (wheel byte enabled) MAXUR EQU NO ; Yes if using MAXUSR in NZCPR/ZCPR2 MAXDR EQU NO ; Yes if using MAXDRV in NZCPR/ZCPR2 MAXCL EQU NO ; Yes if storing MNPL value at MAXC ; WHEEL EQU 3EH ; Set to wheel location if ZCPR2 is yes ; Use 3EH if using NZCPR or ZCMD ; Use 3BH if using unmodified ZCPRHDR file MAXU EQU 3FH ; Set to max user location if MAXUR is YES MAXD EQU 3DH ; Set to max drive location for MAXDR=YES MAXC EQU 3BH ; Set to # of names per line location MXZUSR EQU 15 ; Maximum user # allowed WHLUSR=yes/wheel set WHLUSR EQU YES ; Yes to allow search 0-MXZUSR if wheel set ; WHLA EQU NO ; Yes to disallow A option if wheel zero WHLC EQU NO ; Yes to disallow C option if wheel zero WHLCL EQU NO ; Yes to disallow 4,6 or 8 options if wheel = 0 WHLD EQU NO ; Yes to disallow D option if wheel zero WHLF EQU NO ; Yes to disallow F option if wheel zero WHLL EQU NO ; Yes to disallow L option if wheel zero WHLP EQU NO ; Yes to disallow P option if wheel zero WHLR EQU NO ; Yes to disallow R option if wheel zero WHLS EQU NO ; Yes to disallow S option if wheel zero WHLU EQU NO ; Yes to disallow U option if wheel zero ; ; ; Command line options ; AOPT EQU YES ; Yes to allow searching all user areas COPT EQU NO ; Yes to allow clear screen CLOPT EQU YES ; Yes allows a 40, 64 or 80 column display DOPT EQU YES ; Yes to allow searching all drives on-line FOPT EQU YES ; Yes to allow file output option LOPREV EQU NO ; No to reverse the "L" option and not print LOPT EQU YES ; Yes to allow library file member printing NOPT EQU YES ; Yes to allow disabling page pause option PGPAWS EQU YES ; Yes for pause after each page POPT EQU YES ; Yes to allow printer option ROPT EQU YES ; Yes to allow reset option SOPT EQU YES ; Yes to allow system file option UOPT EQU YES ; Yes to allow user number option VOPT EQU YES ; Yes to allow version number display ; ; ; Console video equates ; REVIDEO EQU NO ; Use reverse video sequences ; If no, the rest of the equates are disabled LEADIN EQU ESC ; Escape lead-in (try a null if not required) INTOREV EQU '4' ; Toggle background (enter your value here) OUTAREV EQU '3' ; Toggle foreground (enter your value here) VECTOR EQU NO ; Yes to display attributes on flashwriter ii VIDEO EQU 0E009H ; Entry to flashwriter video driver prom ; ; ; Hardware equates ; IF NOT (ZCPR2 AND MAXCL) NPL EQU 4 ; # of names per line max values are: ; 2 for 40 x xx, 3 for 64 x 16, & 4 for 80 x 24 ENDIF ; LPS EQU 24 ; # of lines per screen max values are: ; ? for 40 x xx, 16 for 64 x 16, 24 for 80x24 LPS1 EQU 16 ; # of lines per screen if names per line = 3 LPS2 EQU 16 ; # of lines per screen if names per line < 3 FENCEC EQU ':' ; Use 00H for none ; ; ; Miscellaneous equates ; KTHREE EQU YES ; Yes limits file size columns to 3 digits to ; gain an additional print colomn. Allows ; fence to be used with four files per line. PRDI EQU YES ; Yes to print drive # on each line PRUS EQU YES ; Yes to print user # on each line PRLIBD EQU NO ; If YES and PRUS & PRDI are yes then drive and ; user numbers will be displayed on library ; listing lines PRBRDR EQU NO ; Yes to print a quasi-border for library files DORST EQU YES ; Yes to always reset disks when d option active DUOPT EQU YES ; Yes, allow drive/user spec zcpr2 style NODISK EQU YES ; Yes if you do not want to specify disk drive ; When asking for options and using default drv REPERR EQU YES ; Yes to report command line option errors REPUSR EQU YES ; Yes to report user numbers VCODE EQU YES ; Yes if files are to be alphabetized vertically ; ; IF (MAXUR OR MAXDR OR MAXCL) AND NOT ZCPR2 ++++ MAXUR, MAXDR, MAXCL CANNOT BE YES UNLESS ZCPR2 IS YES ENDIF ; ; ; BDOS equates ; RDCHR EQU 1 ; Read char from console WRCHR EQU 2 ; Write char to console PRINTS EQU 9 ; Print string CONST EQU 11 ; Check cons stat RESET EQU 13 ; Reset disk system SELDSK EQU 14 ; Select disk OPEN EQU 15 ; 0ffh=not found CLOSE EQU 16 ; " " SEARCH EQU 17 ; " " NEXT EQU 18 ; " " READ EQU 20 ; Not 0 = EOF WRITE EQU 21 ; Not 0 = disk full MAKE EQU 22 ; 0ffh = directory full CURDSK EQU 25 ; Get currently logged disk name SETDMA EQU 26 ; Set current dma GALLOC EQU 27 ; Get address of allocation vector CURDPB EQU 31 ; Get current disk parameters CURUSR EQU 32 ; Get currently logged user number (2.x only) ; ; BASE EQU 0 ; Default to 0 (or 100h with mac +r option) TPA EQU 100H FCB EQU BASE+5CH BDOS EQU BASE+5 ; ; ORG TPA ; ; ;*********************************************************************** ; ; BEGIN EXECUTABLE PROGRAM CODE * ; ;*********************************************************************** ; ; JMP START ; ; MLEADIN: DB LEADIN ; Leadin char for highlight sequences MINTOREV: DB INTOREV ; Code to enter highlight mode MOUTAREV: DB OUTAREV ; Code to return to normal mode ; IF NOT MAXCL MNPL: DB NPL ; Names per line (# of columns) MLPS: DB LPS ; Lines per screen (between pauses) ENDIF ; NOT MAXCL ; IF MAXCL MNPL: DB 0 MLPS: DB 0 ENDIF ; MAXCL ; FENC: DB FENCEC ; Fence character ; IF COPT DB 'CL SCR CODE->' ; For easy patching via du/ddt CLCHR: DB ESC,'v' ; Enter your clear screen code(s) here DB '$' ; End with a '$' DB 0,0,0,0,0,0 ; Allow further space for custom version ENDIF ; COPT ; ; VERNAME:DB CR,LF,'SD95 - 11/27/84',0 ; ; ; Drive code/user area lookup table ; ; Note that the LODRV-HIDRV table is included here fully configured. ; For your own use, you should change the maximum user areas as appro- ; priate for each drive on your system. Note that there are only 32 ; user areas available under CP/M 2, so the highest legal user area you ; can specify is 31 (range 0-31 = 32 areas). The program will convert ; anything over 31 into mod 31. The default table below is set for the ; usual 16 user areas rather than the full 32 available. ; DB 'MAXUSR TBL>' ; Label to make finding the table easier ; LODRV EQU $ ; Mark beginning of drive/user table ; DB 15 ; Maximum user area for drive a DB 15 ; " " " " " b DB 15 ; " " " " " c DB 15 ; " " " " " d DB 15 ; " " " " " e DB 15 ; " " " " " f DB 15 ; " " " " " g DB 15 ; " " " " " h DB 15 ; " " " " " i DB 15 ; " " " " " j DB 15 ; " " " " " k DB 15 ; " " " " " l DB 15 ; " " " " " m DB 15 ; " " " " " n DB 15 ; " " " " " o DB 15 ; " " " " " p ; HIDRV EQU $ ; Mark end of drive/user table ; START: LXI H,0 DAD SP ; HL=old stack SHLD STACK ; Save it LXI SP,STACK ; Get new stack ; ; ; Initialize reverse video code in message area ; IF REVIDEO LHLD MLEADIN SHLD REVMS1 SHLD REVMS2 SHLD REVMS3 LDA MOUTAREV STA REVMS3+1 ENDIF ; REVIDEO ; ; ; Zero out the entire initialization data area ; LXI H,DATA0 ; Point to beginning of init. data area PUSH H ; Save for non-zero filling later MVI C,DATA1-DATA0 ; Get length of data area XRA A ; Zero accumulator ; ZFILL: MOV M,A INX H DCR C JNZ ZFILL ; ; ; Now copy non-zero initialization data from the template area ; POP H ; Reset hl to data0 LXI D,TMPLT0 ; Set de to beginning of template MVI C,TMPLT1-TMPLT0 ; Get length of template area ; NZFILL: LDAX D ; Get template byte MOV M,A ; Move to data area INX D INX H DCR C JNZ NZFILL MVI C,12 ; Get and save the cp/m version # CALL BDOS MOV A,L STA VERFLG CPI 20H ; Set carry if cp/m 1.4 MVI E,0FFH ; Get current user number if using cp/m 2 MVI C,CURUSR ; Fall through with a=0 if not CNC CPM STA OLDUSR ; Initialize startup user number STA NEWUSR ; And make new user match it ; IF DOPT ; Save extra copy for multi-disk STA BASUSR ; Directories ENDIF ; DOPT ; IF TIMEON CALL TIME ENDIF ; TIMEON ; IF DUOPT ; Drive/user option? LXI H,81H ; Point to command line MOV A,M INX H ORA A JNZ CLOK MOV M,A ; CLOK: LXI D,FCB CALL FNAME MOV A,B CPI 0FFH JZ CLUS STAX D ; CLUS: MOV A,C CPI 0FFH JZ CLNON STA NEWUSR ENDIF ; DUOPT ; IF DOPT AND DUOPT STA BASUSR ENDIF ; DOPT AND DUOPT ; CLNON: MVI C,CURDSK CALL CPM ; Get current disk nr STA OLDDSK ; Save for reset if needed ; IF FOPT INR A STA OUTFCB ; Set directory output file drive ENDIF ; FOPT ; LXI H,FCB MOV A,M ; Get drive name for directory search ORA A ; Any specified? JNZ STRT1A ; Yes skip next routine LDA OLDDSK ; Otherwise, get default disk INR A JMP START2 ; STRT1A: PUSH PSW MVI A,1 STA DFLAG POP PSW ; START2: MOV M,A ; Put the absolute drive code in ; Directory fcb ; ; ; If at least one option is allowed, scan the command line for the ; option field delimiter. The option field delimiter is considered ; valid only if it is preceded by at least 1 space (otherwise, it ; may be part of the directory filename). Any unrecognized options ; or illegal user numbers will be flagged or ignored (see REPERR). ; (We scan the command line buffer rather than the 2nd default FCB ; because all 8 options plus a 2 digit user number won't fit in ; the FCB name field). ; LXI H,80H ; Set command line buffer pointer MOV B,M ; Get length of command line buffer ; ; ; Search for valid command line delimiter. If not found, assume no op- ; tions. ; SCNDOL: INX H DCR B JM CKREST ; Exit if command line buffer empty MOV A,M CPI '$' JNZ SCNDOL DCX H ; '$' found - make sure a space precedes MOV A,M INX H CPI ' ' JNZ SCNDOL ; No space - ignore "$" and search again ; ; ; Valid delimiter found. Scan the rest of the buffer for options. ; Errors past this point will cause an abort if the command line error ; option is enabled. Otherwise, the dud option will be ignored and SD ; will attempt to continue stumbling through the rest of the field. ; XCHG ; Get option field pointer to de ; SCNOPT: INX D ; Bump to next option field character DCR B ; Dock characters left in option field JM CKREST ; If option field exhausted, exit ; SCNAGN: LDAX D ; Get the next option character CPI ' ' ; Do we have a space? JZ SCNOPT ; Ignore it if so ; IF ZCPR2 AND WHLU CPI 'U' ; Disallowing "U" option, treat JZ CLERR ; As error if there.. ENDIF ; ZCPR2 AND WHLU ; LXI H,OTBL-1 ; Get base of option lookup table MVI C,OEND-OTBL+1 ; Get length of option lookup table ; NOMACH: INX H ; Bump to next option table character DCR C ; Are we out of the table? JZ CK4USR ; If so, check for user option ; IF ZCPR2 ; Nzcpr/zcpr2? (wheel byte?) PUSH PSW ; Save accum. LDA WHEEL ; Get wheel byte ORA A ; Check it JZ NOMAC1 ; It's zero, so forget it MOV A,M ; Get the table option CPI '4' ; If 4 then skip lc con JZ UCBP CPI '6' ; If 6 then skip lc con JZ UCBP CPI '8' ; If 8 then skip lc con JZ UCBP ANI 0DFH ; Make sure is upper case ; UCBP: MOV M,A ; Stuff back in table ; NOMAC1: POP PSW ; Restore accum. ENDIF ; ZCPR2 ; CMP M ; Compare our character with option table JNZ NOMACH ; Exit if no match MVI M,0 ; Otherwise, activate the flag CPI 'D' ; All disk search? CZ NOMAC2 ; Yes, start at a always CPI 'A' ; All user search? CZ NOMAC4 ; Yes, start at user no. 0 always JMP SCNOPT ; And go get the next option character ; NOMAC2: PUSH PSW PUSH H LDA DFLAG ORA A JNZ NOMAC3 LXI H,FCB ; Set fcb drive byte to drive a MVI A,1 MOV M,A POP H POP PSW RET ;... ; ; NOMAC3: POP H POP PSW RET ;... ; ; NOMAC4: LDA AFLAG ; Asking for $U3A or $U4A, etc.? ORA A RNZ MVI A,0 ; Always start at user #0 STA NEWUSR STA BASUSR RET ;..... ; ; ; If option character doesn't match the table, see if we have a User ; option. ; CK4USR: IF UOPT ; Check for user number option CPI 'U' JNZ CLERR ; Last option, so bad deal if not it ; UAGN: INX D ; Bump to user number digit DCR B JM CLERR ; Error if nothing left LDAX D ; Get decimal digit CPI ' ' ; Ignore leading spaces JZ UAGN SUI 30H ; Subtract ascii bias JC CLERR ; Error if < 0 CPI 10 JNC CLERR ; Error if > 9 STA NEWUSR ; Save user number, might be only 1 digit ENDIF ; UOPT ; IF DOPT AND UOPT STA BASUSR ; Duplicate it if multi-disk mode ENDIF ; DOPT AND UOPT ; IF UOPT MVI A,1 STA AFLAG ; To allow $u3a, etc. INX D ; Bump to possible 2nd digit of user # DCR B JM CKREST ; No more buffer, exit with user # LDAX D ; Else, check for another digit SUI 30H JC SCNAGN ; If next char not numeric, it is not CPI 10 ; Part of user number so go check for JNC SCNAGN ; Another option MOV L,A ; Save units digit LDA NEWUSR ; Get tens digit ADD A ; Multiply by 10 MOV H,A ADD A ADD A ADD H ADD L ; Combine with units digit STA NEWUSR ; Save the total user number ENDIF ; UOPT ; IF DOPT AND UOPT STA BASUSR ; Duplicate it if multi-disk mode ENDIF ; DOPT AND UOPT ; IF UOPT JMP SCNOPT ; Continue scanning ENDIF ; UOPT ; ; ; If command line error option enabled, playback the command line up ; to the character that we gagged on and exit. If REPERR is not enabled ; then continue as if nothing were amiss to avoid acknowledging that ; some options are available. ; CLERR: IF REPERR XRA A INX D ; Tag end of command line with terminator STAX D CALL CRLF LXI D,ERRMS2 CALL PRINT LXI D,ERRTAG CALL PRINT LXI H,81H ; Playback bad cmd line to error point ; CLELP: MOV A,M ORA A JZ CLEX CALL TYPE INX H JMP CLELP ; CLEX: MVI A,'?' ; Tag line with a '?' field CALL TYPE CALL CRLF ; Space down 1 more line JMP EXIT ; And return to CP/M ENDIF ; REPERR ; IF (NOT REPERR) JMP SCNOPT ; If not reporting errors, ignore the dud ENDIF ; (NOT REPERR) ; ; ; Options input or not specified. If reset option specified, reset ; the disk system now. Its important that the reset be done OUTSIDE ; the multiple drive loop if the file output option is enabled because ; CP/M 1.4 clobbers the DMA buffer on reset. ; CKREST: IF COPT LDA COPFLG ORA A JNZ CLOPN LDA CLCHR CPI 0C3H ; Op-code for JMP JZ CLCAL LXI D,CLCHR ; Get it from down under MVI C,PRINTS ; Print just to console CALL BDOS JMP CLOPN ; CLCAL: LHLD CLCHR+1 SHLD CLCALL+1 ; CLCALL: CALL 0 ; To be safe ENDIF ; COPT ; ;Check for command line option for 40,64, or 80 column & store value ; CLOPN: IF CLOPT ; If CLOPR inabled then LDA CL4FLG ; Load a with 40 col flag ORA A ; Test it JNZ CLOPN1 ; No then skip to 64 col test PUSH PSW ; If so the save a MVI A,2 ; 2 names per line for 40 column ENDIF ; CLOPT ; IF MAXCL AND CLOPT ; If storing value in external location STA MAXC ; Do it ENDIF ; MAXCL AND CLOPT ; IF NOT MAXCL AND CLOPT ; If storing value internal to sd STA MNPL ; Do it ENDIF ; NOT MAXCL AND CLOPT ; IF CLOPT MVI A,LPS2 ; STA MLPS ; POP PSW ; Get it back a ; CLOPN1: LDA CL6FLG ; Load a with 64 col flag ORA A ; Test it JNZ CLOPN2 ; No then skip to 80 col test PUSH PSW ; If so then save a MVI A,3 ; 3 names per line for 64 column ENDIF ; CLOPT ; IF MAXCL AND CLOPT ; If storing value in external location STA MAXC ; Do it ENDIF ; MAXCL AND CLOPT ; IF NOT MAXCL AND CLOPT ; If storing value internal to sd STA MNPL ; Do it ENDIF ; NOT MAXCL AND CLOPT ; IF CLOPT MVI A,LPS1 ; STA MLPS ; POP PSW ; Get back where you belong ; CLOPN2: LDA CL8FLG ; Load a with 80 col flag ORA A ; Test it JNZ ROPTN ; No then exit to test for r option PUSH PSW ; If so then save a MVI A,4 ; 4 names per line for 80 column ENDIF ; CLOPT ; IF MAXCL AND CLOPT ; If storing value in external location STA MAXC ; Do it ENDIF ; MAXCL AND CLOPT ; IF NOT MAXCL AND CLOPT ; If storing value internal to sd STA MNPL ; Do it ENDIF ; NOT MAXCL AND CLOPT ; IF CLOPT MVI A,LPS STA MLPS POP PSW ; Get it back ENDIF ; CLOPT ; ROPTN: IF ROPT LDA ROPFLG ; If reset flag set, reset disk system ORA A ; Before starting to update allocation MVI C,RESET ; Vetors CZ CPM ENDIF ; ROPT ; IF DOPT LDA DOPFLG ; If multi-disk flag set, ORA A ; Need to set error traps CZ SWAPEM ; Swap bdos error vector tables ENDIF ; DOPT ; IF DORST AND DOPT LDA DOPFLG ORA A CZ DSET ; Reset disk system if $d only ENDIF ; DORST AND DOPT ; ; ; Set MNPL and MLPS values if MAXCL ; IF MAXCL LDA MAXC ; Load a reg with value @ maxc STA MNPL ; Punch a into mnpl ; MVI A,LPS ; Load a reg with lps STA MLPS ; Assume 4 names across LDA MAXC ; Get val @ maxc CPI 3 ; 3 columns across? JNZ LPCL1 ; If not then jmp to lpcl1 MVI A,LPS1 ; Load a reg with mnpl for col = 3 STA MLPS ; Punch it into mpls ; LPCL1: LDA MAXC ; Get maxc val again CPI 2 ; 2 columns across? JZ LPCL2 ; If so then jmp to lpcl2 and set mnpl CPI 1 ; Not 2 across, how about 1? JNZ LPSE ; If not then jmp to exit ; LPCL2: MVI A,LPS2 ; It was 1 or 2 so set mnpl with lps2 STA MLPS ; LPSE: ENDIF ; MAXCL ; ; ; Validate drive code and user area numbers from the drive table. ; NOOPT: LXI D,DRUMSG ; Get the drive/user error message PUSH D LDA FCB ; Get directory drive code DCR A ; Normalize to range of 0-31 CPI HIDRV-LODRV ; Compare with maximum drives on-line JNC ERXIT ; Take drive error exit if out of range ; IF MAXDR ; Look for maxd LXI H,MAXD ; Adddress to hl MOV L,M ; Maxd to l INX H ; Add one CMP L ; Check it JNC ERXIT ; Oops if not bigger ENDIF ; MAXDR ; MOV E,A ; Use drive code as index into table MVI D,0 ; IF ZCPR2 AND WHLUSR LDA WHEEL ; Get wheel byte ORA A ; Check it JZ USRCK ; If reset, restrict user MVI A,MXZUSR ; If set, max user = mxzusr JMP USRCK2 ENDIF ; ZCPR2 and WHLUSR ; USRCK: LXI H,LODRV ; Point to base of drive/user table DAD D MOV A,M ; Get the maximum user # for this drive ; IF MAXUR ; Use lomem values if smaller MOV H,A ; Current value of maxusr LDA MAXU ; Alternate value SBI 1 ; Maxusr was really max user + 1 CMP H ; Compare the two JNC USRCK2 ; Jmp if table value smaller or equal STA MAXUSR ; Else replace it ENDIF ; MAXUR ; USRCK2: MOV B,A ; Save the maxuser for later testing (9.2) ANI 1FH ; Make sure its in range 0 - 31 STA MAXUSR ; Save it for later LXI H,NEWUSR ; Point to the directory user area CMP M ; Compare it with the maximum JC ERXIT ; Take error exit if user number illegal POP D ; Destroy error message pointer MOV A,B ; Check to see if this drive (9.2) ORA A ; Has been mapped out (9.2) JM NDSK ; If so then skip this drive (9.2) LXI H,FCB+1 ; Point to name MOV A,M ; Any specified? ; IF NODISK CPI '$' JZ WCD ENDIF ; NODISK ; CPI ' ' JNZ GOTFCB ; ; ; No FCB - make FCB all '?' ; WCD: MVI B,11 ; Fn+ft count ; QLOOP: MVI M,'?' ; Store '?' in fcb INX H DCR B JNZ QLOOP ; GOTFCB: MVI A,'?' ; Force wild extent STA FCB+12 CALL SETSRC ; Set dma for bdos media change check LXI H,FCB ; Point to fcb drive code for directory MOV E,M ; Get the drive code out of the fcb DCR E ; Normalize drive code for select MVI C,SELDSK ; Select the directory drive to retrieve CALL CPM ; The proper allocation vector CALL CKVER ; Check version JC V14 ; Pre-2.x...get params the 1.4 way MVI C,CURDPB ; It is 2.x or mp/m...request dpb CALL BDOS INX H INX H MOV A,M ; Get block shift STA BLKSHF INX H ; Bump to block mask MOV A,M STA BLKMSK ; Get it INX H INX H MOV E,M ; Get max block # INX H MOV D,M XCHG SHLD BLKMAX ; Save it XCHG INX H MOV E,M ; Get directory size INX H MOV D,M XCHG JMP FREE ; Let free save it and setup order table ; V14: LHLD BDOS+1 ; Get params 1.4 style MVI L,3BH ; Point to directory size MOV E,M ; Get it MVI D,0 ; Force high order to 0 PUSH D ; Save for later INX H ; Point to block shift MOV A,M ; Fetch STA BLKSHF ; Save INX H ; Point to block mask MOV A,M ; Fetch it STA BLKMSK ; And save it INX H MOV E,M ; Get max. block no. MVI D,0 XCHG SHLD BLKMAX ; Save it POP H ; Restore directory size JMP FREE20 ; Go figure free space from alloc vector ; ; ; Calculate # of K free on selected drive now so that the FREE figure ; will not reflect either the creation or additions to the SD.DIR file ; (which we would probably erase or move anyway). ; FREE: SHLD DIRMAX ; Save max # of entries in directory LDA VERFLG ; Check version # CPI 30H ; 3.0? JC FREE20 ; Use old method if not LDA FCB ; Get drive # DCR A MOV E,A ; Use new compute free space bdos call MVI C,46 CALL CPM MVI C,3 ; Answer is a 24-bit integer ; FRE3L1: LXI H,BASE+82H ; Answer is in 1st 3 bytes of dma adr MVI B,3 ; Convert it from sectors to k ORA A ; By dividing by 8 ; FRE3L2: MOV A,M RAR MOV M,A DCX H DCR B JNZ FRE3L2 ; Loop for 3 bytes DCR C JNZ FRE3L1 ; Shift 3 times LHLD BASE+80H ; Now get result in k JMP SAVFRE ; Go store it ; FREE20: MVI C,GALLOC ; Get address of allocation vector CALL BDOS XCHG LHLD BLKMAX ; Get its length INX H LXI B,0 ; Init block count to 0 ; GSPBYT: PUSH D ; Save alloc address LDAX D MVI E,8 ; Set to process 8 blocks ; GSPLUP: RAL ; Test bit JC NOTFRE INX B ; NOTFRE: MOV D,A ; Save bits DCX H ; Count down blocks MOV A,L ORA H JZ ENDALC ; Quit if out of blocks MOV A,D ; Restore bits DCR E ; Count down 8 bits JNZ GSPLUP ; Do another bit POP D ; Bump to next byte.. INX D ; Of alloc. vector JMP GSPBYT ; Process it ; ENDALC: POP D ; Clear allocation vector pntr from stack MOV L,C ; Copy blocks to hl MOV H,B LDA BLKSHF ; Get block shift factor SUI 3 ; Convert from sectors to k JZ SAVFRE ; Skip shifts if 1k blocks ret free in hl ; FREKLP: DAD H ; Multiply blocks by k/blk DCR A JNZ FREKLP ; SAVFRE: SHLD FREEBY ; Save the free space for output later ; ; ; Reenter here on subsequent passes while in the all-users mode ; SETTBL: LHLD DIRMAX ; Get directory maximum again INX H ; Directory size is dirmax+1 DAD H ; Double directory size LXI D,ORDER ; To get size of order table DAD D ; Allocate order table SHLD TBLOC ; Name tbl begins where order tbl ends SHLD NEXTT XCHG LHLD BDOS+1 ; Make sure we have room to continue MOV A,E SUB L MOV A,D SBB H JNC OUTMEM ; IF UOPT CALL CKVER ; Set carry if pre-cp/m 2 LDA NEWUSR ; Get user area for directory MOV E,A MVI C,CURUSR ; Get the user function CNC CPM ; And set new user number if cp/m 2 ENDIF ; UOPT ; ; ; Look up the FCB in the directory ; MVI A,'?' LXI H,FCB+12 MOV M,A ; Match all extents INX H MOV M,A ; Match all s1 bytes INX H MOV M,A ; Match all s2 bytes LXI H,0 SHLD COUNT ; Initialize match counter SHLD TOTFIL ; " total file counter SHLD TOTSIZ ; " total size counter CALL SETSRC ; Set dma for directory search MVI C,SEARCH ; Get 'search first' function JMP LOOK ; And go search for 1st match ; ; ; Read more directory entries ; MORDIR: MVI C,NEXT ; Search next ; LOOK: LXI D,FCB CALL CPM ; Read directory entry INR A ; Check for end (0ffh) JZ SPRINT ; If no more, sort & print what we have ; ; ; Point to directory entry ; SOME: DCR A ; Undo prev 'INR A' ANI 3 ; Make modulus 4 ADD A ; Multiply ADD A ; By 32 because ADD A ; Each directory ADD A ; Entry is 32 ADD A ; Bytes long LXI H,BASE+81H ; Point to buffer (skip to FN/ft) ADD L ; Point to entry ADI 9 ; Point to sys byte MOV L,A ; Save (can't carry to H) ; IF SOPT LDA SOPFLG ; Did user request sys files? ORA A JZ SYSFOK ENDIF ; SOPT ; MOV A,M ; Get system byte ORA A ; Check bit 7 JM MORDIR ; Skip that file ; SYSFOK: MOV A,L ; Go back now SUI 10 ; Back to user number (alloc flag) MOV L,A ; Hl points to entry now LDA NEWUSR ; Get current user CMP M JNZ MORDIR ; Ignore if different INX H ; ; ; Move entry to table ; XCHG ; Entry to DE LHLD NEXTT ; Next table entry to HL MVI B,11 ; Entry length (name, type, extent) ; TMOVE: LDAX D ; Get entry character ; IF NOT (VECTOR OR REVIDEO) ANI 7FH ; Remove attributes ENDIF ; NOT (VECTOR OR REVIDEO) ; MOV M,A ; Store in table INX D INX H DCR B ; More? JNZ TMOVE INX D ; DE->> S1 INX D ; DE->> S2 LDAX D ; Get S2 byte, overflow=INT(EXTENTS/32) PUSH H ; Save HL MOV L,A ; Set up 16-bit multiply MVI H,0 MVI B,5 CALL SHLL ; HL is now # of overflow extents DCX D ; DE->> S1 DCX D ; DE->> EXTENT LDAX D ; Get extent ADD L MOV L,A MOV A,H ACI 0 MOV H,A ; HL now has total extents MVI B,7 CALL SHLL ; HL now has total sectors less last ext INX D ; DE->> S1 INX D ; DE->> S2 INX D ; Point to sector count LDAX D ; Get it ADD L MOV L,A MOV A,H ACI 0 MOV H,A ; Hl now has total sectors XTHL ; Do some fancy shuffling XCHG XTHL XCHG MOV M,D INX H MOV M,E POP D ; All back to normal... INX H SHLD NEXTT ; Save updated table address XCHG LHLD COUNT ; Bump the # of matches made INX H SHLD COUNT LXI H,13 ; Size of next entry DAD D XCHG ; Future nextt is in de LHLD BDOS+1 ; Pick up tpa end MOV A,E SUB L ; Compare nextt-tpa end MOV A,D SBB H JC MORDIR ; If tpa end > nextt, loop back for more ; OUTMEM: CALL ERXIT ; Exit if directory too large DB 'Memory',0 ; ; ; Shift HL left by B bits ; SHLL: DAD H DCR B RZ JMP SHLL ; ; ; Sort and print ; SPRINT: IF AOPT OR FOPT OR UOPT CALL SETFOP ; Return to file output DMA & user # ENDIF ; AOPT OR FOPT OR UOPT ; LHLD COUNT ; Get file name count MOV A,L ORA H ; Any found? JZ PRTOTL ; Exit if no files found PUSH H ; Save file count STA SUPSPC ; Enable leading zero suppression ; ; ; Initialize the order table ; LHLD TBLOC ; Get start of name table XCHG ; Into de LXI H,ORDER ; Point to order table LXI B,13 ; Entry length ; BLDORD: MOV M,E ; Save low order address INX H MOV M,D ; Save high order address INX H XCHG ; Table addr to hl DAD B ; Point to next entry XCHG XTHL ; Save tbl addr, fetch loop counter DCX H ; Count down loop MOV A,L ORA H ; More? XTHL ; (restore tbl addr, save counter) JNZ BLDORD ; Yes, go do another one POP H ; Clean loop counter off stack LHLD COUNT ; Get count SHLD SCOUNT ; Save as # to sort DCX H ; Only 1 entry? MOV A,L ORA H JZ DONE ; Yes, so skip sort ; ; ; This sort routine is adapted from SOFTWARE TOOLS by Kernigan and ; Plaugher. ; SORT: LHLD SCOUNT ; Number of entries ; L0: ORA A ; Clear carry MOV A,H ; Gap=gap/2 RAR MOV H,A MOV A,L RAR MOV L,A ORA H ; Is it zero? JZ DONE ; Then none left MOV A,L ; Make gap odd ORI 1 MOV L,A SHLD GAP INX H ; I=gap+1 ; L2: SHLD I XCHG LHLD GAP MOV A,E ; J=i-gap SUB L MOV L,A MOV A,D SBB H MOV H,A ; L3: SHLD J XCHG LHLD GAP ; Jg=j+gap DAD D SHLD JG MVI A,13 ; Compare 13 chars {sfk} CALL COMPARE ; Compare (j) and (jg) JP L5 ; If a(j)<=a(jg) LHLD J XCHG LHLD JG CALL SWAP ; Exchange a(j) and a(jg) LHLD J ; J=j-gap XCHG LHLD GAP MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A JM L5 ; If j>0 goto l3 ORA L ; Check for zero JZ L5 JMP L3 ; L5: LHLD SCOUNT ; For later XCHG LHLD I ; I=i+1 INX H MOV A,E ; If i<=n goto l2 SUB L MOV A,D SBB H JP L2 LHLD GAP JMP L0 ; ; ; Sort is all done - print entries ; DONE: IF FOPT ; If output option wanted, prepare file LDA FOPFLG ORA A JNZ NOOUT ; If file output, fall through, a=0 ; ; ; If all user option enabled, and we're not on the first pass, then the ; output file is already open and positioned, so we can skip the open. ; LXI H,OPNFLG ; Get pointer to output file open flag CMP M ; A=0,set z if opnflg=0 also JNZ NOOUT ; If opnflg not zero, skip open DCR M ; Else, set opnflg for next user # ; ; ; First pass on file append - prepare SD.DIR to receive new or appended ; output. ; LXI D,OUTFCB ; Does output file already exist? MVI C,SEARCH CALL CPM INR A JNZ OPENIT ; If it does, then open it for processing MVI C,MAKE ; Otherwise, create the output file CALL CPM INR A JNZ NOOUT ; Continue if open successful ; ; ; If make or open fails, declare error ; OPNERR: CALL ERXIT DB 'Open',0 ; WRTERR: CALL ERXIT DB 'Write',0 ; ; ; Output file already exists - open it and position to the last record ; of the last extent. ; OPENIT: MVI C,OPEN ; Open 1st extent of output file CALL CPM INR A JZ OPNERR ; Bad deal if 1st won't open ; OPNMOR: LDA OUTFCB+15 CPI 128 JC LSTEXT ; If rc<128, this is last extent LXI H,OUTFCB+12 INR M ; Else, bump to next extent MVI C,OPEN ; And try to open it CALL CPM INR A JNZ OPNMOR ; Continue opening extents til no more DCR M ; Then, reopen preceding extent MVI C,OPEN CALL CPM LDA OUTFCB+15 ; Get rc for the last extent ; ; ; At this point, OUTFCB is opened to the last extent of the file, so ; read in the last record in the last extent. ; LSTEXT: ORA A ; Is this extent empty? JZ NOOUT ; If so, then starting a clean slate DCR A ; Normalize record count STA OUTFCB+32 ; Set record number to read MVI C,READ ; And read last record of file CALL CPM ORA A ; Was read successful? JZ RDOK ; If so, proceed to scan for eof mark ; APERR: CALL ERXIT DB 'Append',0 ; ; ; We now have the last record in the file in our buffer. Scan the last ; record for the EOF mark, indicating where we can start adding data. ; RDOK: LXI H,OUTBUF ; Point to start of output buffer MVI B,128 ; Get length of output buffer ; SCAN: MOV A,M CPI 'Z'-40H ; Have we found end of file? JZ RESCR ; If so, save pointers and reset cr INX H DCR B JNZ SCAN ; Otherwise, look until end of buffer ; ; ; If we find an explicit EOF mark in the last buffer (or an implied EOF ; if the last record is full), move the FCB record and extent pointers ; back to correct for the read operation so that our first write opera- ; tion will effectively replace the last record of the SD.DIR file. ; RESCR: PUSH H ; Save eof buffer pointer PUSH B ; Save eof buffer remaining LXI H,OUTFCB+32 ; Get current record again DCR M ; Dock it JP SAMEXT ; If cr >=0, we're still in same extent LXI H,OUTFCB+12 ; Else, move to previous extent DCR M MVI C,OPEN ; Then, reopen the previous extent CALL CPM INR A JZ APERR ; Append position error if can not reopen LDA OUTFCB+15 ; Else, position to last record of extent DCR A STA OUTFCB+32 ; SAMEXT: POP PSW ; Recall where eof is in buffer STA BUFCNT ; And set buffer counter POP H ; Recall next buffer pointer SHLD BUFPNT ; And set pointer for first addition ENDIF ; FOPT ; ; end of IF FOPT routine ;----------------------------------------------------------------------- ; NOOUT: IF VOPT ; If version option, check if first LDA FIRSTT ; Time through ORA A JNZ NOVOPT ; No, we've been here before MVI A,0FFH ; Virgin, poke it STA FIRSTT LDA VOPFLG ; If version display flag set, print it ORA A JNZ NOVOPT LXI D,VERNAME CALL PRINT CALL CRLF ; NOVOPT: ENDIF ; VOPT ; IF LOPT LHLD COUNT SHLD LCOUNT LXI H,0 SHLD LBTOTL SHLD LMTOTL LXI H,ORDER ; Initialize order table pointer SHLD NEXTL ENDIF ; LOPT ; IF NOT LOPT LXI H,ORDER ; Initialize order table pointer ENDIF ; NOT LOPT ; SHLD NEXTT ; IF VCODE LHLD COUNT ; Code computes end of name CALL MULT13 ; Table (or start of second table XCHG ; Where files will be stored after LHLD TBLOC ; Redundant extents removed.) DAD D SHLD NEWPTR ; Save it twice SHLD XPOINT ; For later ENDIF ; VCODE ; IF NOT VCODE ; JMP NEWLIN ; Start new line and output the files ENDIF ; NOT VCODE ; ; ; Output the directory files we've matched. ; ENTRY: LHLD COUNT DCX H ; Dock file count SHLD COUNT MOV A,H ; Is this the last file? ORA L JZ OKPRNT ; If count=0, last file so skip compare ; ; ; Compare each entry to make sure that it isn't part of a multiple ex- ; tent file. Go only when we have the last extent of the file. ; PUSH B ; Save NPL ; IF NOT VCODE CALL CKABRT ; Check for abort code from keyboard ENDIF ; NOT VCODE ; LHLD NEXTT MVI A,11 CALL COMPR ; Does this entry match next one? POP B ; Recall npl JNZ OKPRNT ; No, print it INX H INX H ; Skip since highest extent last in list SHLD NEXTT JMP ENTRY ; Loop back for next lowest extent ; ; ; Vcode substitution . If VCODE option chosen, OKPRINT moves unique ; filenames and sizes in 'k' to a second table above the first for use ; later. ; OKPRNT: LHLD NEXTT ; Get order table pointer MOV E,M ; Get low order address INX H MOV D,M ; Get high order address INX H SHLD NEXTT ; Save updated table pointer XCHG ; Table entry to hl ; IF VCODE PUSH H ; Save address of byte to be moved LHLD NEWPTR ; Get address in new table to put it in PUSH H ; Save it LXI D,13 ; Update it DAD D SHLD NEWPTR ; Save for later - will be end of table POP H ; Get current move to address XCHG ; Put in de POP H ; Get current move from address back MVI B,11 ; Size of file name, type CALL MOVE ; Move it PUSH D ENDIF ; VCODE ; IF NOT VCODE MVI B,8 ; File name length CALL TYPEIT ; Type filename MVI A,'.' ; Period after fn CALL TYPE MVI B,3 ; Display 3 characters of filetype CALL TYPEIT ENDIF ; NOT VCODE ; CALL DOIT LHLD TOTSIZ ; De now has rounded size in k DAD D ; Add to total used SHLD TOTSIZ LHLD TOTFIL ; Increment file count INX H SHLD TOTFIL XCHG ; Get back file size ; IF VCODE POP D ; Get back where size is to go MOV A,H ; Move size to table two STAX D INX D MOV A,L STAX D ; ; ; One file MOVED - test to see if we have to move another one. ; LHLD COUNT ; Get current file counter and test it MOV A,H ORA L JZ PRTOTL ; If no more files exit to summary output JMP ENTRY ; If more, go get them ENDIF ; VCODE ; ; ; Output the size of the individual file. ; IF NOT VCODE CALL FDECPRT ; Go print it MVI A,'k' ; And follow with k size CALL TYPE ; ; ; One file output - test to see if we have to output another one. ; LHLD COUNT ; Get current file counter and test it MOV A,H ORA L JZ PRTOTL ; If no more files exit to summary output ; ; ; At least one more file to output - can we put it on the current line? ; DCR C PUSH PSW CNZ FENCE ; If room left output the fence character POP PSW JNZ ENTRY ; And go output another file ; ; ; Current line full, start a new one. ; NEWLIN: LDA MNPL MOV C,A ; Reset names per line counter CALL CRLF ; Space down to next line ENDIF ; NOT VCODE ; IF PRDI AND (NOT VCODE) LDA FCB ; Precede new line with drive name ADI 'A'-1 CALL TYPE ENDIF ; PRDI AND (NOT VCODE) ; IF PRDI AND (NOT VCODE) AND (REPUSR AND PRUS) ; If reporting user # and running under CALL CKVER ; Cp/m 2, output the user number too CNC TYPUSR ENDIF ; PRDI AND (NOT VCODE) AND (REPUSR AND PRUS) ; IF PRDI AND (NOT VCODE) MVI A,':' ; Tag header with a colon and a space CALL FPAD ; And exit back to entry ENDIF ; PRDI AND (NOT VCODE) ; IF NOT VCODE JMP ENTRY ; Go back and output another file ENDIF ; NOT VCODE ; ; ; Compute the size of the file/library and update our summary datum. ; This has been changed into a subroutine so that both the file size ; computation and a library size (when printing out library members) ; can be computed in K. ; DOIT: MOV D,M INX H MOV E,M ; Size in de (sectors) LDA BLKMSK PUSH PSW ADD E MOV E,A MOV A,D ACI 0 MOV D,A POP PSW CMA ANA E MOV E,A MVI B,3 ; SHRR: MOV A,D ORA A RAR MOV D,A MOV A,E RAR MOV E,A DCR B JNZ SHRR RET ;..... ; ; ; Print HL in decimal with leading zero suppression ; FDECPRT: IF KTHREE ; Individual file size print XRA A ; Clear leading zero flag STA LZFLG JMP SKTHSD ENDIF ; KTHREE ; DECPRT: XRA A ; Clear leading zero flag STA LZFLG LXI D,-10000 LDA SUPSPC PUSH PSW XRA A STA SUPSPC CALL DIGIT POP PSW STA SUPSPC LXI D,-1000 ; Print 1000's digit CALL DIGIT ; SKTHSD: LXI D,-100 ; Etc. CALL DIGIT LXI D,-10 CALL DIGIT MVI A,'0' ; Get 1's digit ADD L JMP TYPE ; DIGIT: MVI B,'0' ; Start off with ascii 0 ; DIGLP: PUSH H ; Save current remainder DAD D ; Subtract JNC DIGEX ; Quit on overflow POP PSW ; Throw away remainder INR B ; Bump digit JMP DIGLP ; Loop back ; DIGEX: POP H ; Restore pointer MOV A,B CPI '0' ; Zero digit? JNZ DIGNZ ; No, type it LDA LZFLG ; Leading zero? ORA A MVI A,'0' JNZ TYPE ; Print digit LDA SUPSPC ; Get space suppression flag ORA A ; See if printing file totals RZ ; Yes, don't give leading spaces JMP SPACE ; Leading zero...print space ; DIGNZ: STA LZFLG ; Leading zero flag so next zero prints JMP TYPE ; And print digit ;..... ; ; ;======================================================================= ; VCODE subroutines begin here ; ; Multiply contents of HL register by 13 ; IF VCODE MULT13: MOV D,H MOV E,L DAD H DAD D DAD H DAD H DAD D RET ;..... ; ; ; Main subroutine to print out a filename and column delimiter ; SUBA: CALL PFILE1 ; Routine to print a filename RZ ; If at end of line return with zero set CPI 0FFH ; If true past the end of the table CNZ FENCE ; Print the column delimiter if more LHLD JUMPER ; Put the jumper back in de XCHG RET ;..... ; ; PFILE1: MOV A,M ; Let's see what we have CPI 0FEH RNC ANI 7FH ; Strip parity bit PUSH B ; Save the number of columns MVI B,8 ; Print file name and type CALL TYPEIT MVI A,'.' CALL TYPE MVI B,3 CALL TYPEIT PUSH H CALL CKABRT ; Ctl-c from keyboard? POP H MOV D,M ; Get it into INX H MOV E,M XCHG ; Hl CALL FDECPRT ; And print it out MVI A,'k' CALL TYPE POP B ; Get back number of columns LHLD TOTFIL ; Get number of files left DCX H ; Reduce it by one SHLD TOTFIL ; And resave it MOV A,H ORA L ; Down to zero yet? RZ ; Return if no more files DCR C ; Decrement it and RET ENDIF ; VCODE ;..... ; ; end of VCODE routines ;======================================================================= ; ; ; Show total space and files used ; PRTOTL: IF LOPT AND (NOT VCODE) LDA LOPFLG ORA A ENDIF ; LOPT AND (NOT VCODE) ; IF LOPT AND (NOT VCODE) AND LOPREV JZ PRTOT1 ENDIF ; LOPT AND (NOT VCODE) AND LOPREV ; IF LOPT AND (NOT VCODE) AND (NOT LOPREV) JNZ PRTOT1 ENDIF ; LOPT AND (NOT VCODE) AND (NOT LOPREV) ; IF LOPT AND (NOT VCODE) LHLD TOTFIL ; How many files did we match? MOV A,H ORA L CNZ PRTLMEM ; Skip the .lbr check if none found ; PRTOT1 EQU $ ENDIF ; LOPT AND (NOT VCODE) ; XRA A ; Get a zero to... STA SUPSPC ; Suppress leading spaces in totals LHLD TOTFIL ; How many files did we match? MOV A,H ORA L JZ NXTUSR ; Skip the summary if we didn't find any PUSH H ; Save totfil STA FNDFLG ; Set file found flag ; IF VCODE ; Leading crlf for vertical output mode LDA FIRSTT ; If not first time through ORA A CNZ CRLF ENDIF ; VCODE ; LXI D,TOTMS1 ; Print [cr,lf] " Drive " CALL PRINT LDA FCB ADI 'A'-1 CALL TYPE ; Output the drive code ; IF REPUSR CALL CKVER JC NOUSER CALL TYPUSR ; Output the user number ENDIF ; REPUSR ; NOUSER: LXI D,TOTMS6 ; Print " FILES: " CALL PRINT POP H ; Recall totfil CALL DECPRT ; Print number of files matched PUSH PSW ; Just in case LDA MNPL ; Load a with # of names per line CPI 3 ; Is it 3? JZ SKDRV ; Yes then skip cr,lf print CPI 4 ; Is it 4? JZ SKDRV ; Yes then skip cr,lf print LXI D,TOTMS3 ; Split drive status line for 40 < display CALL PRINT ; Do it ; SKDRV: POP PSW ; Put it back LXI D,TOTMS4 ; No cr,lf needed since display > 40 CALL PRINT LHLD TOTSIZ ; Print total k used by files matched CALL DECPRT LXI D,TOTMS5 ; Print "K " CALL PRINT CALL PRTFRE ; Output free space remaining & " FREE." ; IF NOT VCODE CALL CRLF ENDIF ; NOT VCODE ; ; ; Summary line printed, now print the detail files, but first compute ; total lines the printout will take. ; IF VCODE NPRNT: PUSH PSW ; Just in case LDA MNPL ; Load a with # names per line CPI 1 ; Is it 1? JNZ MNC1 ; If not test for 2 LXI D,0-1 ; Minus number of columns LXI B,1-1 ; Number of columns minus 1 ; MNC1: CPI 2 ; Wasn't 1, is it 2? JNZ MNC2 ; If not then test for 3 LXI D,0-2 ; Minus number of columns LXI B,2-1 ; Number of columns minus 1 ; MNC2: CPI 3 ; Wasn't 2, is it 3? JNZ MNC3 ; If not then test for 4 LXI D,0-3 ; Minus number of columns LXI B,3-1 ; Number of columns minus 1 ; MNC3: CPI 4 ; Wasn't 3, is it 4? JNZ MNC4 ; If not then fall through LXI D,0-4 ; Minus number of columns LXI B,4-1 ; Number of columns minus 1 ; MNC4: POP PSW ; Put it back LHLD TOTFIL ; Get total number of files DAD B ; Round up to a full line MVI C,0FFH ; NPRNT1: INR C ; 'c' will end up holding number DAD D ; Of lines to be displayed. JC NPRNT1 MOV A,C STA LINES ; Done. save it for later STA SUPSPC ; Allow spaces in front of file sizes ; ; ; Number of lines times size of an entry equals the number of bytes to ; jump in the second table when outputing files in vertical order. ; MOV L,A ; Put number of lines into hl MVI H,0 CALL MULT13 SHLD JUMPER ; Put it away ; ; ; Fill a sector with FF at the end of table 2 ; LHLD NEWPTR ; Now points to end of table 2 MVI B,128 MVI A,0FFH ; NPRNT2: MOV M,A INX H DCR B JNZ NPRNT2 ; ; ; Increment the number of files for use later in SUBA. This insures ; that a column delimiter will be printed after the last filename, if ; the file appears in other than the last column of the display. ; LXI H,TOTFIL INR M ; ; ; Print out a line of files ; NPRNT3: CALL CRLF ; Start a new line PUSH PSW ; Save it just in case LDA MNPL ; Load a with # of names per line MOV C,A ; Reset number of columns POP PSW ; Put it back ENDIF ; VCODE ; IF PRDI AND VCODE PUSH B LDA FCB ; Show drive letter at beginning of ADI 'A'-1 ; Each line CALL TYPE ENDIF ; PRDI AND VCODE ; IF REPUSR AND PRUS AND PRDI AND VCODE ; Also user number, if allowed CALL CKVER CNC TYPUSR ENDIF ; REPUSR AND PRUS AND PRDI AND VCODE ; IF PRDI AND VCODE MVI A,':' CALL FPAD POP B ENDIF ; PRDI AND VCODE ; ; ; Print first filename ; IF VCODE LHLD XPOINT ; Xpoint points to start of second table CALL SUBA ; At entry. below it is incremented ; For additional lines of printout. JZ NLINE ; Either out of columns or out of files. ; ; ; Print second filename ; LHLD XPOINT DAD D CALL SUBA JZ NLINE ; ; ; NOTE: The following conditionals are used only to save some bytes if ; running with only two or three columns of files in display. ; ; Print third filename, if still room on line ; PUSH PSW ; Just in case LDA MNPL ; Load a with # of names per line CPI 1 ; Is it 1? JZ VCLT2 ; If so then skip name print CPI 2 ; Is it 2? JZ VCLT2 ; If so then skip name print POP PSW ; Put it back where it belongs LHLD XPOINT DAD D DAD D CALL SUBA JZ NLINE JMP VCMT2 ; VCLT2: POP PSW ; Didn't put it back so do it now ; ; ; Print fourth filename ; VCMT2: PUSH PSW ; Just in case it's loaded bang! LDA MNPL ; Load a with # of names per line CPI 4 ; Is it 4? JNZ VCLT3 ; If not then skip fourth name print POP PSW ; Put it back LHLD XPOINT DAD D DAD D DAD D CALL SUBA JMP VCMT3 ; VCLT3: POP PSW ; Didn't put it back yet so do it now ; VCMT3: DS 0 ; ; Wasn't 4 so go NLINE: LHLD XPOINT ; Increment xpoint to next file LXI D,13 DAD D SHLD XPOINT LHLD TOTFIL ; Time to see if we're out of files MOV A,H ORA L JZ DOLIB ; Yes we are LXI H,LINES ; Nope, just need a new line DCR M JNZ NPRNT3 ENDIF ; VCODE ; DOLIB: IF LOPT AND VCODE LDA LOPFLG ORA A ENDIF ; LOPT AND VCODE ; IF LOPREV AND LOPT AND VCODE JZ DOLIB1 ENDIF ; LOPREV AND LOPT AND VCODE ; IF NOT LOPREV AND LOPT AND VCODE JNZ DOLIB1 ENDIF ; NOT LOPREV AND LOPT AND VCODE ; IF LOPT AND VCODE LHLD TOTFIL ; How many files did we match? MOV A,H ORA L CNZ PRTLMEM ; Skip the library check if none found ; DOLIB1: ENDIF ; LOPT AND VCODE ; ; ; Directory for one user area completed. If 'all users' option is se- ; lected, then go do another directory on the next user number until we ; exceed the maximum user # for the selected drive. ; NXTUSR: IF AOPT ; If all users option enabled LDA AOPFLG ; If not all users mode - skip next ORA A JNZ GOCLZ CALL CKVER ; Are we running cp/m 2? JC GOCLZ ; Skip user increment if not CALL CKABRT ; Check for user abort first LDA MAXUSR ; No abort - get maximum user number LXI H,NEWUSR ; Bump directory user number INR M CMP M ; Does next user # exceed maximum? JNC SETTBL ; Continue if more user areas to go ENDIF ; AOPT ; IF DOPT AND AOPT ; If multi-disk option enabled LDA BASUSR ; Reset base user number for the MOV M,A ; Next directory search ENDIF ; DOPT AND AOPT ; ; ; We've finished all of our outputting. Flush the remainder of the out- ; put buffer and close the file before going to exit routine. ; GOCLZ: IF FOPT LXI H,OPNFLG ; Get file open status then reset flag to MOV A,M ; Force reopen on next pass MVI M,0 ORA A JZ NXTDSK ; Skip closing sd.dir if it wasn't opened LXI H,BUFCNT MOV A,M ; Retrieve # of unflushed characters in MVI M,128 ; Buffer, force bufcnt to empty status ORA A ; If bufcnt=128, buffer empty set sign JM CLOSE ; Close sd.dir if buffer is empty JZ FLUSH ; Write last record to sd.dir if full buf LHLD BUFPNT ; Else pad unused buffer with ctl-z ; PUTAGN: MVI M,'Z'-40H INX H DCR A JNZ PUTAGN ; Keep padding until buffer filled out ; FLUSH: LXI D,OUTFCB ; Flush the last output buffer MVI C,WRITE CALL CPM ORA A JNZ WRTERR ; CLOZE: LXI D,OUTFCB ; Close the output file MVI C,CLOSE CALL CPM ENDIF ; FOPT ; ; ; Directory for all user areas completed. If the multi-disk option is ; enabled and selected, reset to the base user area and repeat the di- ; rectory for next drive on-line until we either exceed the drives in ; our LODRV-HIDRV table, or the BDOS shuts us down with a select or bad ; sector error, which will be intercepted back to the EXIT module. ; NXTDSK: LXI H,FNDFLG ; Get file found flag MOV A,M MVI M,0 ; Clear file found flag for next drive ORA A JNZ NDSK ; Continue if at least 1 file found ; IF FOPT ; If file output enabled, temp. diasable LXI H,FOPFLG DCR M PUSH H ENDIF ; FOPT ; LXI D,NOFMS1 ; Print first part of no files message CALL PRINT ; Print it LDA MNPL ; Load a with # of names per line CPI 4 ; Is it 4? JZ LNOFM ; If so then jump to long message print CPI 3 ; Is it 3? JZ LNOFM ; If so then jump to long message print LXI D,NOFSM ; Isn't 3 or 4 so set up short message CALL PRINT ; Print it JMP NNOFM ; Skip long message print IF MAXCL ; If maxcl then print short message anyway LNOFM: LXI D,NOFSM ; Since RCPM's won't want to print the word ENDIF ; MAXCL ; IF NOT MAXCL ; Not MAXCL so long message is defined LNOFM: LXI D,NOFLM ENDIF ; NOT MAXCL ; CALL PRINT ; Print message ; NNOFM: LDA FCB ADI 'A'-1 CALL TYPE ; Output the drive ; IF REPUSR CALL CKVER JC NOUSR1 CALL TYPUSR ; Output the user number ENDIF ; REPUSR ; NOUSR1: LXI D,NOFMS2 ; Print divider CALL PRINT CALL PRTFRE ; Tag with free message ; IF NOT VCODE CALL CRLF ; Need another crlf in horiz. output mode ENDIF ; NOT VCODE IF FOPT ; Restore original file output mode POP H INR M ENDIF ; FOPT ; NDSK: IF DOPT ; If multi-disk option enabled LDA DOPFLG ; If multi-disk not selected - skip next ORA A JNZ NPRT CALL CKABRT ; Check for user abort first MVI A,HIDRV-LODRV ; Get maximum drive code to search LXI H,FCB ; Bump directory fcb drive code INR M CMP M ; Does next disk exceed maximum? JC NPRT ENDIF ; DOPT ; IF MAXDR AND DOPT LDA MAXD ; Look at another value limit INR A CMP M ; Is it lower? JC NPRT ; Bail out if too low JMP NOOPT ; Search next disk ENDIF ; MAXDR AND DOPT ; IF DOPT JNC NOOPT ; Search next disk if maxdr not true ENDIF ; DOPT ; ; ; If no printer, fall through to EXIT ; NPRT: IF POPT ; Check if printer is in use LDA POPFLG ORA A ; Printer active? JNZ EXIT ; No, just exit... MVI C,5 MVI E,CR ; Print a crlf CALL CPM MVI E,LF ; Line feed CALL CPM ENDIF ; POPT ; JMP EXIT ; All done - exit to ccp ;..... ; ; ; Print the user number of the directory in decimal ; TYPUSR: IF REPUSR LDA NEWUSR CPI 10 ; If user no. < 10, skip tens digit JC DUX PUSH B MVI C,'0'-1 ; DUY: INR C ; Get tens digit SUI 10 JNC DUY ; Loop until we've gone too far ADI 10 MOV B,A ; Save units digit MOV A,C ; Print tens digit CALL TYPE MOV A,B ; Get units back POP B ; DUX: ADI '0' JMP TYPE ENDIF ; REPUSR ; ; ; Force new line on video and check for page pause ; CRLF: MVI A,CR ; Send CR CALL TYPE MVI A,LF ; Send LF JMP TYPE ;..... ; ; ; Separate the directory output on a line with a space, the delimiter, ; followed by another space. ; FENCE: CALL SPACE LDA FENC ; Fence character ; FPAD: CALL TYPE ; Print it, fall into space ; SPACE: MVI A,' ' ; Fall through to type ; ; ; Output character in A to console, and optionally to printer and/or the ; output file. ; TYPE: PUSH B PUSH D PUSH H PUSH PSW ; Save the character to output CALL TYPE1 ; Send it to console POP PSW ; Restore the output character ANI 7FH ; Strip parity bit on character ; ; ; Check if reverse video sequence. If so, do not store the ; leadin character or entry/exit characters in SD.DIR ; IF REVIDEO CPI LEADIN ; If lead-in for hilite JZ NOHLT ; Skip file i/o and printer CPI INTOREV ; Reverse start? JZ CKREV CPI OUTAREV ; Reverse end? JNZ TYSKIP ; No, skip ; CKREV: MOV B,A ; Save character LDA HITRAP ; Get previous character CPI LEADIN ; Was it a leadin? MOV A,B ; Restore char JZ NOHLT ; Skip file and printer ; TYSKIP: STA HITRAP ; Save character for hilite trap ENDIF ; REVIDEO ; ; ; Test file output mode and skip to page pause test if not active. ; IF FOPT MOV B,A ; Save stripped character to b LDA FOPFLG ; Is file output active? ORA A JNZ NOWRIT ; Go check for page pause if not ; ; ; File output mode active - make sure we have room in buffer to add the ; next character. If buffer full, write out current record first and ; then start a new record with current character. ; LHLD BUFPNT ; Get current buffer pointer LDA BUFCNT ; Get buffer capacity remaining ORA A JNZ PUTBUF ; Continue if buffer not full CALL SETFOP ; Set the dma address LXI D,OUTFCB ; Otherwise, write the current buffer out MVI C,WRITE CALL CPM ; (note call must save character in b) ORA A JNZ WRTERR ; Write error exit if disk full or r/o LXI H,OUTBUF ; Reset buffer pointer MVI A,128 ; Reset buffer capacity ; PUTBUF: MOV M,B ; Shove character to next buffer position INX H ; Bump buffer pointer SHLD BUFPNT ; And save it DCR A ; Dock count of characters left in buffer STA BUFCNT ; And save it ; NOWRIT: MOV A,B ; Recall stripped character ENDIF ; FOPT ; IF POPT ; If printer option ANI 7FH ; Strip parity bit on character MOV E,A ; Setup list output call MVI C,5 LDA POPFLG ; Test printer flag ORA A CZ CPM ; Print character if flag true MOV A,E ; Recall character ENDIF ; POPT ; IF REVIDEO NOHLT: STA HITRAP ; Save character for hilite trap ENDIF ; REVIDEO ; IF PGPAWS CPI LF ; Do we have a lf? JNZ TYPRET ; Exit if not ENDIF ; PGPAWS ; IF NOPT AND PGPAWS LDA NOPFLG ; Is the page pause function disabled? ORA A JZ TYPRET ; Exit if so ENDIF ; NOPT AND PGPAWS ; IF PGPAWS LDA LINCNT ; Get line count INR A ; Bump it LXI H,MLPS CMP M ; Are we at the end of the screen? JC NOTEOS ; Skip if not LXI D,EOSMSG ; Else, display pause message MVI C,PRINTS ; Without checking for lfs CALL BDOS CALL CINPUT ; Wait for character CPI 'C'-40H ; Want to abort? JZ EXIT1 ; Abort on ctl-c LXI D,MORERA ; Wipe the silly '[more]' out MVI C,PRINTS CALL BDOS XRA A ; Reset line count ; NOTEOS: STA LINCNT ; Save new line count ENDIF ; PBPAWS ; TYPRET: POP H ; Exit from type POP D POP B RET ;..... ; ; ; Output character ; TYPE1: IF VECTOR ORA A ; Set sign flag if ms bit is on JP TYPE2 ; If character is ascii, continue MOV B,A ; Else, get character to b MVI A,5 ; Video driver function for direct output JMP VIDEO ; Display in rev video, exit from video ENDIF ; VECTOR ; TYPE2: IF REVIDEO ORA A JP TYPE99 PUSH PSW LDA MLEADIN ; Send esc char first CALL TYPE99 LDA MINTOREV CALL TYPE99 POP PSW ; Retrieve character ANI 7FH CALL TYPE99 LDA MLEADIN ; Send esc first CALL TYPE99 LDA MOUTAREV ; The out of reverse video character ; TYPE99: ENDIF ; REVIDEO ; IF DIRCON MOV C,A ; Get character into bios entry register LHLD BASE+1 ; Get page base of bios MVI L,12 ; Get entry vector to conout JMP GOHL ; Call conout direct through the bios ENDIF ; DIRCON ; IF NOT DIRCON MOV E,A ; Get character into bdos entry register MVI C,WRCHR JMP BDOS ; Call conout via the bdos ENDIF ; NOT DIRCON ;..... ; ; ; Print a string at HL of length B ; TYPEIT: MOV A,M CALL TYPE INX H DCR B JNZ TYPEIT RET ;..... ; ; ; Print string on the console ; PRINT: LDAX D ; Get the character from the DE string ANI 7FH ; Strip off any parity ORA A ; See if it is a 0 RZ ; Terminates with a 0 character CALL TYPE ; Show the character on the console INX D ; Next string position JMP PRINT ; Go do another ;..... ; ; ; Fetch character from console (without echo) ; CINPUT: LHLD BASE+1 MVI L,9 CALL GOHL ANI 7FH ; Strip off any parity RET ;..... ; ; ; Check for a CTRL-C or CTRL-S entered from the keyboard. Jump to EXIT ; if CTRL-C, pause on CTRL-S. ; CKABRT: LHLD BASE+1 MVI L,6 ; Check status of keyboard CALL GOHL ; Any key pressed? ORA A RZ ; No, return to caller CALL CINPUT ; Get character CPI 'C'-40H ; Ctl-c? JZ EX0 ; If ctl-c then quit CPI 'S'-40H ; Ctl-s? RNZ ; No, return to caller CALL CINPUT ; Yes, wait for another char. CPI 'C'-40H ; Might be ctl-c JZ EX0 ; If ctl-c, else fall thru and continue RET ;..... ; ; ; Routine to do disk reset if D option entered on command line ; DSET: MVI C,RESET CALL CPM RET ;..... ; ; ; Kludge to allow call to address in HL ; GOHL: PCHL ; ; Entry to BDOS saving all extended registers ; CPM: PUSH B PUSH D PUSH H CALL BDOS MOV B,A ; Save return code LDA VERFLG ; Is this 3.0? CPI 30H MOV A,B JC CPM20 ; No, exit normally CPI 0FFH ; It is 3.0 - was return code ff? JNZ CPM20 ; No, exit normally MOV A,H ; 3.0 and a=ff - check for error code ORA A JNZ DSKERR ; Trap out if we got a physical error MOV A,B ; Else continue normally ; CPM20: POP H POP D POP B RET ;..... ; ; ; For file output mode, return to old user area and set DMA for the file ; output buffer. ; SETFOP: IF UOPT OR AOPT CALL CKVER ; Clear carry if CP/M 2 or later LDA OLDUSR ; Get user number at startup MOV E,A MVI C,CURUSR CNC CPM ; Reset the old user number if CP/M 2 ENDIF ; UPOT OR AOPT ; IF FOPT LXI D,OUTBUF ; Move dma from search buffer into the JMP SET2 ; Output buffer ENDIF ; FOPT ; RET ;..... ; ; ; Move disk buffer DMA to default buffer for directory search operations ; and BDOS media change routines (necessary for pre-CP/M 2 systems while ; in file output mode with an active buffer). ; SETSRC: LXI D,BASE+80H ; SET2: MVI C,SETDMA JMP CPM ;..... ; ; ; Print the amount of free space remaining on the selected drive ; PRTFRE: LXI D,TOTMS7 ; Print " ( " CALL PRINT LHLD FREEBY CALL DECPRT ; Print k free LXI D,TOTMS8 ; Print " K FREE) " JMP PRINT ;..... ; ; ; Compare routine for sort ; COMPR: PUSH H ; Save table addr MOV E,M ; Load low order INX H MOV D,M ; Load high order INX H MOV C,M INX H MOV B,M ; ; ; BC, DE now point to entries to be compared ; XCHG MOV E,A ; Get count ; CMPLP: MOV A,M ANI 7FH MOV D,A LDAX B ANI 7FH CMP D INX H INX B JNZ NOTEQL ; Quit on mismatch DCR E ; Or end of count JNZ CMPLP ; NOTEQL: POP H RET ; Cond code tells all ;..... ; ; ; Swap entries in the order table ; SWAP: LXI B,ORDER-2 ; Table base DAD H ; *2 DAD B ; + base XCHG DAD H ; *2 DAD B ; + base MOV C,M LDAX D XCHG MOV M,C STAX D INX H INX D MOV C,M LDAX D XCHG MOV M,C STAX D RET ;..... ; ; ; New compare routine ; COMPARE:LXI B,ORDER-2 DAD H DAD B XCHG DAD H DAD B XCHG MOV C,M INX H MOV B,M XCHG MOV E,M INX H MOV D,M XCHG MOV E,A ; Count ; CMPLPE: MOV A,M ANI 7FH MOV D,A LDAX B ANI 7FH CMP D INX B INX H RNZ DCR E JNZ CMPLPE RET ;..... ; ; ; Error exit ; ERXIT: IF FOPT MVI A,0FFH STA FOPFLG ; Disable file output mode on error ENDIF ; FOPT ; CALL CRLF ; Space down POP D ; Get pointer to message string CALL PRINT ; Print it LXI D,ERRMS1 ; Print " Error" CALL PRINT CALL CRLF ; Space down ; ; ; Exit - all done, restore stack ; EXIT: IF DOPT ; If multi-disk option enabled LDA DOPFLG ; If multi-disk not selected - skip next ORA A JNZ EX0 CALL CKABRT ; Check for user abort first MVI A,HIDRV-LODRV ; Get maximum drive code to search LXI H,FCB ; Bump directory fcb drive code INR M CMP M ; Does next disk exceed maximum? JC EX0 ENDIF ; DOPT ; IF MAXDR AND DOPT LDA MAXD ; Look at another value limit INR A CMP M ; Is it lower? JC EX0 ; Bail out if too low JMP NOOPT ; Search next disk ENDIF ; MAXDR AND DOPT ; IF DOPT JNC NOOPT ; Search next disk if maxdr not true ENDIF ; DOPT ; EX0: IF VCODE CALL CRLF ; Turn up a blank line at end ENDIF ; VCODE MVI C,CONST ; Check console status CALL CPM ORA A ; Character waiting? MVI C,RDCHR CNZ CPM ; Gobble up character ; IF DOPT ; Restore bdos intercept vectors LDA VERFLG ; Or error mode, depending on version CPI 30H JC EXIT0 MVI C,45 MVI E,0 ; Set error mode back to default CALL CPM JMP EXIT1 ; EXIT0: LDA DOPFLG ; If they were swapped ORA A CZ SWAPEM ENDIF ; DOPT ; EXIT1: IF ROPT LDA ROPFLG ; If disk system was reset ORA A LDA OLDDSK ; Get default disk at startup MOV E,A MVI C,SELDSK ; Reselect it CZ CPM ENDIF ; ROPT ; LHLD STACK ; Get old stack pointer SPHL ; Move back to old stack RET ; And return to ccp ;..... ; ; ; Trap BDOS select and sector error vectors to our own intercept routine ; so we can catch a reference to an illegal drive. IF DOPT SWAPEM: LDA VERFLG ; Check version CPI 30H ; See if error mode call is available JC SWAP20 ; If not, use bdos error vectors MVI C,45 MVI E,0FFH ; Use set error mode call CALL CPM ; Set "return code only" mode RET ;..... ; ; SWAP20: LHLD BDOS+1 ; Get pointer to base of bdos ENDIF ; DOPT ; IF DOPT AND LOWCCP LDA BDOSPG ; Get "proper" bdos page MOV E,A ; Save it in "E" MOV A,H ; Get location of bdos CMP E ; Is it where bdos normally is? JZ BDCHK2 ; Yes, but perform 2nd check to be sure INX H ; Swap in the new pointer if running a MOV E,M ; Program below the ccp INX H MOV D,M XCHG ; Now hl points to the proper vector JMP SWAPOK ; Bypass second check ENDIF ; DOPT AND LOWCCP ; IF DOPT BDCHK2: MOV A,L SUI 6 ; Check if pointing directly to bdos JZ SWAPOK ; Continue if true MVI A,'D' ; Undo option request for multi-disk STA DOPFLG ; SWAPOK: MVI L,9 ; Point to sector error vector LXI D,VECTBL ; Exchanging with our own vector table MVI A,4 ; 4 bytes to swap ; SWAPLP: MOV B,M ; Get byte from hl XCHG MOV C,M ; Get byte from de MOV M,B ; Put byte from hl XCHG MOV M,C ; Put byte from de INX H ; Bump exchange pointers INX D DCR A ; Dock counter JNZ SWAPLP ; Continue swapping til done RET ENDIF ; DOPT ;..... ; ; ; Check CP/M version number. Return carry flag set if pre-CP/M 2. If ; CP/M 2 or later or MP/M (any version), return carry clear. ; CKVER: LDA VERFLG CPI 20H RET ;..... ; ; ; Recovery point from intercepted BDOS select and bad sector errors. ; DSKERR: IF DOPT LXI SP,STACK ; Get out of bdos' stack JMP EXIT ; And exit back to ccp ENDIF ; DOPT ; ;----------------------------------------------------------------------- ; start of FNAME routine ; FNAME module ; IF DUOPT MAXDISK EQU 16 ; Maximum number of disks MAXUSER EQU 31 ; Maximum user number ; ; MAIN MODULE ; ON ENTRY, DE PTS TO FCB TO BE FILLED AND HL PTS TO FIRST BYTE OF ; TARGET STRING; FCB IS 36 BYTES LONG ; ON EXIT, B=DISK NUMBER (1 FOR A, ETC) AND C=USER NUMBER ; HL PTS TO TERMINATING CHAR ; A=0 AND Z SET IF ERROR IN DISK OR USER NUMBERS, ; A=0FFH AND NZ ; IF OK ; FNAME: PUSH D ; Save DE MVI A,0FFH ; Set default disk and user STA DISK STA USER MVI B,36 ; Initialize FCB PUSH D ; Save pointer XRA A ; A=0 ; FNINI: STAX D ; Store zero INX D ; Point to next DCR B ; Count down JNZ FNINI POP D ; Get pointer back ; ; ; Scan for colon in string ; PUSH H ; Save pointer ; COLON: MOV A,M ; Scan fora colon or space INX H ; Point to next CPI ':' ; Colon found? JZ COLON1 CPI ',' ; Comma found? JZ GETF1 CPI ' '+1 ; Delimiter? JC GETF1 JMP COLON ; Continue if not end of line ; COLON1: POP H ; Clear stack MOV A,M ; Save possible drive specification CALL CAPS ; Capitalize CPI 'A' ; Digit if less than 'a' JC USERCK ; Process user number SUI 'A' ; Convert to 0-31 CPI MAXDISK ; Within bounds? JC SVDISK ; ERREXIT:XRA A ; Error indicator POP D ; Restore 'de' RET ;... ; ; ; Log in specified disk ; SVDISK: INR A ; Adjust to 1 for 'a' STA DISK ; Save flag INX H ; Point to next character ; ; ; Check for user ; USERCK: MOV A,M ; Get possible user number CPI ':' ; No user number JZ GETFILE CPI '?' ; All user numbers? JNZ USERC1 STA USER ; Set value INX H ; Point to after MOV A,M ; Must be colon CPI ':' JZ GETFILE JMP ERREXIT ; Fatal error if not colon after ? ; USERC1: XRA A ; Zero user number MOV B,A ; 'b' = accumulator for user number ; USRLOOP:MOV A,M ; Get digit INX H ; Point to next CPI ':' ; Done? JZ USRDN SUI '0' ; Convert to binary JC ERREXIT ; User number error? CPI 10 JNC ERREXIT MOV C,A ; Next digit in 'c' MOV A,B ; Old number in 'a' ADD A ; *2 ADD A ; *4 ADD B ; *5 ADD A ; *10 ADD C ; *10+new digit MOV B,A ; Result in 'b' JMP USRLOOP ; USRDN: MOV A,B ; Get nuer user number CPI MAXUSER+1 ; Within range? JNC ERREXIT STA USER ; Save in flag JMP GETFILE ; ; ; Extract file name ; GETF1: POP H ; Get pointer to byte ; GETFILE:MOV A,M ; Pointing to colon? CPI ':' JNZ GFILE1 INX H ; Skip over colon ; GFILE1: MOV A,M ; Get next character CPI ',' ; Delimiter? JZ GFQUES CPI ' '+1 ; Not a delimiter? JNC GFILE2 ; GFQUES: INX D ; Fill with ??? MVI B,11 ; 11 bytes MVI A,'?' ; GFFILL: STAX D ; Put? INX D ; Point to next DCR B ; Count down JNZ GFFILL ; FNDONE: LDA DISK ; Get disk number MOV B,A ; In 'b' LDA USER ; Get user number MOV C,A ; In 'c' POP D ; Restore registers MVI A,0FFH ; No error ORA A ; Set flags RET ;..... ; ; ; Get file name fields ; GFILE2: MVI B,8 ; At most, 8 bytes for filename CALL SCANF ; Scan and fill MVI B,3 ; At most, 3 bytes for filetype MOV A,M ; Get delimiter CPI '.' ; Filename ending in '.'? JNZ GFILE3 INX H ; Point to character after '.' CALL SCANF ; Scan and fill JMP FNDONE ; Done...return to 'args' ;... ; ; GFILE3: CALL SCANF4 ; Fill with spaces JMP FNDONE ;..... ; ; ; Scanner routine ; SCANF: CALL DELCK ; Check for delimiter JZ SCANF4 ; Fill with spaces if found INX D ; Point to next byte in filename CPI '*' ; Question mark fill ? JNZ SCANF1 MVI A,'?' ; Place '?' STAX D JMP SCANF2 ; SCANF1: STAX D ; Place character INX H ; Point to next position ; SCANF2: DCR B ; Count down JNZ SCANF ; Continue loop ; SCANF3: CALL DELCK ; "b" chars or more - skip to delimiter RZ INX H ; Point to next JMP SCANF3 ; SCANF4: INX D ; Point to next filename or filetype MVI A,' ' ; Fill with spaces STAX D DCR B ; Count down JNZ SCANF4 RET ;..... ; ; ; Buffers ; DISK: DB 0 ; Disk number USER: DB 0 ; User number ; ; ; Check character pointed to by 'HL' for a delimiter, return with Zero ; flage set if the character is a delimiter ; DELCK: MOV A,M ; Get the character CALL CAPS ; Capitalize ORA A ; 0=delimiter RZ CPI ' '+1 ; Space character+1 JC DELCK1 ; Space character or less CPI '=' RZ CPI 5FH ; Underscore RZ CPI '.' RZ CPI ':' RZ CPI ';' RZ CPI ',' RZ CPI '<' RZ CPI '>' RET ;... ; ; DELCK1: CMP M ; Compare with self for ok RET ;... ; ; CAPS: CPI 'a' RC CPI 'z'+1 RNC SUI 20H RET ENDIF ; DUOPT ;..... ; end of FNAME routine ; ;======================================================================= ; ; SUBROUTINES to read library file directory ; ;======================================================================= ; start of LOPT routine ; IF LOPT PRTLMEM:LXI H,ORDER ; Initialize order table pointer SHLD NEXTL XRA A STA LNCNT ; ENTRYL: LHLD LCOUNT ; Get fcb count DCX H ; Decrement it SHLD LCOUNT MOV A,H ; Is this the last file? ORA L JZ LBRTST ; If count=0, last file skip compare PUSH B CALL CKABRT ; Check for abort code from keyboard LHLD NEXTL MVI A,11 CALL COMPR ; Does this entry match next one? POP B JNZ LBRTST ; No, print it INX H INX H ; Skip, highest extent comes last in list SHLD NEXTL JMP ENTRYL ; Loop back for next lowest extent ; ; ; Exit Library member printing ; LBEXIT: LHLD LMTOTL MOV A,H ORA L RZ PUSH H ; Save member count XRA A ; Get a zero to... STA SUPSPC ; Suppress leading spaces in totals LXI H,MNPL ; If last line is full, don't turn LDA LNCNT ; Up extra line CMP M CNZ CRLF ; If partial line, extra line needed ENDIF ; LOPT ; IF PRBRDR AND LOPT CALL BDRCH2 LXI D,CONTM1 ; Print "There are " ENDIF ; PRBRDR AND LOPT ; IF NOT PRBRDR AND LOPT LXI D,CONTM2 ENDIF ; NOT PRBRDR AND LOPT ; IF LOPT CALL PRINT POP H ; Get total member count back CALL DECPRT LXI D,MFILES ; Print "Members in " CALL PRINT LHLD LBTOTL CALL DECPRT LXI D,LIBR JMP PRINT ;..... ; ; ; Valid entry obtained - spit it out. ; LBRTST: LHLD NEXTL ; Get order table pointer MOV E,M ; Get low order address INX H MOV D,M ; Get high order address INX H SHLD NEXTL ; Save updated table pointer LXI H,8 DAD D CALL CKLBR JNZ LBRNEX PUSH D LXI H,MNPL LDA LNCNT ; Old code here CMP M CNZ CRLF PUSH PSW ; Just in case LDA MNPL ; Load a with # of names per line CPI 4 ; Is it 4? JZ LBMS ; If so then jump to long lbr message CPI 3 ; Is it 3? JZ LBMS ; If so then jump to long lbr message ENDIF ; LOPT ; IF PRBRDR AND LOPT LXI D,LFMSEP3 ; Set up short "LBR members" message ENDIF ; PRBRDR AND LOPT ; IF NOT PRBRDR AND LOPT LXI D,LFMSEP4 ENDIF ; NOT PRBRDR AND LOPT ; IF LOPT CALL PRINT ; Print it JMP SKLBMS ; Skip past long message ENDIF ; LOPT ; LBMS: IF PRBRDR AND LOPT LXI D,LFMSEP1 ; Set up long "Library directory" message ENDIF ; PRBRDR AND LOPT ; IF NOT PRBRDR AND LOPT LXI D,LFMSEP2 ENDIF ; NOT PRBRDR AND LOPT ; IF LOPT CALL PRINT ; Print it ; SKLBMS: POP PSW ; Put it back LDA FCB ; Get current drive ADI 'A'-1 ; Convert to ascii CALL TYPE ; Print it ENDIF ; LOPT ; IF REPUSR AND LOPT CALL TYPUSR ; Print user # after it ENDIF ; REPUSR AND LOPT ; IF LOPT MVI A,':' ; And colon CALL TYPE POP H PUSH H MVI B,8 ; File name length CALL TYPEIT MVI A,'.' ; Period after fn CALL TYPE MVI B,3 ; Display 3 characters of filetype CALL TYPEIT CALL DOIT ; Compute size of library in k XCHG CALL DECPRT MVI A,'k' CALL TYPE CALL CRLF POP H ; ; ; Saves the library file name into LBRFCB ; LDA FCB LXI D,LBRFCB ; To STAX D INX D MVI B,11 ; Len CALL MOVE ; Do the move XCHG MVI B,25 ; CLMFCB: MVI M,0 INX H DCR B JNZ CLMFCB CALL SETLDMA LXI D,LBRFCB ; Point to file MVI C,OPEN ; Get function CALL CPM ; Open it MVI C,READ LXI D,LBRFCB CALL CPM CALL SETFOP LXI H,LBBUF MOV A,M ORA A JZ CKLDIR ; Check directory present? ; BADLBR: LXI H,NLBRF MVI B,25 CALL TYPEIT ; LMLEXI: CALL LBCLOSE ; ; ; Do next library file ; LBRNEX: LHLD LCOUNT ; Check count MOV A,H ORA L JZ LBEXIT ; No more, all done JMP ENTRYL ; Else, get next .lbr file ; NLBRF: DB '++ Not a LIBRARY file ++',CR,LF ; ; ; Close the library file ; LBCLOSE:LXI D,LBRFCB MVI C,CLOSE CALL CPM RET ;..... ; ; ; Set the Library file DMA adderss ; SETLDMA:CALL CKVER ; Set carry if pre-cp/m 2 LDA NEWUSR ; Get user area for directory MOV E,A MVI C,CURUSR ; Get the user function CNC CPM ; And set new user number if cp/m 2 LXI D,LBBUF MVI C,SETDMA CALL CPM RET ;..... ; ; ; Check to see if there indeed is a LBR file directory and barf if not! ; CKLDIR: MVI B,11 ; Length of file name MVI A,' ' ; Space INX H ; CKDLP: CMP M JNZ BADLBR DCR B INX H JNZ CKDLP ; ; ; The first entry in the LBR directory is indeed blank. Now see if the ; directory size is >0 ; MOV E,M ; File starting location low INX H ; Must be zero here MOV A,M ; File starting location high ORA E ; Must be zero here also JNZ BADLBR INX H MOV E,M ; Get library size low INX H ; Point to library size high MOV D,M ; Get library size high MOV A,D ORA E ; Library must have some size JZ BADLBR DCX D XCHG SHLD SLFILE LHLD LBTOTL INX H SHLD LBTOTL LDA MNPL STA LNCNT ; Reset names per line counter MVI B,3 LXI H,17 DAD D JMP LMTEST ; LFMLOP: LHLD SLFILE ; Get MOV A,L ORA H JZ LMLEXI DCX H SHLD SLFILE CALL SETLDMA MVI C,READ LXI D,LBRFCB CALL CPM CALL SETFOP MVI B,4 ; Get file count per sector LXI H,LBBUF ; Get buffer starting address ; LMTEST: MOV A,M ; Get member open flag ORA A ; Test for open JZ PRMNAM ; LMTESA: LXI D,32 ; Member not open get offset DAD D ; To next and add it in. DCR B ; Is buffer empty ? JNZ LMTEST ; No so test next entry JMP LFMLOP ; Yes get next buffer... ; PRMNAM: PUSH H ; Print member name and size PUSH B CALL CKABRT ; Check for abort code from keyboard LXI H,LNCNT LDA MNPL CMP M JNZ PRMNA1 ENDIF ; LOPT ; IF PRBRDR AND LOPT MVI A,'*' ; Load a reg with border character CALL TYPE ; Print it MVI A,' ' ; CALL TYPE ; Print space between border & text ENDIF ; PRBRDR AND LOPT ; IF PRDI AND PRLIBD AND LOPT LDA LBRFCB ; Precede new line with drive name ADI 'A'-1 CALL TYPE ENDIF ; PRDI AND PRLIBD AND LOPT ; IF (PRDI AND PRLIBD) AND (REPUSR AND PRUS) AND LOPT CALL CKVER ; Under cp/m 2, output the user number CNC TYPUSR ; Too ENDIF ; (PRDI AND PRLIBD) AND (REPUSR AND PRUS) AND LOPT ; IF PRDI AND PRLIBD AND LOPT MVI A,':' ; Tag header with a colon and a space CALL FPAD ; And exit back to entry ENDIF ; PRDI AND PRLIBD AND LOPT ; IF LOPT PRMNA1: POP B POP H PUSH H PUSH B INX H MVI B,8 ; File name length CALL TYPEIT MVI A,'.' ; Period after fn CALL TYPE MVI B,3 ; Display 3 characters of filetype CALL TYPEIT INX H INX H MOV E,M INX H MOV D,M XCHG ; ; ; Output the size of the individual file. ; PUSH D PUSH H PUSH H LHLD LLENLOC PUSH H POP D POP H DAD D SHLD LLENLOC POP H ; ; ; New code added to convert lib members from sectors to 'k' ; ; Upon entry member's size in sectors is in HL ; ; Begin "0K" library bug fix here. The problem was a single byte add ; when a double byte add was required. LXI D,7 ; Round up to nearest 1k DAD D XCHG LXI H,0 MOV A,E ; Put low byte of sector count in a ; RRC RRC RRC ANI 1FH MOV E,A ; And put it back MOV L,D ; Get the high byte if any MVI D,0 ; Clean out the old resting place DAD H ; Multiply it by 32 to convert to DAD H ; Number DAD H ; Of DAD H ; K DAD H ; Bytes DAD D ; And add in the low byte POP D CALL FDECPRT ; Go print it MVI A,'k' ; And follow with size CALL TYPE ; ; ; At least one more file to output - can we put it on the current line? ; LHLD LMTOTL INX H SHLD LMTOTL LDA LNCNT DCR A STA LNCNT PUSH PSW CNZ FENCE ; If room left, output the fence char. POP PSW POP B POP H JNZ LMTESA ; And go output another file ; ; ; Current line full, start a new one. ; LDA MNPL STA LNCNT ; Reset names per line counter CALL CRLF ; Space down to next line JMP LMTESA ;..... ; ; ; Move characters from 'HL' to 'DE' length in 'B' ; MOVE: MOV A,M ; Get a character STAX D ; Store it INX H ; To next 'from' INX D ; To next 'to' DCR B ; More? JNZ MOVE ; Yes, loop RET ; No, return ;..... ; ; ; Test file extent for LBR ; CKLBR: PUSH H PUSH D PUSH B XCHG LXI H,LBRTYP MVI C,3 ; CKLBL: LDAX D ANI 7FH CMP M JNZ CKLBX INX H INX D DCR C JNZ CKLBL ; CKLBX: POP B POP D POP H RET ;..... ; ; BDRCH2: MVI A,'*' CALL TYPE POP PSW ; BDRCH1: MVI A,'*' CALL TYPE POP PSW RET ;..... ; ; LFMSEP1:DB CR,LF,'** Library Directory for ',0 LFMSEP2:DB CR,LF,'Library Directory for ',0 LFMSEP3:DB CR,LF,'** Lbr Members in ',0 LFMSEP4:DB CR,LF,'Lbr Members in ',0 LBRTYP: DB 'LBR' ENDIF ; LOPT (from waaaaay back in pgm) ; ; end of LOPT routine ;*********************************************************************** ; ; TIME: CALCULATE USER'S ELAPSED TIME ; ;*********************************************************************** ; ; Calculate time on system and inform user. Log him off if =>MAXMIN ; unless STATUS is non-zero. ; IF TIMEON TIME: NOP ; The sysop must add the code here neces- NOP ; Sary to read his clock and store NOP ; binary values of current hours (0-23) NOP ; in CHOUR and minutes (0-59) in CMIN LXI H,LHOUR ; Point to log-on hour LDA CHOUR ; Current hour CMP M ; Equal? JNZ TIME1 ; No LDA LMIN ; Log on minutes MOV D,A LDA CMIN ; Current minutes SUB D STA TON ; Store total time on JMP TIME2 ; TIME1: LDA LMIN ; Log on min MOV D,A MVI A,03CH ; 60 min into a SUB D LXI H,CMIN ; Point at current min ADD M ; Add current minutes STA TON ; TIME2: LDA STATUS ; Look at user status ORA A ; Special user? JNZ TIME3 ; Yes, skip log off check XRA A ; Clear status bits LDA TON SUI MAXMIN ; Subtract max time allowed JC TIME3 ; Still time left LDA WHEEL CPI 0FFH ; Skip timup if wheel byte is set RZ CALL TIMEUP ; Time is up, inform user MVI A,0CDH ; Alter jump vector STA 0 ; At zero JMP 0 ; And log him off ; TIME3: LXI H,MSG1+015H ; Point at message insert bytes LDA TON ; Convert to ascii MVI B,0FFH ; TIME4: INR B SUI 0AH ; Subtract 10 JNC TIME4 ; Until done ADI 0AH ORI '0' ; Make ASCII MOV M,A DCX H MVI A,'0' ADD B MOV M,A ENDIF ; TIMEON ; IF TIMEON AND QUITE RET ENDIF ; TIMEON AND QUITE ; IF TIMEON LXI D,MSG1 CALL PRINT RET ;..... ; ; MSG1: DB CR,LF,'Time on system is 00 minutes',CR,LF,' ',0 ; TIMEUP: LXI D,MSG2 CALL PRINT RET ;..... ; ; MSG2: DB CR,LF,CR,LF DB 'Your time is up - wait 24 hours ' DB 'to call back',CR,LF,' ',0 ; TON: DB 0 ENDIF ; TIMEON ; ; end of TIMEON routine ;----------------------------------------------------------------------- ; ; end of program code ; ;----------------------------------------------------------------------- ; ; Initialized data area ; DRUMSG: DB 'Drive/User',0 ; IF PGPAWS EOSMSG: DB ' [more]',CR,'$' MORERA: DB ' ',CR,'$' ENDIF ; PGPAWS ; ERRMS1: DB ' ' ERRMS2: DB 'Error',0 ; IF REPERR ERRTAG: DB ' ->',0 ENDIF ; REPERR ; NOFMS1: DB CR,LF,CR,LF ; IF REVIDEO REVMS1: DB LEADIN,INTOREV ENDIF ; REVIDEO ; DB ' ',0 ; NOFLM: DB '>> No detectable file(s) on ',0 NOFSM: DB '>> No file(s) on ',0 NOFMS2: DB ': ',0 TOTMS1: DB CR,LF ; IF REVIDEO REVMS2: DB LEADIN,INTOREV ENDIF ; Revideo ; DB ' Drive ',0 ; TOTMS3: DB ' ',CR,LF,0 TOTMS4: DB ' space used: ',0 TOTMS5: DB 'k ',0 TOTMS6: DB ': files: ',0 TOTMS7: DB '(',0 TOTMS8: DB 'k free)' ; IF REVIDEO REVMS3: DB LEADIN,OUTAREV ENDIF ; REVIDEO ; DB ' ',0 ; Eliminate double LF ; IF LOPT CONTM1: DB CR,LF,'*** There are ',0 CONTM2: DB CR,LF,'There are ',0 MFILES: DB ' member files in ',0 LIBR: DB ' library(s)',0 ENDIF ; LOPT ; ; ;======================================================================= ; ; Permanently initialized data area ; ;======================================================================= IF DOPT VECTBL: DW DSKERR ; Bdos sector error intercept vector DW DSKERR ; Bdos select error intercept vector ENDIF ; DOPT ; ; ;======================================================================= ; ; Template of initialization data for when SD is run or rerun ; ; The values here are copied by initialization code into ; the area in which they are actually used by the program ; ;======================================================================= ; TMPLT0 EQU $ ; Mark start of initialization template ; ; Option field lookup table. Note that you can force any of these op- ; tions as a DEFAULT by changing the letter for the option into a zero ; (assuming that its enabling equate is true). Each option that you ; hard-wire in this manner will no longer be recognized as a command ; line OPTION, and if you redundantly key it in, SD will flag it as un- ; recognized. ; OTBL0: IF NOT WHLA AND AOPT DB 'A' ; Axl users option flag ENDIF ; NOT WHLA AND AOPT ; IF WHLA AND AOPT DB 'a' ENDIF ; WHLA AND AOPT ; IF NOT WHLC AND COPT DB 'C' ; Clear screen option flag ENDIF ; NOT WHLC AND COPT ; IF WHLC AND COPT DB 'c' ENDIF ; WHLC AND COPT ; IF NOT WHLCL AND CLOPT DB '4' ENDIF ; NOT WHLCL AND CLOPT ; IF WHLCL AND CLOPT DB '4'+40H ENDIF ; WHLCL AND CLOPT ; IF NOT WHLCL AND CLOPT DB '6' ENDIF ; NOT WHLCL AND CLOPT ; IF WHLCL AND CLOPT DB '6'+40H ENDIF ; WHLCL AND CLOPT ; IF NOT WHLCL AND CLOPT DB '8' ENDIF ; NOT WHLCL AND CLOPT ; IF WHLCL AND CLOPT DB '8'+40H ENDIF ; WHLCL AND CLOPT ; IF NOT WHLD AND DOPT DB 'D' ; Multi-disk option flag ENDIF ; NOT WHLD AND DOPT ; IF WHLD AND DOPT DB 'd' ENDIF ; WHLD AND DOPT ; IF NOT WHLF AND FOPT DB 'F' ; Sd.dir file output option ENDIF ; NOT WHLF AND FOPT ; IF WHLF AND FOPT DB 'f' ENDIF ; WHLF AND FOPT ; IF NOT WHLL AND LOPT DB 'L' ; Display library members flag ENDIF ; NOT WHLL AND LOPT ; IF WHLL AND LOPT DB 'l' ENDIF ; WHLL AND LOPT ; IF NOPT AND PGPAWS ; No page-pause option flag DB 'N' ENDIF ; NOPT AND PGPAWS ; IF NOT WHLP AND POPT DB 'P' ; Printer output option ENDIF ; NOT WHLP AND POPT ; IF WHLP AND POPT DB 'p' ENDIF ; WHLP AND POPT ; IF NOT WHLR AND ROPT DB 'R' ; If not auto reset and not wheel restr. ENDIF ; NOT WHLF AND ROPT ; IF WHLR AND ROPT DB 'r' ; If not auto reset and is wheel restr. ENDIF ; WHLR AND ROPT ; IF NOT WHLS AND SOPT DB 'S' ENDIF ; NOT WHLS AND SOPT ; IF WHLS AND SOPT DB 's' ENDIF ; WHLS AND SOPT ; IF VOPT ; Display version number flag DB 'V' OEND0: ENDIF ; VOPT ; ; ; End of option lookup table IF FOPT BUFPN0: DW OUTBUF ; Ptr to next location in output buffer BUFCN0: DB 128 ; Number of bytes left in output buffer OUTFC0: DB 0,'SD DIR' ENDIF ; FOPT TMPLT1 EQU $ ; Mark end of initialization data template ; THIS IS THE END OF THE CODE THAT MUST BE STORED ON DISK IN THE COM FILE ; ;======================================================================= ; ; data area reinitialized by code when SD is run or rerun ; ;======================================================================= DATA0 EQU $ ; Mark beginning of area to initialize OTBL EQU $ ; Mark start of option table ; IF AOPT AOPFLG: DS 1 ENDIF ; AOPT ; IF COPT COPFLG: DS 1 ENDIF ; COPT ; IF CLOPT CL4FLG: DS 1 CL6FLG: DS 1 CL8FLG: DS 1 ENDIF ; CLOPT ; IF DOPT DOPFLG: DS 1 ENDIF ; DOPT ; IF FOPT FOPFLG: DS 1 ENDIF ; FOPT ; IF LOPT LOPFLG: DS 1 ENDIF ; LOPT ; IF NOPT AND PGPAWS ; No page-pause option flag NOPFLG: DS 1 ENDIF ; NOPT AND PGPAWS ; IF POPT POPFLG: DS 1 ENDIF ; POPR ; IF ROPT ROPFLG: DS 1 ENDIF ; AUTOR OR ROPT ; IF SOPT SOPFLG: DS 1 ENDIF ; SOPT ; IF VOPT ; Display version number flag VOPFLG: DS 1 ENDIF ; VOPT ; OEND EQU $ ; Mark end of option table ; ; ; End of option lookup table IF FOPT BUFPNT: DS 2 ; Ptr to next location in output buffer BUFCNT: DS 1 ; Number of bytes left in output buffer OUTFCB: DS 1 + 8 + 3 ; Space for user #, filename, and filetype ENDIF ; FOPT ;----------------------------------------------------------------------- ; ; BEGINNING OF AREA REINITIALIZED TO ZERO EACH TIME SD IS RUN ; IF FOPT DS 21 ; Rest of sd.dir fcb OPNFLG: DS 1 ; File open flag for all user file output ENDIF ; FOPT ; AFLAG: DS 1 ; If a option check for prior u option DFLAG: DS 1 ; If d option check for prior drive spec. FNDFLG: DS 1 ; Flag whether any files matched ; IF PGPAWS LINCNT: DS 1 ; Count of lines printed on screen ENDIF ; PGPAWS ; ; IF LOPT LLENLOC:DS 2 ; Running total of .lbr length LMTOTL: DS 2 LBTOTL: DS 2 LNCNT: DS 1 LCOUNT: DS 2 NEXTL: DS 2 SLFILE: DS 2 ENDIF ; LOPT ; IF VCODE LINES: DS 1 ; Number of lines to be printed out. ENDIF ; VCODE ; IF VOPT FIRSTT: DS 1 ; First time flag for version # display ENDIF ; VOPT DATA1 EQU $ ; Mark end of area to initialize ; ;======================================================================= ; ; Uninitialized data area ; ;======================================================================= IF FOPT OUTBUF: DS 128 ; Output file buffer ENDIF ; VOPT ; BASUSR: DS 1 ; Dupe of original dir. user # to search BLKMAX: DS 2 ; Highest block # on drive BLKMSK: DS 1 ; Sec/blk - 1 BLKSHF: DS 1 ; # shifts to mult by sec/blk COUNT: DS 2 ; Entry count DIRMAX: DS 2 ; Highest file # in directory FREEBY: DS 2 ; Contains number of k left on dir. drive GAP: DS 2 ; Sort routine storage HITRAP: DS 1 ; Highlit trap (previously typed char) I: DS 2 ; Sort routine storage J: DS 2 ; Sort routine storage JG: DS 2 ; Sort routine storage LZFLG: DS 1 ; 0 when printing leading zeros MAXUSR: DS 1 ; Max user # for drive from lookup table NEWUSR: DS 1 ; Contains user # selected by "$U" option NEXTT: DS 2 ; Next table entry OLDDSK: DS 1 ; Holder for currently logged-in drive OLDUSR: DS 1 ; Contains user number upon invocation SCOUNT: DS 2 ; # to sort SUPSPC: DS 1 ; Leading space flag for decimal routine TBLOC: DS 2 ; Pointer to start of name table TEMP: DS 2 ; Save dir entry TOTFIL: DS 2 ; Total number of files TOTSIZ: DS 2 ; Total size of all files VERFLG: DS 1 ; Cx/m version number (0=pre-cp/m 2) ; IF LOPT LBRFCB: DS 36 LBBUF: DS 80H ENDIF ; LOPT ; IF VCODE NEWPTR: DS 2 ; Pointer to start of second table XPOINT: DS 2 ; Ditto JUMPER: DS 2 ; Amount to increment by in second table ; To keep vertical file alignment ENDIF ; VCODE ; DS 60 ; Stack area STACK: DS 2 ; Save old stack pointer here ; ORDER EQU $ ; Order table starts here ; ; END