home *** CD-ROM | disk | FTP | other *** search
- * Date 08/10/83 18:22 HM VAN TASSELL REVISION-B
-
- ; Made several changes to make SD more useful and friendly to me and maybe
- ; to others. Added HELP if // is filename or if a bad option specified.
- ; Changed so will always start with drive A: if D option choosen and no
- ; drive is specified in command line, user = 0 if A option choosen and no
- ; user was specified as an option,-see the new STARTZ, ZUSR & ZDRV.
- ; Added STSKIP & SKIPTO to skip over drives that dont exist but are in
- ; drive table. Useful for some of us that use M: to specify memory drive.
- ; To more closely conform to Digial Research notation used in CP/M PLUS,
- ; changed from "$" to "[]" to indicate options and eliminated need for a
- ; leading space and allow the use of either space or comma between options.
- ; Added code for 3 byte INTO/OUTA reverse video so can use esc,G,x code to
- ; indicate file attributes. Since directorys can be long, added a message
- ; at start of each section, see STMSG equate. Added option 'T' which is
- ; a sort by filetype and then by filename, TOPREV reverses 'T' option.
-
- ; NOTE: Edit help message at start of code to match your choice of options
-
- * SD.ASM Ver 4.8A
- * (Rev 14 MAY 83)
- *
- * SUPER DIRECTORY PROGRAM
- * by Bruce R. Ratoff
- *
- * Based on 'DIRS' by Keith Petersen, W8SDZ
- *
- * Displays the directory of a CP/M disk, sorted alphabetically,
- * with the file size in K, rounded to the nearest CP/M block size.
- *
- * This latest variation on a common theme will automatically adjust
- * itself for any block size and directory length under CP/M 1.4 or 2.x
- * or MP/M (any version). 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 optionally resetting the disk
- * system before execution begins; (4) directing output to a disk file
- * and appending to it on subsequent runs; (5) summary line output giving
- * drive and user information, # of files matched and how much space they
- * consume, and the amount of free space remaining on the disk; (6) displaying
- * or suppressing CP/M 2 "system" files; (7) accepting ambiguous filenames
- * with or without a drive name; and (8) printer output.
-
- * See SD.DOC for detailed instructions on configuring and running SD.ASM
- *
- * ==========================================================================
- *
- * NOTE: If you add improvements or otherwise update
- * this program, please modem a copy of the new file
- * to "TECHNICAL CBBS" in Dearborn, Michigan - phone
- * 313-846-6127 (110, 300, 450 or 600 baud). Use the
- * filename SD-NEW.NEW. (KBP)
- *
- * P.S. As author of the original version as well as
- * this latest update (4.5), I would also appreciate
- * hearing your comments/changes. Please leave me a
- * note on Cranford, NJ RIBBS - 201-272-1874. (BRR)
- *
- * ==========================================================================
- * Fixes/updates (in reverse order to minimize reading time):
- *
- * 05/14/83 Put back in 0AH,0DH in TOTMS6 (removed in SD-47) for an extra
- * line after 'free space' to make screen. Corrected sense of LOPREV
- * EQU to reverse 'L' option. Bill Wood
- *
- * 05/10/83 With SD-48 comes a major revision to this very popular SD
- * program. This revision adds the optional capability to search
- * and print the members of LIBRARY (.LBR) files formed by the LU
- * library utility that is getting to be so popular.
- *
- * See LOPT & LOPREV
- *
- * The option has been given the "L" tag and at assembly time you
- * can set LOPREV to TRUE to print all library members found,
- * unless the "L" option is given, then no members will be printed.
- * If you set LOPREV to FALSE then the library members will only
- * be printed when the "L" option is given on the command line.
- *
- * The member file sizes are shown in 128 byte sectors to allow a
- * slightly different appearance between the normal DIR and library
- * DIR printouts. This sector size conforms to the -s command that
- * is now found in the LDIR211 program.
- *
- * I won't go into all of the places that parts of the code came
- * from or who wrote it as that would be highly redundant. I do
- * give thanks to them in any case, for some great ideas.
- *
- * G.B.Shaffstall Lakewood RCP/M
- *
- * 12Feb83 Added an improved version of Dave Roznar's and Bob Kohler's
- * "BYELOW" modifications, which will allow SD to work in a system
- * where BYE is running under the CCP (the "D" option didn't work).
- * >> 20Jan83 Added fix to SWAPEM routine to allow use with BYELOW
- * >> when using BYE. Added BDOSPAG equate at beginning of code.
- * -- Note: If you are going to use the LOWCCP option, you cannot
- * -- MOVCPM without re-modifying SD. (but you can just change
- * -- The one byte at the beginning of the program).
- * -- BUT, SD will operate properly if you only use one size of
- * -- CP/M system (DOPT will work when BYE runs or if it isn't
- * -- runnint) <<sigh, if you understand what I just said, congrats
- *
- * ALSO: Changed code so that the newline feature of 21Aug82 will only
- * be sent to the printer-- and it will only be sent when the program
- * is done, NOT, after every free space message. (4.7 - Paul Traina)
- *
- * 15Nov82 Added Set Error Mode call and new free space calculation method
- * for compatibility with CP/M 3.0 (4.6 - B. Ratoff)
- *
- * 21Aug82 Added newline after free space message since some buffered
- * hardcopy devices won't print an incomplete line. Made hilite
- * sequences, column delimiter, names per line and lines per screen
- * patchable to avoid reassembly. Added $V option to display version
- * number string. (4.5 - B. Ratoff)
- *
- * 28feb82 Ignore attribute bits in compare subrs, equate CRT leadin char.,
- * add Hazeltine 1500 equates. (4.4 - W.Earnest)
- *
- * 06feb82 Modified use of BDOS error vector table for DOPT. The previous
- * arrangement would change BDOS without checking whether it really was
- * pointing to the right location. In addition, the trap vectors are
- * swapped only when called for.
- * Modified RMAC/MAC options: ASEG statement added for using RMAC
- * without the requirement for external defs.
- * Also added dim for ADM-31 (works same as reverse video), and cleared
- * high^order bit when being sent to printer. (4.3 - R.B.STRAND)
- *
- * 11-1-81 Eliminated LF after "More" message. Allows yet another
- * line per more.
- *
- * 10-25-81 Incorporated 10/21 updates renamed version. -CAF
- * Also made display more compact by eliminating unneeded lf's
- * This allows two more lines per "more"
- *
- * 10-21-81 Added conditionals for REVIDEO for reverse video
- * display of tags ($SYS, etc.) -CAF
- *
- * 10/20/81 minor update to correct (1) malfunction when appending to an
- * existing sd.dir file with the directory from an empty disk;
- * (2) clobbering data area while closing sd.dir when last record
- * appended is completely full; and (3) equate interaction error
- * between fopt and aopt. (ver 4.1 - david boruff)
- *
- * 10/19/81 MAJOR UPDATE adding new command line options for
- * (1) disk system reset; (2) page pause override;
- * (3) displaying directory of a specified user area;
- * (4) searching ranges of drives or user areas; and
- * (5) printer output. Corrected previous name error
- * to avoid confusion with Keith Petersen's old SDIR.
- *
- * Corrected obscure file output bug which occurred only
- * when appending on even record or extent boundaries.
- * Reset equate of Ver 2.3 deleted as redundant now that
- * command line reset available as an option or default.
- * Shortened page-pause message to free-up program space.
- * Optimized much of the existing code to compact the load
- * module and gain space for new features. Option scanner
- * rewritten to permit free form input and to simplify any
- * future expansions of the command line option set.
- * Reclaimed uninitialized data memory to further compact
- * load module size. By popular demand, restored code to
- * display free space remaining when no files are found.
- * Added tables to allow restricting directory searches
- * to a range of drives and/or user areas. BDOS intercept
- * added to facilitate searching drives that may not be
- * on-line (more generally applicable than the FILEFIND
- * method if your BIOS returns control to BDOS on fatal disk
- * errors). General cosmetic overhaul including tabular
- * realignment and additional comments to enhance readability
- * at the cost of a "few" extra bytes. (Ver 4.0 - David Boruff)
- *
- * 09/23/81 MINOR UPDATE to add equate to allow suppressing user
- * numbers in the directory output. (Ver 3.1 - David Boruff)
- *
- * 09/18/81 MAJOR UPDATE implementing new file output option allowing
- * directory output to be appended to a disk file. Changed
- * option specification format to require a dollar sign
- * preceding the option specifiers. Changed header format
- * to display drive & user #'s for each line less than 4
- * files wide. Changed code for no files found to display
- * error message only. (Ver 3.0 - David Boruff)
- *
- * 09/12/81 MINOR UPDATE deleting WIDE and NOT WIDE code in deference
- * to equating screen size. Added Flashwriter II equate to
- * allow display of file attributes in reverse video. Changed
- * tag-line to display drive and user #. Added equate to allow
- * disk system reset on startup. Other cosmetic changes made
- * to open up display format and give output a less cramped
- * appearance. (Ver 2.3 - David Boruff)
- *
- * 06/05/81 Added PGPAWZ (page pause) conditional for remote
- * CP/M systems where pausing may not be wanted.
- * Setting PGPAWZ and REPSIZ to FALSE will result in
- * a display like DIR, but sorted and with the stat
- * of space remaining. Rearranged equates to allow
- * 15 lines per page when narrow display is chosen.
- * (Ver 2.2 - KBP)
- *
- * 06/01/81 Added version number, restored CTL-C break, added
- * CTL-C test to allow break at page pause, added
- * routine to gobble up any waiting console character
- * at EXIT, added conditional assembly to allow no
- * report of file sizes, added conditional assembly
- * for direct console I/O for remote CP/M systems
- * where phone line noise would garbage display. (KBP)
- *
- * 05/06/81 Corrected double printing of drive name in CALLB.
- * Error only occurred with narrow display when file
- * wasn't found. (Tim Nicholas)
- *
- * 02/06/81 Changed sort to have odd gap (KBP say its faster)
- *
- * 01/06/81 Changed sort from bubble sort to shell sort
- * for faster speed.
- *
- * 12/24/80 Changed BIOS conout to BDOS conout to allow
- * printing of directory with CTL-P. Also added
- * print of remaining space even if file not
- * found. (Steve Nossen)
- *
- * 12/15/80 Added space suppression when printing file
- * totals. (KBP)
- *
- * 12/14/80 Added logic to print space remaining on disk.
- * Changed ^C test so that interrupting character is
- * not echoed (makes remote use cleaner). (BRR)
- *
- * 12/02/80 Fixed bug in print routine which compared last file
- * against garbage before printing. (BRR)
- *
- * 11/29/80 Changed to allow printing 4 file names. (Ben Bronson
- * and Keith Petersen)
- *
- * 11/22/80 Fixed bug in handling >256 files. Changed abort test
- * in print routine to only abort on control-c. (BRR)
- *
- * ==========================================================================
- *
- * Set 'RMAC' TRUE to assemble with relocating assembler
- * (requires link with PAGE 0 equates in separate file).
- *
- * ==========================================================================
-
- FALSE EQU 0
- TRUE EQU NOT FALSE
-
- ******************************
- * *
- * USER OPTION SPECIFICATIONS *
- * *
- ******************************
-
- ALTCPM EQU FALSE ;True for H8 or TRS-80
- DIRCON EQU FALSE ;True for direct console output
- LOWCCP EQU FALSE ;True only if you are running with BYELOW
- BDOSPG EQU 0CCh ;Set properly if LOWCCP is true
- OPTION EQU TRUE ;True if allowing ANY command line options
- AOPT EQU TRUE ;True to allow searching all user areas
- DOPT EQU TRUE ;True to allow searching all drives on-line
- STARTZ EQU TRUE ;True to start with zero dr & user in none spec
- FOPT EQU TRUE ;True to allow file output option
- NOPT EQU TRUE ;True to allow disabling page pause option
- PGPAWZ EQU TRUE ;True for pause after each page
- POPT EQU TRUE ;True to allow printer option
- REPERR EQU TRUE ;True to report command line option errors
- REPSIZ EQU TRUE ;True to report file sizes
- REPUSR EQU TRUE ;True to report user numbers
- RMAC EQU FALSE ;True for RMAC assembly and external def link
- ROPT EQU TRUE ;True to allow reset option
- SOPT EQU TRUE ;True to allow system file option
- TOPT EQU TRUE ;True for sort by filetype & filename
- TOPREV EQU FALSE ;False to reverse "T" opt for normal sort
- UOPT EQU TRUE ;True to allow user number option
- VOPT EQU TRUE ;True to allow version number display
- LOPT EQU TRUE ;True to allow Library file member printing
- LOPREV EQU FALSE ;False to reverse the "L" option and not print
-
- REVIDEO EQU TRUE ;Use reverse video sequences
- LEADIN EQU 27 ;Esc. leadin for ADM-31 & Z19
- INTOREV EQU 0029H ;Dim video for ADM-31 type terminals
- OUTAREV EQU 0028H ;and to get out (note digits are reversed)
- * NOTE: use a 2 digit INTO/OUTA sequence & set one to 0 if only one needed
-
- * INTOREV EQU 3847H ;Seq. for underline mode (for WYSE-200)
- * OUTAREV EQU 3047H ;Normal video " "
- * INTOREV EQU 0070H ;Sequence to enter reverse video (Z19)
- * OUTAREV EQU 0071H ;And to get out
- * LEADIN EQU '~' ;Tilda leadin for hazeltine 1500
- * INTOREV EQU 0019H ;Background mode on Hazeltine 1500
- * OUTAREV EQU 001FH ;Foreground mode on Hazeltine 1500
- VECTOR EQU FALSE ;True to display attributes on Flashwriter II
- VIDEO EQU 0E009H ;Entry to Flashwriter video driver PROM
-
- DELIM EQU 7CH ;Fence (delimiter) character (vertical bar)
- ;DELIM EQU 20H ;Space
-
- NPL EQU 4 ;# of names per line (max of 3 for 64x16)
- * (max of 4 for 80x24)
-
- LPS EQU 23 ;# of lines per screen (max of 14 for 64x16)
- * (max of 23 for 80x24)
- STMSG EQU TRUE ;true to start each directory with message
- *
- STSKIP EQU 3 ;Start skipping at this drive number
- SKIPTO EQU 13 ;and skip to this drive number
-
-
-
- IF NOPT AND NOT PGPAWZ
- ++++ NOPT OPTION REDUNDANT WITHOUT PGPAWZ ++++
- ENDIF
-
- IF REPERR AND NOT OPTION
- ++++ REPERR EQUATE USELESS WITHOUT OPTION ++++
- ENDIF
-
- * BDOS equates
-
- RDCHR EQU 1 ;Read char from console
- WRCHR EQU 2 ;Write char to console
- 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)
-
- IF ALTCPM
- BASE EQU 4200H
- TPA EQU 4300H
- ENDIF
-
- IF (NOT ALTCPM) AND (NOT RMAC)
- BASE EQU 0 ;Default to 0 (or 100H with MAC +R option)
- TPA EQU 100H
- ENDIF
-
- IF RMAC
- EXTRN BASE,FCB,BDOS ;Make base external
- ELSE
- FCB EQU BASE+5CH
- BDOS EQU BASE+5
- ASEG ; Ignore this error if using MAC
- ORG TPA
- ENDIF
-
- FILL MACRO BYTES,WITH
- REPT BYTES
- DB WITH
- ENDM
- ENDM
-
- $-MACRO
-
- PAGE 60
- TITLE 'SD Version 4.8 - 10 May 1983'
-
- *********************************
- * *
- * BEGIN EXECUTABLE PROGRAM CODE *
- * *
- *********************************
-
- JMP START
-
- MLEADIN DB LEADIN ;leadin char for hilite sequences
- MINTOREV DW INTOREV ;code to enter hilite mode
- MOUTAREV DW OUTAREV ;code to return to normal mode
- MDELIM DB DELIM ;char to delimit columns on display
- MNPL DB NPL ;names per line (# of columns)
- MLPS DB LPS ;lines per screen (between pauses)
- BDOSPAG DB BDOSPG ;normal residing place for BDOS if LOWCCP
- VERNAME:
- DB 'SD 4.8A-10May83/HMVT rev-B 10Aug8','3'+80H
-
- HLPMES: DB 13,10,10
- DB 'Useage: SD dr:FILENAME.TYP [option,option...]'
- DB 13,10,10,'Drive and/or filespec are optional'
- DB 13,10,'Wildcards * and ? allowed'
- DB 13,10,'SD // for help'
- DB 13,10,10,'Options Are:'
- DB 13,10,09,'A=All Users'
- DB 13,10,09,'D=All Disks'
- DB 13,10,09,'F=Make File'
- DB 13,10,09,'L=Library'
- DB 13,10,09,'N=No Paging'
- DB 13,10,09,'P=Printer'
- DB 13,10,09,'R=Reset'
- DB 13,10,09,'S=System'
- DB 13,10,09,'T=Sort by Type'
- DB 13,10,09,'Un=User No.'
- DB 13,10,09,'V=Versio','n'+80H
-
- START: LXI H,0
- DAD SP ;HL=old stack
- SHLD STACK ;Save it
- LXI SP,STACK ;Get new stack
-
- 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, or
- 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
- STA BASUSR ;Save extra copy for multi-disk directories
- ENDIF
-
- 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
-
- * 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).
-
- IF OPTION
- LXI H,80H ;Set command line buffer+2 pointer
- MOV B,M ;Get length of command line buffer
-
- * Check for a help request
- INX H
- INX H
- MOV A,M
- CPI '/'
- CZ HELP
- DCX H
- DCX H
- * Search for the command line delimiter. If not found, assume no options.
-
- SCNDOL: INX H
- DCR B
- JM CKREST ;Exit if command line buffer empty
- MOV A,M
- CPI '[' ;Digital Research changing to "["
- JNZ SCNDOL
- ; DCX H ;'$' found - make sure space precedes it
- ; 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
- CPI ',' ;Same for comma
- JZ SCNOPT
- CPI ']' ;End of option list
- JZ CKREST
- 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
- CMP M ;Compare our character with option table
- JNZ NOMACH ;Exit if no match
- MVI M,0 ;Otherwise, activate the flag
- JMP SCNOPT ;..and go get the next option character
-
- * 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 that ain't 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 as it may be only 1 digit
-
- IF DOPT
- STA BASUSR ;Duplicate it if multi-disk mode
- PUSH PSW
- MVI A,0FFH ;Set got user flag
- STA GOTUSR
- POP PSW
- ENDIF
-
- INX D ;Bump to possible 2nd digit of user number
- DCR B
- JM CKREST ;If no more buffer, exit with complete user #
- LDAX D ;Else, check for another digit
- SUI 30H
- JC SCNAGN ;If next char not numeric, its not part of
- CPI 10 ;..user number so go check for another option
- JNC SCNAGN
- 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
-
- IF DOPT
- STA BASUSR ;Duplicate it if multi-disk mode
- ENDIF
-
- JMP SCNOPT ;Continue scanning
- ENDIF ;Balance 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 command 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
- JMP HELP1 ;..and tell how to do it
- ELSE
-
- JMP SCNOPT ;If not reporting errors, ignore the dud
-
- ENDIF ;Balance REPERR
- ENDIF ;Balance OPTION
-
- * 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 ROPT
- LDA ROPFLG ;If reset flag set, reset disk system before
- ORA A ;..starting to update allocation vectors
- MVI C,RESET
- CZ CPM
- ENDIF ;Balance ROPT
-
- IF VOPT
- LDA VOPFLG ;If version display flag set, print it
- ORA A
- JNZ NOVOPT
- LXI D,VERNAME
- CALL PRINT
- CALL CRLF
- NOVOPT:
- ENDIF
-
- IF DOPT
- LDA DOPFLG ;If multi-disk flag set,
- ORA A ;..need to set error traps
- CZ SWAPEM ;Swap BDOS error vector tables
- ENDIF
-
- * If "A" option choosen and no user number specified
- * set user to zero
-
- IF (AOPT AND STARTZ)
- ZUSR: LDA GOTUSR ;Was a user specified?
- ORA A
- JNZ ZDRV ;YES-quit now
- LDA AOPFLG ;Was D option specified?
- ORA A
- JNZ ZDRV ;JMP if NO
- XRA A
- STA NEWUSR ;ZERO NEWUSR for all users
- IF DOPT
- STA BASUSR ;ZERO BASUSR for all users
- ENDIF
- ENDIF
-
- * If "D" option choosen and no drive specified
- * set drive to physical zero
-
- ZDRV: LXI H,FCB
- MOV A,M ;Get drive name for directory search
- ORA A ;Any specified?
- JNZ NOOPT ;Yes skip next routine
-
- IF (DOPT AND STARTZ)
- LDA DOPFLG ;else if DOPT then
- ORA A
- JNZ ZDRV1
- INR A ;always start with A
- MOV M,A
- JMP NOOPT
- ENDIF
-
- ZDRV1: LDA OLDDSK ;Otherwise, get default disk
- INR A
- MOV M,A ;Put the absolute drive code in directory FCB
-
-
- * Validate drive code and user area numbers from the drive table.
-
- NOOPT: LXI D,DREMSG ;Get the drive/user error message
- PUSH D
- LDA FCB ;Get directory drive code
- DCR A ;Normalize to range of 0-15
- CPI HIDRV-LODRV ;Compare with maximum drives on-line
- JNC ERXIT ;Take drive error exit if out of range
- LXI H,USRMSG ;Switch to user # error message
- XTHL
- MOV E,A ;Use drive code as index into table
- MVI D,0
- LXI H,LODRV ;Point to base of drive/user table
- DAD D
- MOV A,M ;Get the maximum user # for this drive
- ANI 0FH ;Make sure its in range 0 - 15
- 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
-
- LXI H,FCB+1 ;Point to name
- MOV A,M ;Any specified?
- CPI '['
- JZ GOTDL
- CPI ' '
- JNZ GOTFCB
-
- * No FCB - make FCB all '?'
-
- GOTDL: 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's 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 pointer 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 - return 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 table begins where order table 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
-
- * Look up the FCB in the directory
-
- SFIRST: 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
-
- MOV A,M ;Get SYS 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,12 ;Entry length (name, type, extent)
-
- TMOVE: LDAX D ;Get entry char
-
- IF NOT (VECTOR OR REVIDEO)
- ANI 7FH ;Remove attributes
- ENDIF
-
- MOV M,A ;Store in table
- INX D
- INX H
- DCR B ;More?
- JNZ TMOVE
- INX D
- INX D ;Point to sector count
- LDAX D ;Get it
- MOV M,A ;Store in table
- INX H
- SHLD NEXTT ;Save updated table addr
- 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 then loop back for more
-
- OUTMEM: CALL ERXIT ;Exit if directory too large
- DB 'Memor','y' OR 80H
-
- * Sort and print
-
- SPRINT: IF AOPT OR FOPT OR UOPT
- CALL SETFOP ;Return to file output DMA & user #
- ENDIF
-
- 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 01
- 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
- 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 with 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.
-
- ; IF AOPT
- LXI H,OPNFLG ;point 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, make opnflg not zero and open
- ; ENDIF ;Balance AOPT
-
- * 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 'Ope','n' OR 80H
-
- WRTERR: CALL ERXIT
- DB 'Writ','e' OR 80H
-
- * 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 we're 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 'Appen','d' OR 80H
-
- * 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, keep looking til 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 operation
- * 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 we can't 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 ;Balance FOPT
-
- NOOUT:
- IF LOPT
- LHLD COUNT
- SHLD LCOUNT
- LXI H,0
- SHLD LBTOTL
- SHLD LMTOTL
- LXI H,ORDER ;Initialize order table pointer
- SHLD NEXTL
- ELSE
-
- LXI H,ORDER ;Initialize order table pointer
- ENDIF
-
- SHLD NEXTT
-
- IF STMSG ;Print "Driectory for...
- LXI D,DIRMS1 ;at start of each section
- CALL PRINT
- CALL PRDIR ;Print " Drive, x User, y"
- LDA LINCNT
- INR A ;Bump line count
- STA LINCNT
- ENDIF
-
- JMP NEWLIN ;Start new line and output the files
-
- * 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
- * extent file. Go only when we have the last extent of the file.
-
- PUSH B ;Save NPL
- CALL CKABRT ;Check for abort code from keyboard
- 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 comes last in list
- SHLD NEXTT
- JMP ENTRY ;Loop back for next lowest extent
-
- * Valid entry obtained - spit it out.
-
- 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
-
- 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
-
- * Compute the size of the file and update our summary datum.
-
- MOV E,M ;Get extent #
- MVI D,0
- INX H
- MOV A,M ;Get sector count of last extent
- XCHG
- DAD H ;# of extents times 16k
- DAD H
- DAD H
- DAD H
- XCHG ;Save in DE
- LXI H,BLKMSK
- ADD M ;Round last extent to block size
- RRC
- RRC ;Convert from sectors to K
- RRC
- ANI 1FH
- MOV L,A ;Add to total K
- MVI H,0
- DAD D
- LDA BLKMSK ;Get SECTORS/BLK-1
- RRC
- RRC ;Convert to K/BLK
- RRC
- ANI 1FH
- CMA ;Use to finish rounding
- ANA L
- MOV L,A
- XCHG ;Save file size in DE
- LHLD TOTSIZ
- DAD D ;Add to total used
- SHLD TOTSIZ
- LHLD TOTFIL ;Increment file count
- INX H
- SHLD TOTFIL
- XCHG ;Get back file size
-
- * If report size enabled, output the size of the individual file.
-
- IF REPSIZ ;If file size report wanted
- CALL DECPRT ;..go print it
- MVI A,'k' ;..and follow with K size
- CALL TYPE
- ENDIF
-
- * 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
-
- MVI A,3 ;If printing less than 4 wide
- CMP C
- JC NWLA
-
- LDA FCB ;.. precede new line with drive name
- ADI 'A'-1
- CALL TYPE
-
- IF REPUSR ;If reporting user numbers and running under
- CALL CKVER ;..CP/M 2, output the user number too
- CNC TYPUSR
- ENDIF ;Balance REPUSR
-
- MVI A,':' ;Tag header with a colon and a space
- CALL FPAD ;..and exit back to ENTRY
-
- NWLA:
-
- JMP ENTRY ;Go back and output another file
-
- * Print HL in decimal with leading zero suppression
-
- DECPRT: SUB A ;Clear leading zero flag
- STA LZFLG
- LXI D,-1000 ;Print 1000's digit
- CALL DIGIT
- 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 ;Set leading zero flag so next zero prints
- JMP TYPE ;And print digit
-
- * Show total space and files used
-
- PRTOTL:
- IF LOPT
- LDA LOPFLG
- ORA A
-
- IF LOPREV
- JZ PRTOT1
- ELSE
- JNZ PRTOT1
- ENDIF
-
- LHLD TOTFIL ;How many files did we match?
- MOV A,H
- ORA L
- CNZ PRTLMEM ;Skip the Library check if we didn't find any
- PRTOT1 EQU $
- ENDIF
-
- 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
-
- CALL CRLF
- CALL PRDIR ;Print " Drive, x User, y"
-
- NOUSER: LXI D,TOTMS3 ;Print " CONTAINS "
- CALL PRINT
- LHLD TOTSIZ ;Print total K used by files matched
- CALL DECPRT
- LXI D,TOTMS4 ;PRINT "K IN "
- CALL PRINT
- POP H ;Recall TOTFIL
- CALL DECPRT ;Print number of files matched
- LXI D,TOTMS5 ;Print " FILES WITH "
- CALL PRINT
- CALL PRTFRE ;Output free space remaining & " FREE."
-
- * Directory for one user area completed. If all users option is
- * selected, 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 ;Balance DOPT and AOPT
-
- * We've finished all of our outputting. Flush the remainder of the
- * output buffer and close the file before going to exit routine.
-
- GOCLZ: IF FOPT
- ; LDA FOPFLG ;Is file output mode active?
- ; ORA A
- ; JNZ NXTDSK ;If not, move to next drive, otherwise ..
- ; STA PASS1 ;Make PASS1=0 to force reopen on next drive
-
- 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 BUFFER
- MVI M,128 ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
- ORA A ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
- JM CLOSE ;close sd.dir if buffer is empty
- JZ FLUSH ;write last record to sd.dir if buffer full
-
- LHLD BUFPNT ;OTHERWISE, PAD UNUSED BUFFER WITH CTRL-ZS
- PUTAGN: MVI M,'Z'-40H
- INX H
- DCR A
- JNZ PUTAGN ;CONTINUE PADDING TIL BUFFER FILLED OUT
- ; MVI A,128
- ; STA BUFCNT ;Force buffer to empty status
-
- 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 ;BALANCE 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 directory 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, disable temporarily
- LXI H,FOPFLG
- DCR M
- PUSH H
- ENDIF
-
- LDA FCB ;Stash ASCII directory drive in NO FILE msg
- ADI 'A'-1
- STA NOFMS2
- LXI D,NOFMS1 ;Print "No file on ? - "
- CALL PRINT
- CALL PRTFRE ;Tag with free message
-
- IF FOPT ;Restore original file output mode
- POP H
- INR M
- ENDIF
-
- 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,STSKIP ;Skip if STart SKIP
- LXI H,FCB ;Bump directory FCB drive code
- INR M
- CMP M
- JNZ NEXT1
- MVI A,SKIPTO ;If STSKIP then SKIPTO
- MOV M,A
- NEXT1: MVI A,HIDRV-LODRV ;Get maximum drive code to search
- CMP M ;Does next disk exceed maximum?
- JNC NOOPT ;Search next disk if not
- ENDIF ;Balance DOPT
-
- NPRT: ;if no printer, fall through to EXIT
-
- IF POPT ;now, check if printer is in use
- LDA POPFLG
- ORA A ;printer active?
- JNZ EXIT ;no, just exit...
- MVI C,5
- MVI E,13 ;print a CRLF
- CALL CPM
- MVI E,10 ;line feed
- CALL CPM
- ENDIF ;POPT
-
- JMP EXIT ;All done - exit to CCP
-
- * Print "Directory for....
-
- PRDIR: 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 PRDIR1
- LXI D,TOTMS2 ;Print ", USER "
- CALL PRINT
- CALL TYPUSR ;Output the user number
- ENDIF
- PRDIR1: RET
-
- * Print the user number of the directory in decimal
-
- TYPUSR: IF REPUSR
- LDA NEWUSR
- CPI 10 ;If user no. > 9 print leading 1
- JC DUX
- MVI A,'1'
- CALL TYPE
- LDA NEWUSR ;Print low digit of user no.
- SUI 10
- DUX: ADI '0'
- JMP TYPE
- ENDIF
-
- * Force new line on video and check for page pause
-
- CRLF: MVI A,0DH ;Send CR
- CALL TYPE
- MVI A,0AH ;Send LF
- JMP TYPE ;Exit to caller from TYPE
-
- * Separate the directory output on a line with a space, the delimiter,
- * followed by another space.
-
- FENCE: CALL SPACE
-
- LDA MDELIM ;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
-
- * 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
- * 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 ;Take 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 ;Balance 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
-
- IF PGPAWZ
- CPI 0AH ;Do we have a LF?
- JNZ TYPRET ;Exit if not
- ENDIF
-
- IF NOPT AND PGPAWZ
- LDA NOPFLG ;Is the page pause function disabled?
- ORA A
- JZ TYPRET ;Exit if so
- ENDIF
-
- IF PGPAWZ
- 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,9 ;..without checking for LFs
- CALL BDOS
- CALL CINPUT ;Wait for character
- CPI 'C'-40H
- JZ EXIT ;Abort on CTRL-C
- XRA A ;Reset line count
- NOTEOS: STA LINCNT ;Save new line count
- ENDIF
-
- 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 ;Set video driver function for direct output
- JMP VIDEO ;Display in reverse video and exit from VIDEO
- ENDIF
-
- TYPE2: IF REVIDEO
- ORA A
- JP TYPE99
- PUSH PSW
- LDA MLEADIN ;Send ESC char first
- CALL TYPE99
- LDA MINTOREV ;INTO REV VIDEO
- CALL TYPE99
- LDA MINTOREV+1
- 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
- CALL TYPE99
- LDA MOUTAREV+1 ;The out of reverse video character
-
- TYPE99:
- ENDIF ;Balance 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
- ELSE
-
- MOV E,A ;Get character into BDOS entry register
- MVI C,WRCHR
- JMP BDOS ;Call CONOUT via the BDOS
- ENDIF ;Balance DIRCON
-
-
- * Print a string at HL of length B
-
- TYPEIT: MOV A,M
- CALL TYPE
- INX H
- DCR B
- JNZ TYPEIT
- RET
-
- * Print string terminated with last byte high on console.
-
- PRINT: LDAX D
- PUSH PSW
- ANI 7FH
- CALL TYPE
- POP PSW
- ORA A
- RM
- INX D
- JMP PRINT
-
- * Fetch character from console (without echo)
-
- CINPUT: LHLD BASE+1
- MVI L,9
- CALL GOHL
- ANI 7FH
- 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 ;CTRL-C?
- JZ EXIT ;If CTRL-C then quit
- CPI 'S'-40H ;CTRL-S?
- RNZ ;No, return to caller
- CALL CINPUT ;Yes, wait for another char.
- CPI 'C'-40H ;Might be CTRL-C
- JZ EXIT ;Exit if CTRL-C, else fall thru and continue
- 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 extended 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
-
- IF FOPT
- LXI D,OUTBUF ;Move DMA from search buffer into the
- JMP SET2 ;..output buffer
- ENDIF
- 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: LHLD FREEBY ;Get space left before adding to MASTER.DIR
- CALL DECPRT ;Print K free
- LXI D,TOTMS6 ;Print " 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 - modified for filetype sort
-
- 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
-
- IF TOPT ;If T option true
- LDA TOPFLG ;Get option flag
- ORA A ;test for zero
- IF TOPREV ;If reverse "T" option
- JZ CMPFNFT ;and "T" option choosen JMP
- ELSE
- JNZ CMPFNFT
- ENDIF
- *
- * Compare by Filename, Filetype, and Extent - in that order
- *
- PUSH H
- PUSH B
- LXI D,8 ;Pt to FT
- CALL ADDEM
- MVI E,3 ; 3 bytes in type
- CALL CMPLPE ;compare FT'S
- POP B
- POP H
- RNZ ;Continue if match
- PUSH H
- PUSH B
- MVI E,8 ;8 bytes in name
- CALL CMPLPE ;Compare FN'S
- POP B
- POP H
- RNZ ;Continue if match
- LXI D,11 ;Pt to EXT
- CALL ADDEM
- LDAX B ;Compare EXT'S
- CMP M
- RET
-
- ADDEM: PUSH H ;Adds DE to HL & BC
- MOV H,B
- MOV L,C
- DAD D
- MOV B,H
- MOV C,L
- POP H
- DAD D
- RET
- ENDIF
-
- *
- * Compare by Filename, Filetype, Extent - in that order
- *
- CMPFNFT:
- MVI E,12 ;Compare FN, FT, EX
- ; and fall into routine
- 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
-
- HELP: INX H ;Make sure there is a
- CMP M ;second "/" else return
- DCX H ;since some people use /
- RNZ ;for a file name
- HELP1: LXI D,HLPMES ;Print a short HELP message
- CALL PRINT
- CALL CRLF
- JMP EXIT
-
- * Error exit
-
- ERXIT: IF FOPT
- MVI A,-1
- STA FOPFLG ;Disable file output mode on error
- ENDIF
-
- 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: MVI C,CONST ;Check console status
- CALL CPM
- ORA A ;Char waiting?
- MVI C,RDCHR
- CNZ CPM ;Gobble up char
-
- 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
- EXIT1:
- ENDIF
-
- 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 ;Balance 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 BDOSPAG ;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 second check just to be
- ;sure we are OK.
- INX H ;swap in the new pointer if running a prg
- MOV E,M ;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
-
- * 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
-
- IF LOPT
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- ; SUBROUTINES to read library file directory
- ;
- ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- ;
- PRTLMEM LXI H,ORDER ;Initialize order table pointer
- SHLD NEXTL
- XRA A
- STA LNCNT
- ENTRYL LHLD LCOUNT
- MOV A,H ;Is this the last file?
- ORA L
- JZ LBEXIT ;If COUNT=0, last file so RETURN
- DCX H ;Dock file count
- SHLD LCOUNT
- 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 since 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
- LDA LNCNT
- CMP M
- CNZ CRLF
- LXI D,CONTM ;Print "There are "
- 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
- CALL PRINT
- RET
-
- * 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 ENTRYL
- PUSH D
- LXI H,MNPL
- LDA LNCNT
- CMP M
- CNZ CRLF
- LXI H,LFMSEP
- MVI B,31
- CALL TYPEIT
- 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 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
- JMP ENTRYL
- NLBRF DB '++Not a LIBRARY file.++',13,10
- ;
- ; Close the library file
- ;
- LBCLOSE LXI D,LBRFCB
- MVI C,CLOSE
- CALL CPM
- RET
- ;
- ; SETLDMA - 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
- ;
- ; CKLDIR - check to see if there indeed is a LBR file
- ; directory and barf if not!
- ;
- CKLDIR: MVI B,11 ;len 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
- LDA MNPL
- STA LNCNT ;Reset names per line counter
- 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
- MVI A,3 ;If printing less than 4 wide
- CMP M
- JC PRMNA1
- LDA LBRFCB ;.. precede new line with drive name
- ADI 'A'-1
- CALL TYPE
-
- IF REPUSR ;If reporting user numbers and running under
- CALL CKVER ;..CP/M 2, output the user number too
- CNC TYPUSR
- ENDIF ;Balance REPUSR
-
- MVI A,':' ;Tag header with a colon and a space
- CALL FPAD ;..and exit back to ENTRY
- 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
-
- * If report size enabled, output the size of the individual file.
-
- IF REPSIZ ;If file size report wanted
- CALL DECPRT ;..go print it
- MVI A,'s' ;..and follow with S size
- CALL TYPE
- ENDIF
-
- * 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 character
- 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 CHAR
- STAX D ;STORE IT
- INX H ;TO NEXT "FROM"
- INX D ;TO NEXT "TO"
- DCR B ;MORE?
- JNZ MOVE ; YES, LOOP
- RET ; NO, RETURN
- ;
- ; cklbr -- 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
- ;
- LFMSEP db ' Library file members for : '
- LBRTYP db 'LBR'
- ENDIF ;LOPT
-
- ***********************
- * *
- * End of Program Code *
- * *
- ***********************
-
- * Initialized data area
-
- DREMSG: DB 'Driv','e' OR 80H
-
- IF PGPAWZ
- EOSMSG: DB ' [More]',0DH,'$'
- ENDIF
-
- ERRMS1: DB ' '
- ERRMS2: DB 'Erro','r' OR 80H
-
- IF REPERR
- ERRTAG: DB ' -','>' OR 80H
- ENDIF
-
- NOFMS1: DB 0DH,0AH,'No file on '
- NOFMS2: DB ' -',' ' OR 80H
-
- DIRMS1: DB 0DH,0AH,' Directory fo','r' OR 80H
-
- TOTMS1: DB ' Drive',' ' OR 80H
-
- IF REPUSR
- TOTMS2: DB ', user',' ' OR 80H
- ENDIF
-
- TOTMS3: DB ' contains',' ' OR 80H
- TOTMS4: DB 'k in',' ' OR 80H
- TOTMS5: DB ' files with',' ' OR 80H
- TOTMS6: DB 'k free','.',0DH,0AH OR 80H ;,0DH,0AH OR 80H
- USRMSG: DB 'User ','#' OR 80H
-
- IF LOPT
- CONTM DB ' There are',' '+80H
- MFILES DB ' Member Files in',' '+80H
- LIBR DB ' Library(s)','.'+80H
- ENDIF
-
- FNDFLG: DB 0 ;Flag whether any files matched
-
- IF PGPAWZ
- LINCNT: DB 0 ;Count of lines printed on screen
- ENDIF
-
- * 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
- * appropriate for each drive on your system, and then delete any
- * DBs referencing drives that don't exist. Note also that there
- * are only 16 user areas available under CP/M 2, so the highest
- * legal user area you can specify is 15 (range 0-15 = 16 areas).
- * The program will convert anything over 15 into mod 15.
- * NOTE: If some drives in active table are unused then skip these
- * drives by using STSKIP and SKIPTO equates.
-
- LODRV EQU $ ;Mark beginning of drive/user table
-
- DB 15 ;Maximum user area for Drive A
- DB 15 ; " " " " " B
- DB 00 ; " " " " " C
- DB 00 ; " " " " " D
- DB 00 ; " " " " " E
- DB 00 ; " " " " " F
- DB 00 ; " " " " " G
- DB 00 ; " " " " " H
- DB 00 ; " " " " " I
- DB 00 ; " " " " " J
- DB 00 ; " " " " " K
- DB 00 ; " " " " " L
- DB 15 ; " " " " " M
- ; DB 15 ; " " " " " N
- ; DB 15 ; " " " " " O
- ; DB 15 ; " " " " " P
-
- HIDRV EQU $ ;Mark end of drive/user table
-
- * Option field lookup table.
- * Note that you can force any of these options 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 unrecognized.
-
- OTBL EQU $ ;Mark start of option table
-
- IF AOPT ;All users-option flag
- AOPFLG: DB 'A'
- ENDIF
-
- IF DOPT ;Multi-disk-option flag
- DOPFLG: DB 'D'
- ENDIF
-
- IF FOPT ;File-output-option flag
- FOPFLG: DB 'F'
- ENDIF
-
- IF LOPT ;Display Library members flag
- LOPFLG: DB 'L'
- ENDIF
-
- IF NOPT AND PGPAWZ ;No page-pause option flag
- NOPFLG: DB 'N'
- ENDIF
-
- IF POPT ;Printer option flag
- POPFLG: DB 'P'
- ENDIF
-
- IF ROPT ;Reset option flag
- ROPFLG: DB 'R'
- ENDIF
-
- IF SOPT ;System file option flag
- SOPFLG: DB 'S'
- ENDIF
-
- IF TOPT
- TOPFLG: DB 'T' ;Type sort option flag
- ENDIF
-
- IF VOPT ;Display version number flag
- VOPFLG: DB 'V'
- ENDIF
-
- OEND EQU $ ;Mark end of option table
-
- * End of option lookup table
-
- ; IF AOPT
- ;PASS1: DB 0 ;First pass flag for all user file output
- ; ENDIF
-
- IF DOPT
- VECTBL: DW DSKERR ;BDOS SECTOR ERROR INTERCEPT VECTOR
- DW DSKERR ;BDOS SELECT ERROR INTERCEPT VECTOR
- ENDIF
-
- IF FOPT
- BUFPNT: DW OUTBUF ;POINTER TO NEXT LOCATION IN OUTPUT BUFFER
- BUFCNT: DB 128 ;NUMBER OF BYTES LEFT IN OUTPUT BUFFER
- opnflg: db 0 ;file open flag for all user file output
- OUTFCB: DB 0,'SD DIR'
- FILL 21,0 ;REST OF SD.DIR FCB
- OUTBUF DS 128 ;OUTPUT FILE BUFFER
- ENDIF
-
- IF STARTZ
- GOTUSR: DB 0
- ENDIF
-
- * Uninitialized data area
-
- BASUSR DS 1 ;Dupe of original directory 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 directory drive
- GAP DS 2 ;Sort routine storage
- 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 ;Maximum user # for drive from lookup table
- NEWUSR DS 1 ;Contains user number 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 ;CP/M version number (0=pre-CP/M 2)
-
- IF LOPT
- LMTOTL DW 0
- LBTOTL DW 0
- LNCNT DB 0
- LCOUNT DW 0
- NEXTL DW 0
- SLFILE DW 0
- LBRFCB: DS 36
- LBBUF DS 80H
- ENDIF
-
- DS 60 ;Stack area
- STACK DS 2 ;Save old stack pointer here
-
- ORDER EQU $ ;Order table starts here
-
- END
-