home *** CD-ROM | disk | FTP | other *** search
Text File | 1984-04-29 | 37.6 KB | 1,626 lines |
- TITLE 'XDIR Ver 1.0 for CP/M-86'
- ;
- ; XDIR.A86 for CP/M-86, as of February 18, 1981: Kelly Smith
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- ;USER OPTION SPECIFICATIONS
- ;
- AOPT EQU TRUE ;TRUE TO ALLOW SEARCHING ALL USER AREAS
- DOPT EQU TRUE ;TRUE TO ALLOW SEARCHING ALL DRIVES ON-LINE
- 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
- SOPT EQU TRUE ;TRUE TO ALLOW SYSTEM FILE OPTION
- UOPT EQU TRUE ;TRUE TO ALLOW USER NUMBER OPTION
- DELIM EQU 7CH ;FENCE (DELIMITER) CHARACTER (VERTICAL BAR)
- BIGCRT EQU TRUE ;TRUE = 24/80 DISPLAY, FALSE = 16/64 DISPLAY
- NPL EQU 4 ;# OF NAMES PER LINE (MAX OF 3 FOR 64X16)
- ; (MAX OF 4 FOR 80X24)
- LPS EQU 20 ;# OF LINES PER SCREEN (MAX OF 12 FOR 64X16)
- ; (MAX OF 20 FOR 80X24)
- ;
- ; 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
- BASE EQU 0
- TPA EQU 100H
- FCB EQU BASE+5CH
- ;
- M EQU Byte Ptr 0[BX]
- ;
- ; BEGIN EXECUTABLE PROGRAM CODE
- ;
- ORG TPA
- START: MOV DL,0FFH ;GET CURRENT USER NUMBER
- MOV CL,CURUSR
- CALL CPM
- MOV Byte Ptr OLDUSR,AL ;INITIALIZE STARTUP USER NUMBER
- MOV Byte Ptr NEWUSR,AL ;..AND MAKE NEW USER MATCH IT
- MOV Byte Ptr BASUSR,AL ;SAVE EXTRA COPY FOR MULTI-DISK DIRECTORIES
- MOV CL,CURDSK
- CALL CPM ;GET CURRENT DISK NR
- MOV Byte Ptr OLDDSK,AL ;SAVE FOR RESET IF NEEDED
- INC AL
- MOV Byte Ptr OUTFCB,AL ;SET DIRECTORY OUTPUT FILE DRIVE
- MOV BX,FCB
- MOV AL,M ;GET DRIVE NAME FOR DIRECTORY SEARCH
- OR AL,AL ;ANY SPECIFIED?
- JNZ START2 ;YES SKIP NEXT ROUTINE
- MOV AL,Byte Ptr OLDDSK ;OTHERWISE, GET DEFAULT DISK
- INC AL
- START2: MOV M,AL ;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).
- ;
- MOV BX,80H ;SET COMMAND LINE BUFFER POINTER
- MOV CH,M ;GET LENGTH OF COMMAND LINE BUFFER
- ;
- ; SEARCH FOR THE COMMAND LINE DELIMITER. IF NOT FOUND, ASSUME NO OPTIONS.
- ;
- SCNDOL: LAHF
- INC BX
- SAHF
- DEC CH
- JNS L_1
- JMP CKREST ;EXIT IF COMMAND LINE BUFFER EMPTY
- L_1:
- MOV AL,M
- CMP AL,'$'
- JNZ SCNDOL
- DEC BX ;'$' FOUND - MAKE SURE SPACE PRECEDES IT
- MOV AL,M
- INC BX
- CMP AL,' '
- 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 BX,DX ;GET OPTION FIELD POINTER TO DE
- SCNOPT: LAHF ;BUMP TO NEXT OPTION FIELD CHARACTER
- INC DX
- SAHF
- DEC CH ;DOCK CHARACTERS LEFT IN OPTION FIELD
- JNS L_2
- JMP CKREST ;IF OPTION FIELD EXHAUSTED, EXIT
- L_2:
- SCNAGN: MOV SI,DX ;GET THE NEXT OPTION CHARACTER
- MOV AL,[SI]
- CMP AL,' ' ;DO WE HAVE A SPACE?
- JZ SCNOPT ;IGNORE IT IF SO
- MOV BX,(Offset OTBL)-1 ;GET BASE OF OPTION LOOKUP TABLE
- MOV CL,(Offset OEND)-(Offset OTBL)+1 ;GET LENGTH OF OPTION LOOKUP TABLE
- NOMACH: INC BX ;BUMP TO NEXT OPTION TABLE CHARACTER
- DEC CL ;ARE WE OUT OF THE TABLE?
- JZ CK4USR ;IF SO, CHECK FOR USER OPTION
- CMP AL,M ;COMPARE OUR CHARACTER WITH OPTION TABLE
- JNZ NOMACH ;EXIT IF NO MATCH
- MOV M,0 ;OTHERWISE, ACTIVATE THE FLAG
- JMPS SCNOPT ;..AND GO GET THE NEXT OPTION CHARACTER
- ;
- ; IF OPTION CHARACTER DOESN'T MATCH THE TABLE, SEE IF WE HAVE A USER
- ; OPTION.
- ;
-
- IF UOPT
- CK4USR: ;CHECK FOR USER NUMBER OPTION
- CMP AL,'U'
- JNZ CLERR ;LAST OPTION, SO BAD DEAL IF THAT AIN'T IT
- UAGN: LAHF ;BUMP TO USER NUMBER DIGIT
- INC DX
- SAHF
- DEC CH
- JS CLERR ;ERROR IF NOTHING LEFT
- MOV SI,DX ;GET DECIMAL DIGIT
- MOV AL,[SI]
- CMP AL,' ' ;IGNORE LEADING SPACES
- JZ UAGN
- SUB AL,30H ;SUBTRACT ASCII BIAS
- JB CLERR ;ERROR IF < 0
- CMP AL,10
- JNB CLERR ;ERROR IF > 9
- MOV Byte Ptr NEWUSR,AL ;SAVE USER NUMBER AS IT MAY BE ONLY 1 DIGIT
- MOV Byte Ptr BASUSR,AL ;DUPLICATE IT IF MULTI-DISK MODE
- LAHF ;BUMP TO POSSIBLE 2ND DIGIT OF USER NUMBER
- INC DX
- SAHF
- DEC CH
- JS CKREST ;IF NO MORE BUFFER, EXIT WITH COMPLETE USER #
- MOV SI,DX ;ELSE, CHECK FOR ANOTHER DIGIT
- MOV AL,[SI]
- SUB AL,30H
- JB SCNAGN ;IF NEXT CHAR NOT NUMERIC, ITS NOT PART OF
- CMP AL,10 ;..USER NUMBER SO GO CHECK FOR ANOTHER OPTION
- JNB SCNAGN
- MOV BL,AL ;SAVE UNITS DIGIT
- MOV AL,Byte Ptr NEWUSR ;GET TENS DIGIT
- ADD AL,AL ;MULTIPLY BY 10
- MOV BH,AL
- ADD AL,AL
- ADD AL,AL
- ADD AL,BH
- ADD AL,BL ;COMBINE WITH UNITS DIGIT
- MOV Byte Ptr NEWUSR,AL ;SAVE THE TOTAL USER NUMBER
- MOV Byte Ptr BASUSR,AL ;DUPLICATE IT IF MULTI-DISK MODE
- JMP SCNOPT ;CONTINUE SCANNING
- ENDIF
-
- ;
- ; 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.
- ;
-
- IF REPERR
- CLERR:
- XOR AL,AL
- LAHF ;TAG END OF COMMAND LINE WITH TERMINATOR
- INC DX
- SAHF
- MOV SI,DX
- MOV [SI],AL
- CALL CRLF
- MOV DX,(Offset ERRMS2)
- CALL PRINT
- MOV DX,(Offset ERRTAG)
- CALL PRINT
- MOV BX,81H ;PLAYBACK BAD COMMAND LINE TO ERROR POINT
- CLELP: MOV AL,M
- OR AL,AL
- JZ CLEX
- CALL SEND_CHAR
- INC BX
- JMPS CLELP
- CLEX: MOV AL,'?' ;TAG LINE WITH A '?' FIELD
- CALL SEND_CHAR
- CALL CRLF ;SPACE DOWN 1 MORE LINE
- JMP EXIT ;..AND RETURN TO CP/M
- ENDIF
-
- ;
- ; OPTIONS INPUT OR NOT SPECIFIED. IF RESET OPTION SPECIFIED, DO IT NOW.
- ;
- CKREST:
- MOV AL,Byte Ptr ROPFLG ;IF RESET FLAG SET, RESET DISK SYSTEM BEFORE
- OR AL,AL ;..STARTING TO UPDATE ALLOCATION VECTORS
- MOV CL,RESET
- JNZ L_3
- CALL CPM
- L_3:
- ;
- ; VALIDATE DRIVE CODE AND USER AREA NUMBERS FROM THE DRIVE TABLE.
- ;
- NOOPT: MOV DX,(Offset DREMSG) ;GET THE DRIVE/USER ERROR MESSAGE
- PUSH DX
- MOV AL,Byte Ptr .FCB ;GET DIRECTORY DRIVE CODE
- DEC AL ;NORMALIZE TO RANGE OF 0-15
- CMP AL,(Offset HIDRV)-(Offset LODRV) ;COMPARE WITH MAXIMUM DRIVES ON-LINE
- JNAE L_4
- JMP ERXIT ;TAKE DRIVE ERROR EXIT IF OUT OF RANGE
- L_4:
- MOV BX,(Offset USRMSG) ;SWITCH TO USER # ERROR MESSAGE
- MOV BP,SP
- XCHG BX,[BP]
- MOV DL,AL ;USE DRIVE CODE AS INDEX INTO TABLE
- MOV DH,0
- MOV BX,(Offset LODRV) ;POINT TO BASE OF DRIVE/USER TABLE
- ADD BX,DX
- MOV AL,M ;GET THE MAXIMUM USER # FOR THIS DRIVE
- AND AL,0FH ;MAKE SURE ITS IN RANGE 0 - 15
- MOV Byte Ptr MAXUSR,AL ;SAVE IT FOR LATER
- MOV BX,(Offset NEWUSR) ;POINT TO THE DIRECTORY USER AREA
- CMP AL,M ;COMPARE IT WITH THE MAXIMUM
- JNB L_5
- JMP ERXIT ;TAKE ERROR EXIT IF USER NUMBER ILLEGAL
- L_5:
- POP DX ;DESTROY ERROR MESSAGE POINTER
- MOV BX,FCB+1 ;POINT TO NAME
- MOV AL,M ;ANY SPECIFIED?
- CMP AL,' '
- JNZ GOTFCB
- ;
- ; NO FCB - MAKE FCB ALL '?'
- ;
- MOV CH,11 ;FN+FT COUNT
- QLOOP: MOV M,'?' ;STORE '?' IN FCB
- LAHF
- INC BX
- SAHF
- DEC CH
- JNZ QLOOP
- GOTFCB: MOV AL,'?' ;FORCE WILD EXTENT
- MOV Byte Ptr .FCB+12,AL
- CALL SETSRC ;SET DMA FOR BDOS MEDIA CHANGE CHECK
- MOV BX,FCB ;POINT TO FCB DRIVE CODE FOR DIRECTORY
- MOV DL,M ;GET THE DRIVE CODE OUT OF THE FCB
- DEC DL ;NORMALIZE DRIVE CODE FOR SELECT
- MOV CL,SELDSK ;SELECT THE DIRECTORY DRIVE TO RETRIEVE
- CALL CPM ;..THE PROPER ALLOCATION VECTOR
- MOV CL,curdpb ;get disk parameter block
- INT 224
- INC BX ;point to block shift
- INC BX
- MOV AL,ES: M ;[AL] = block shift = log2(records/block)
- SUB AL,3 ;[AL] = log2(kbytes/block)
- MOV Byte Ptr blkshf,AL
- INC BX ;point to disk size
- mov al,es: m ;get block mask, and save it
- mov Byte Ptr blkmsk,al
- INC BX
- INC BX
- MOV DL,ES: M
- INC BX
- MOV DH,ES: M
- MOV Word Ptr dsksiz,DX ;dsksiz = blocks/dsk
- ;
- ;
- ; Now get amount used on disk
- ;
- allctd: MOV CL,galloc ;get allocation vector address
- INT 224
- ;
- push ds ;save the data segment at all cost...
- MOV DX,Word Ptr dsksiz ;get blocks/disk
- mov si,bx ;make indirect pointer
- test dl,7 ;big blocks or little blocks?
- jz divlp1
- add dx,8
- divlp1: mov cl,3 ;the great divide...
- shr dx,cl
- mov cx,dx
- mov dl,0
- push es ;trick to get to proper data segment
- pop ds
- cntit: lods ds: m ;nice way to get data to [AL] pointed by 0[BX] from [SI]
- ;...with nifty increment of pointer at [SI]
- mov bx,cx
- mov cx,8 ;scan thru 8 bits for 1's set
- try1: shr al,1
- jnb not1
- inc dx ;got a live one, bump 'used' counter
- not1: loop try1
- mov cx,bx
- loop cntit
- pop ds ;restore to orginal data segment
- ;
- MOV BX,Word Ptr dsksiz ;[BX] = blocks/disk-1, [DX] = blocks used
- inc bx ;bump for actual disk size
- MOV AL,BL ;do a sixteen bit subtract
- SUB AL,DL
- MOV BL,AL
- MOV AL,BH
- SBB AL,DH
- MOV BH,AL ;[BX] = unused blocks
- MOV AL,Byte Ptr blkshf ;now convert from blocks to kilobytes
- OR AL,AL
- shftit: JZ savit
- SHL BX,1
- DEC AL
- JMPS shftit
- ;
- savit: MOV Word Ptr freeby,BX ;[BX] = kbytes unused
- ;
- ;
- ; REENTER HERE ON SUBSEQUENT PASSES WHILE IN THE ALL-USERS MODE
- ;
- SETTBL: MOV BX,Word Ptr dsksiz ;GET DIRECTORY MAXIMUM AGAIN
- LAHF ;DIRECTORY SIZE IS dsksiz+1
- INC BX
- SAHF
- SHL BX,1 ;DOUBLE DIRECTORY SIZE
- MOV DX,(Offset ORDER) ;TO GET SIZE OF ORDER TABLE
- LAHF ;ALLOCATE ORDER TABLE
- ADD BX,DX
- RCR SI,1
- SAHF
- RCL SI,1
- MOV Word Ptr TBLOC,BX ;NAME TABLE BEGINS WHERE ORDER TABLE ENDS
- MOV Word Ptr NEXTT,BX
- XCHG BX,DX
- ;
- ;+++ MAY HAVE TO CHECK FOR AVAILABLE MEMORY HERE +++
- ;
-
- IF UOPT
- MOV AL,Byte Ptr NEWUSR ;GET USER AREA FOR DIRECTORY
- MOV DL,AL
- MOV CL,CURUSR ;GET THE USER FUNCTION
- CALL CPM ;..AND SET NEW USER NUMBER
- ENDIF
-
- ;
- ; LOOK UP THE FCB IN THE DIRECTORY
- ;
- SFIRST: MOV BX,0
- MOV Word Ptr COUNT,BX ;INITIALIZE MATCH COUNTER
- MOV Word Ptr TOTFIL,BX ; " TOTAL FILE COUNTER
- MOV Word Ptr TOTSIZ,BX ; " TOTAL SIZE COUNTER
- CALL SETSRC ;SET DMA FOR DIRECTORY SEARCH
- MOV CL,SEARCH ;GET 'SEARCH FIRST' FUNCTION
- JMPS LOOK ;..AND GO SEARCH FOR 1ST MATCH
- ;
- ; READ MORE DIRECTORY ENTRIES
- ;
- MORDIR: MOV CL,NEXT ;SEARCH NEXT
- LOOK: MOV DX,FCB
- CALL CPM ;READ DIRECTORY ENTRY
- INC AL ;CHECK FOR END (0FFH)
- JNZ L_6
- JMP SPRINT ;IF NO MORE, SORT & PRINT WHAT WE HAVE
- L_6:
- ;
- ; POINT TO DIRECTORY ENTRY
- ;
- SOME: DEC AL ;UNDO PREV 'INR A'
- AND AL,3 ;MAKE MODULUS 4
- ADD AL,AL ;MULTIPLY...
- ADD AL,AL ;..BY 32 BECAUSE
- ADD AL,AL ;..EACH DIRECTORY
- ADD AL,AL ;..ENTRY IS 32
- ADD AL,AL ;..BYTES LONG
- MOV BX,BASE+81H ;POINT TO BUFFER
- ;
- ;SKIP TO FN/FT
- ;
- ADD AL,BL ;POINT TO ENTRY
- ADD AL,9 ;POINT TO SYS BYTE
- MOV BL,AL ;SAVE (CAN'T CARRY TO H)
-
- IF SOPT
- MOV AL,Byte Ptr SOPFLG ;DID USER REQUEST SYS FILES?
- OR AL,AL
- JZ SYSFOK
- ENDIF
-
- MOV AL,M ;GET SYS BYTE
- OR AL,AL ;CHECK BIT 7
- JS MORDIR ;SKIP THAT FILE
- SYSFOK: MOV AL,BL ;GO BACK NOW
- SUB AL,10 ;BACK TO USER NUMBER (ALLOC FLAG)
- MOV BL,AL ;HL POINTS TO ENTRY NOW
- MOV AL,Byte Ptr NEWUSR ;GET CURRENT USER
- CMP AL,M
- JNZ MORDIR ;IGNORE IF DIFFERENT
- INC BX
- ;
- ; MOVE ENTRY TO TABLE
- ;
- XCHG BX,DX ;ENTRY TO DE
- MOV BX,Word Ptr NEXTT ;NEXT TABLE ENTRY TO HL
- MOV CH,12 ;ENTRY LENGTH (NAME, TYPE, EXTENT)
- TMOVE: MOV SI,DX ;GET ENTRY CHAR
- MOV AL,[SI]
- AND AL,7FH ;REMOVE ATTRIBUTES
- MOV M,AL ;STORE IN TABLE
- LAHF
- INC DX
- SAHF
- LAHF
- INC BX
- SAHF
- DEC CH ;MORE?
- JNZ TMOVE
- LAHF
- INC DX
- SAHF
- LAHF ;POINT TO SECTOR COUNT
- INC DX
- SAHF
- MOV SI,DX ;GET IT
- MOV AL,[SI]
- MOV M,AL ;STORE IN TABLE
- LAHF
- INC BX
- SAHF
- MOV Word Ptr NEXTT,BX ;SAVE UPDATED TABLE ADDR
- XCHG BX,DX
- MOV BX,Word Ptr COUNT ;BUMP THE # OF MATCHES MADE
- LAHF
- INC BX
- SAHF
- MOV Word Ptr COUNT,BX
- MOV BX,13 ;SIZE OF NEXT ENTRY
- LAHF
- ADD BX,DX
- RCR SI,1
- SAHF
- RCL SI,1
- XCHG BX,DX ;FUTURE NEXTT IS IN DE
- JMP MORDIR ;ATTEMPT TO GET NEXT DIRECTORY ENTRY
- ;
- ; SORT AND PRINT
- ;
- SPRINT:
- CALL SETFOP ;RETURN TO FILE OUTPUT DMA & USER #
- MOV BX,Word Ptr COUNT ;GET FILE NAME COUNT
- MOV AL,BL
- OR AL,BH ;ANY FOUND?
- JNZ L_7
- JMP PRTOTL ;EXIT IF NO FILES FOUND
- L_7:
- PUSH BX ;SAVE FILE COUNT
- MOV Byte Ptr SUPSPC,AL ;ENABLE LEADING ZERO SUPPRESSION
- ;
- ; INITIALIZE THE ORDER TABLE
- ;
- MOV BX,Word Ptr TBLOC ;GET START OF NAME TABLE
- XCHG BX,DX ;INTO DE
- MOV BX,(Offset ORDER) ;POINT TO ORDER TABLE
- MOV CX,13 ;ENTRY LENGTH
- BLDORD: MOV M,DL ;SAVE LOW ORDER ADDRESS
- INC BX
- MOV M,DH ;SAVE HIGH ORDER ADDRESS
- INC BX
- XCHG BX,DX ;TABLE ADDR TO HL
- ADD BX,CX ;POINT TO NEXT ENTRY
- XCHG BX,DX
- MOV BP,SP ;SAVE TBL ADDR, FETCH LOOP COUNTER
- XCHG BX,[BP]
- DEC BX ;COUNT DOWN LOOP
- MOV AL,BL
- OR AL,BH ;MORE?
- MOV BP,SP ;(RESTORE TBL ADDR, SAVE COUNTER)
- XCHG BX,[BP]
- JNZ BLDORD ;YES, GO DO ANOTHER ONE
- POP BX ;CLEAN LOOP COUNTER OFF STACK
- MOV BX,Word Ptr COUNT ;GET COUNT
- MOV Word Ptr SCOUNT,BX ;SAVE AS # TO SORT
- DEC BX ;ONLY 1 ENTRY?
- MOV AL,BL
- OR AL,BH
- JNZ L_8
- JMP DONE ;YES, SO SKIP SORT
- L_8:
- ;
- ; THIS SORT ROUTINE IS ADAPTED FROM SOFTWARE TOOLS
- ; BY KERNIGAN AND PLAUGHER.
- ;
- SORT: MOV BX,Word Ptr SCOUNT ;NUMBER OF ENTRIES
- SORT0: OR AL,AL ;CLEAR CARRY
- MOV AL,BH ;GAP=GAP/2
- RCR AL,1
- MOV BH,AL
- MOV AL,BL
- RCR AL,1
- MOV BL,AL
- OR AL,BH ;IS IT ZERO?
- JNZ L_9
- JMP DONE ;THEN NONE LEFT
- L_9:
- MOV AL,BL ;MAKE GAP ODD
- OR AL,01
- MOV BL,AL
- MOV Word Ptr GAP,BX
- INC BX ;I=GAP+1
- SORT2: MOV Word Ptr I,BX
- XCHG BX,DX
- MOV BX,Word Ptr GAP
- MOV AL,DL ;J=I-GAP
- SUB AL,BL
- MOV BL,AL
- MOV AL,DH
- SBB AL,BH
- MOV BH,AL
- SORT3: MOV Word Ptr J,BX
- XCHG BX,DX
- MOV BX,Word Ptr GAP ;JGAP=J+GAP
- LAHF
- ADD BX,DX
- SAHF
- MOV Word Ptr JGAP,BX
- MOV AL,12 ;COMPARE 12 CHARS
- CALL COMPARE ;COMPARE (J) AND (JG)
- JNS SORT5 ;IF A(J)<=A(JG)
- MOV BX,Word Ptr J
- XCHG BX,DX
- MOV BX,Word Ptr JGAP
- CALL SWAP ;EXCHANGE A(J) AND A(JG)
- MOV BX,Word Ptr J ;J=J-GAP
- XCHG BX,DX
- MOV BX,Word Ptr GAP
- MOV AL,DL
- SUB AL,BL
- MOV BL,AL
- MOV AL,DH
- SBB AL,BH
- MOV BH,AL
- JS SORT5 ;IF J>0 GOTO SORT3
- OR AL,BL ;CHECK FOR ZERO
- JZ SORT5
- JMPS SORT3
- SORT5: MOV BX,Word Ptr SCOUNT ;FOR LATER
- XCHG BX,DX
- MOV BX,Word Ptr I ;I=I+1
- INC BX
- MOV AL,DL ;IF I<=N GOTO SORT2
- SUB AL,BL
- MOV AL,DH
- SBB AL,BH
- JS L_10
- JMP SORT2
- L_10:
- MOV BX,Word Ptr GAP
- JMP SORT0
- ;
- ; SORT IS ALL DONE - PRINT ENTRIES
- ;
- DONE: MOV AL,Byte Ptr FOPFLG
- OR AL,AL
- JZ L_11
- JMP NOOUT ;IF FILE OUTPUT, FALL THROUGH WITH A=0
- L_11:
- ;
- ; 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.
- ;
- MOV BX,(Offset OPNFLG) ;POINT TO OUTPUT FILE OPEN FLAG
- CMP AL,M ;A=0, SET Z IF OPNFLG=0 ALSO
- JZ L_12
- JMP NOOUT ;IF OPNFLG NOT ZERO, SKIP OPEN
- L_12:
- DEC M ;ELSE, MAKE OPNFLG NOT ZERO AND OPEN
- ;
- ; FIRST PASS ON FILE APPEND - PREPARE XDIR.DIR TO RECEIVE NEW OR APPENDED
- ; OUTPUT.
- ;
- MOV DX,(Offset OUTFCB) ;DOES OUTPUT FILE ALREADY EXIST?
- MOV CL,SEARCH
- CALL CPM
- INC AL
- JNZ OPENIT ;IF IT DOES, THEN OPEN IT FOR PROCESSING
- MOV CL,MAKE ;OTHERWISE, CREATE THE OUTPUT FILE
- CALL CPM
- INC AL
- JZ L_13
- JMP NOOUT ;CONTINUE IF OPEN SUCCESSFUL
- L_13:
- ;
- ; 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: MOV CL,OPEN ;OPEN 1ST EXTENT OF OUTPUT FILE
- CALL CPM
- INC AL
- JZ OPNERR ;BAD DEAL IF 1ST WON'T OPEN
- OPNMOR: MOV AL,Byte Ptr OUTFCB+15
- CMP AL,128
- JB LSTEXT ;IF RC<128, THIS IS LAST EXTENT
- MOV BX,(Offset OUTFCB)+12
- INC M ;ELSE, BUMP TO NEXT EXTENT
- MOV CL,OPEN ;..AND TRY TO OPEN IT
- CALL CPM
- INC AL
- JNZ OPNMOR ;CONTINUE OPENING EXTENTS TIL NO MORE
- DEC M ;THEN, REOPEN PRECEDING EXTENT
- MOV CL,OPEN
- CALL CPM
- MOV AL,Byte Ptr 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: OR AL,AL ;IS THIS EXTENT EMPTY?
- JZ NOOUT ;IF SO, THEN WE'RE STARTING A CLEAN SLATE
- DEC AL ;NORMALIZE RECORD COUNT
- MOV Byte Ptr OUTFCB+32,AL ;SET RECORD NUMBER TO READ
- MOV CL,READ ;..AND READ LAST RECORD OF FILE
- CALL CPM
- OR AL,AL ;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: MOV BX,(Offset OUTBUF) ;POINT TO START OF OUTPUT BUFFER
- MOV CH,128 ;GET LENGTH OF OUTPUT BUFFER
- SCAN: MOV AL,M
- CMP AL,'Z'-40H ;HAVE WE FOUND END OF FILE?
- JZ RESCR ;IF SO, SAVE POINTERS AND RESET CR
- LAHF
- INC BX
- SAHF
- DEC CH
- 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 XDIR.DIR FILE.
- ;
- RESCR: PUSH BX ;SAVE EOF BUFFER POINTER
- PUSH CX ;SAVE EOF BUFFER REMAINING
- MOV BX,(Offset OUTFCB)+32 ;GET CURRENT RECORD AGAIN
- DEC M ;DOCK IT
- JNS SAMEXT ;IF CR >=0, WE'RE STILL IN SAME EXTENT
- MOV BX,(Offset OUTFCB)+12 ;ELSE, MOVE TO PREVIOUS EXTENT
- DEC M
- MOV CL,OPEN ;THEN, REOPEN THE PREVIOUS EXTENT
- CALL CPM
- INC AL
- JZ APERR ;APPEND POSITION ERROR IF WE CAN'T REOPEN
- MOV AL,Byte Ptr OUTFCB+15 ;ELSE, POSITION TO LAST RECORD OF EXTENT
- DEC AL
- MOV Byte Ptr OUTFCB+32,AL
- SAMEXT: POP AX ;RECALL WHERE EOF IS IN BUFFER
- XCHG AL,AH
- SAHF
- MOV Byte Ptr BUFCNT,AL ;..AND SET BUFFER COUNTER
- POP BX ;RECALL NEXT BUFFER POINTER
- MOV Word Ptr BUFPNT,BX ;.. AND SET POINTER FOR FIRST ADDITION
- NOOUT: MOV BX,(Offset ORDER) ;INITIALIZE ORDER TABLE POINTER
- MOV Word Ptr NEXTT,BX
- JMP NEWLIN ;START NEW LINE AND OUTPUT THE FILES
- ;
- ; OUTPUT THE DIRECTORY FILES WE'VE MATCHED.
- ;
- ENTRY: MOV BX,Word Ptr COUNT
- DEC BX ;DOCK FILE COUNT
- MOV Word Ptr COUNT,BX
- MOV AL,BH ;IS THIS THE LAST FILE?
- OR AL,BL
- 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 CX ;SAVE NPL
- CALL CKABRT ;CHECK FOR ABORT CODE FROM KEYBOARD
- MOV BX,Word Ptr NEXTT
- MOV AL,11
- CALL COMPR ;DOES THIS ENTRY MATCH NEXT ONE?
- POP CX ;RECALL NPL
- JNZ OKPRNT ;NO, PRINT IT
- INC BX
- INC BX ;SKIP SINCE HIGHEST EXTENT COMES LAST IN LIST
- MOV Word Ptr NEXTT,BX
- JMPS ENTRY ;LOOP BACK FOR NEXT LOWEST EXTENT
- ;
- ; VALID ENTRY OBTAINED - SPIT IT OUT.
- ;
- OKPRNT: MOV BX,Word Ptr NEXTT ;GET ORDER TABLE POINTER
- MOV DL,M ;GET LOW ORDER ADDRESS
- LAHF
- INC BX
- SAHF
- MOV DH,M ;GET HIGH ORDER ADDRESS
- LAHF
- INC BX
- SAHF
- MOV Word Ptr NEXTT,BX ;SAVE UPDATED TABLE POINTER
- XCHG BX,DX ;TABLE ENTRY TO HL
- MOV CH,8 ;FILE NAME LENGTH
- CALL TYPEIT ;TYPE FILENAME
- MOV AL,'.' ;PERIOD AFTER FN
- CALL SEND_CHAR
- MOV CH,3 ;DISPLAY 3 CHARACTERS OF FILETYPE
- CALL TYPEIT
- ;
- ; COMPUTE THE SIZE OF THE FILE AND UPDATE OUR SUMMARY DATUM.
- ;
- MOV DL,M ;GET EXTENT #
- MOV DH,0
- INC BX
- MOV AL,M ;GET SECTOR COUNT OF LAST EXTENT
- XCHG BX,DX
- SHL BX,1 ;# OF EXTENTS TIMES 16K
- SHL BX,1
- SHL BX,1
- SHL BX,1
- XCHG BX,DX ;SAVE IN DE
- MOV BX,(Offset BLKMSK)
- ADD AL,M ;ROUND LAST EXTENT TO BLOCK SIZE
- ROR AL,1
- ROR AL,1 ;CONVERT FROM SECTORS TO K
- ROR AL,1
- AND AL,1FH
- MOV BL,AL ;ADD TO TOTAL K
- MOV BH,0
- ADD BX,DX
- MOV AL,Byte Ptr BLKMSK ;GET SECTORS/BLK-1
- ROR AL,1
- ROR AL,1 ;CONVERT TO K/BLK
- ROR AL,1
- AND AL,1FH
- NOT AL ;USE TO FINISH ROUNDING
- AND AL,BL
- MOV BL,AL
- XCHG BX,DX ;SAVE FILE SIZE IN DE
- MOV BX,Word Ptr TOTSIZ
- LAHF ;ADD TO TOTAL USED
- ADD BX,DX
- RCR SI,1
- SAHF
- RCL SI,1
- MOV Word Ptr TOTSIZ,BX
- MOV BX,Word Ptr TOTFIL ;INCREMENT FILE COUNT
- LAHF
- INC BX
- SAHF
- MOV Word Ptr TOTFIL,BX
- XCHG BX,DX ;GET BACK FILE SIZE
- ;
- ; IF REPORT SIZE ENABLED, OUTPUT THE SIZE OF THE INDIVIDUAL FILE.
- ;IF FILE SIZE REPORT WANTED
- ;
- CALL DECPRT ;..GO PRINT IT
- MOV AL,'k' ;..AND FOLLOW WITH K SIZE
- CALL SEND_CHAR
- ;
- ; ONE FILE OUTPUT - TEST TO SEE IF WE HAVE TO OUTPUT ANOTHER ONE.
- ;
- MOV BX,Word Ptr COUNT ;GET CURRENT FILE COUNTER AND TEST IT
- MOV AL,BH
- OR AL,BL
- JNZ L_14
- JMP PRTOTL ;IF NO MORE FILES, EXIT TO SUMMARY OUTPUT
- L_14:
- ;
- ; AT LEAST ONE MORE FILE TO OUTPUT - CAN WE PUT IT ON THE CURRENT LINE?
- ;
- DEC CL
- LAHF
- XCHG AL,AH
- PUSH AX
- JZ L_15
- CALL FENCE ;IF ROOM LEFT, OUTPUT THE FENCE CHARACTER
- L_15:
- POP AX
- XCHG AL,AH
- SAHF
- JZ L_16
- JMP ENTRY ;.. AND GO OUTPUT ANOTHER FILE
- L_16:
- ;
- ; CURRENT LINE FULL, START A NEW ONE.
- ;
- NEWLIN: MOV CL,NPL ;RESET NAMES PER LINE COUNTER
- CALL CRLF ;SPACE DOWN TO NEXT LINE
- MOV AL,Byte Ptr .FCB ;.. PRECEDE NEW LINE WITH DRIVE NAME
- ADD AL,'A'-1
- CALL SEND_CHAR
- MOV AL,':' ;TAG DRIVE LETTER WITH A COLON AND SPACE
- CALL SEND_CHAR
- JMP ENTRY ;GO BACK AND OUTPUT ANOTHER FILE
- ;
- ;IF REPORTING USER NUMBERS
- ;
- ; PRINT HL IN DECIMAL WITH LEADING ZERO SUPPRESSION
- ;
- DECPRT: SUB AL,AL ;CLEAR LEADING ZERO FLAG
- MOV Byte Ptr LZFLG,AL
- MOV DX,-1000 ;PRINT 1000'S DIGIT
- CALL DIGIT
- MOV DX,-100 ;ETC.
- CALL DIGIT
- MOV DX,-10
- CALL DIGIT
- MOV AL,'0' ;GET 1'S DIGIT
- ADD AL,BL
- JMP SEND_CHAR
- ;
- DIGIT: MOV CH,'0' ;START OFF WITH ASCII 0
- DIGLP: PUSH BX ;SAVE CURRENT REMAINDER
- ADD BX,DX ;SUBTRACT
- JNB DIGEX ;QUIT ON OVERFLOW
- POP AX ;THROW AWAY REMAINDER
- INC CH ;BUMP DIGIT
- JMPS DIGLP ;LOOP BACK
- DIGEX: POP BX ;RESTORE POINTER
- MOV AL,CH
- CMP AL,'0' ;ZERO DIGIT?
- JNZ DIGNZ ;NO, TYPE IT
- MOV AL,Byte Ptr LZFLG ;LEADING ZERO?
- OR AL,AL
- MOV AL,'0'
- JZ L_17
- JMP SEND_CHAR ;PRINT DIGIT
- L_17:
- MOV AL,Byte Ptr SUPSPC ;GET SPACE SUPPRESSION FLAG
- OR AL,AL ;SEE IF PRINTING FILE TOTALS
- JNZ L_18
- RET ;YES, DON'T GIVE LEADING SPACES
- L_18:
- JMP SPACE ;LEADING ZERO...PRINT SPACE
- DIGNZ: MOV Byte Ptr LZFLG,AL ;SET LEADING ZERO FLAG SO NEXT ZERO PRINTS
- JMP SEND_CHAR ;AND PRINT DIGIT
- ;
- ; SHOW TOTAL SPACE AND FILES USED
- ;
- PRTOTL: XOR AL,AL ;GET A ZERO TO...
- MOV Byte Ptr SUPSPC,AL ;SUPPRESS LEADING SPACES IN TOTALS
- MOV BX,Word Ptr TOTFIL ;HOW MANY FILES DID WE MATCH?
- MOV AL,BH
- OR AL,BL
- JZ NXTUSR ;SKIP THE SUMMARY IF WE DIDN'T FIND ANY
- PUSH BX ;SAVE TOTFIL
- MOV Byte Ptr FNDFLG,AL ;SET FILE FOUND FLAG
- MOV DX,(Offset TOTMS1) ;PRINT [CR,LF,LF]"DRIVE "
- CALL PRINT
- MOV AL,Byte Ptr .FCB
- ADD AL,'A'-1
- CALL SEND_CHAR ;OUTPUT THE DRIVE CODE
- MOV DX,(Offset TOTMS2) ;PRINT ", USER "
- CALL PRINT
- CALL TYPUSR ;OUTPUT THE USER NUMBER
- MOV DX,(Offset TOTMS3) ;PRINT " CONTAINS "
- CALL PRINT
- MOV BX,Word Ptr TOTSIZ ;PRINT TOTAL K USED BY FILES MATCHED
- CALL DECPRT
- MOV DX,(Offset TOTMS4) ;PRINT "K IN "
- CALL PRINT
- POP BX ;RECALL TOTFIL
- CALL DECPRT ;PRINT NUMBER OF FILES MATCHED
- MOV DX,(Offset 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.
- ;
-
- IF AOPT
- NXTUSR: ;IF ALL USERS OPTION ENABLED
- MOV AL,Byte Ptr AOPFLG ;IF NOT ALL USERS MODE - SKIP NEXT
- OR AL,AL
- JNZ GOCLZ
- CALL CKABRT ;CHECK FOR USER ABORT FIRST
- MOV AL,Byte Ptr MAXUSR ;NO ABORT - GET MAXIMUM USER NUMBER
- MOV BX,(Offset NEWUSR) ;BUMP DIRECTORY USER NUMBER
- INC M
- CMP AL,M ;DOES NEXT USER # EXCEED MAXIMUM?
- JNAE L_19
- JMP SETTBL ;CONTINUE IF MORE USER AREAS TO GO
- L_19:
- ENDIF
-
- ;
- ;IF MULTI-DISK OPTION ENABLED
-
- IF AOPT AND DOPT
- MOV AL,Byte Ptr BASUSR ;RESET BASE USER NUMBER FOR THE
- MOV M,AL ;..NEXT DIRECTORY SEARCH
- ENDIF
-
- ;
- ; WE'VE FINISHED ALL OF OUR OUTPUTTING. FLUSH THE REMAINDER OF THE
- ; OUTPUT BUFFER AND CLOSE THE FILE BEFORE GOING TO EXIT ROUTINE.
- ;
-
- IF FOPT
- GOCLZ:
- MOV BX,(Offset OPNFLG) ;GET FILE OPEN STATUS THEN RESET FLAG TO
- MOV AL,M ;..FORCE REOPEN ON NEXT PASS
- MOV M,0
- OR AL,AL
- JZ NXTDSK ;SKIP CLOSING XDIR.DIR IF IT WASN'T OPENED
- MOV BX,(Offset BUFCNT)
- MOV AL,M ;RETRIEVE # OF UNFLUSHED CHARACTERS IN BUFFER
- MOV M,128 ;FORCE BUFCNT TO EMPTY STATUS FOR NEXT DRIVE
- OR AL,AL ;IF BUFCNT=128, BUFFER EMPTY SO SET SIGN BIT
- JS CLOZE ;CLOSE XDIR.DIR IF BUFFER IS EMPTY
- JZ FLUSH ;WRITE LAST RECORD TO XDIR.DIR IF BUFFER FULL
- MOV BX,Word Ptr BUFPNT ;OTHERWISE, PAD UNUSED BUFFER WITH CTRL-ZS
- PUTAGN: MOV M,'Z'-40H
- LAHF
- INC BX
- SAHF
- DEC AL
- JNZ PUTAGN ;CONTINUE PADDING TIL BUFFER FILLED OUT
- FLUSH: MOV DX,(Offset OUTFCB) ;FLUSH THE LAST OUTPUT BUFFER
- MOV CL,WRITE
- CALL CPM
- OR AL,AL
- JZ L_20
- JMP WRTERR
- L_20:
- CLOZE: MOV DX,(Offset OUTFCB) ;CLOSE THE OUTPUT FILE
- MOV CL,CLOSE
- CALL CPM
- ENDIF
-
- ;
- ; 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: MOV BX,(Offset FNDFLG) ;GET FILE FOUND FLAG
- MOV AL,M
- MOV M,0 ;CLEAR FILE FOUND FLAG FOR NEXT DRIVE
- OR AL,AL
- JNZ NDSK ;CONTINUE IF AT LEAST 1 FILE FOUND
- ;
- ;IF FILE OUTPUT ENABLED, DISABLE TEMPORARILY
- ;
-
- IF FOPT
- MOV BX,(Offset FOPFLG)
- DEC M
- PUSH BX
- ENDIF
-
- MOV AL,Byte Ptr .FCB ;STASH ASCII DIRECTORY DRIVE IN NO FILE MSG
- ADD AL,'A'-1
- MOV Byte Ptr NOFMS2,AL
- MOV DX,(Offset NOFMS1) ;PRINT "NO FILE ON ? - "
- CALL PRINT
- CALL PRTFRE ;TAG WITH FREE MESSAGE
- ;
- ;RESTORE ORIGINAL FILE OUTPUT MODE
- ;
-
- IF FOPT
- POP BX
- INC M
- ENDIF
-
- IF DOPT
- NDSK: ;IF MULTI-DISK OPTION ENABLED
- MOV AL,Byte Ptr DOPFLG ;IF MULTI-DISK NOT SELECTED - SKIP NEXT
- OR AL,AL
- JZ L_21
- JMP EXIT
- L_21:
- CALL CKABRT ;CHECK FOR USER ABORT FIRST
- MOV AL,(Offset HIDRV)-(Offset LODRV) ;GET MAXIMUM DRIVE CODE TO SEARCH
- MOV BX,FCB ;BUMP DIRECTORY FCB DRIVE CODE
- INC M
- CMP AL,M ;DOES NEXT DISK EXCEED MAXIMUM?
- JNAE L_22
- JMP NOOPT ;SEARCH NEXT DISK IF NOT
- L_22:
- ENDIF
-
- JMP EXIT ;ALL DONE - EXIT TO CCP
- ;
- ; PRINT THE USER NUMBER OF THE DIRECTORY IN DECIMAL
- ;
- TYPUSR:
- MOV AL,Byte Ptr NEWUSR
- CMP AL,10 ;IF USER NO. > 9 PRINT LEADING 1
- JB DUX
- MOV AL,'1'
- CALL SEND_CHAR
- MOV AL,Byte Ptr NEWUSR ;PRINT LOW DIGIT OF USER NO.
- SUB AL,10
- DUX: ADD AL,'0'
- JMPS SEND_CHAR
- ;
- ; FORCE NEW LINE ON VIDEO AND CHECK FOR PAGE PAUSE
- ;
- CRLF: MOV AL,0DH ;SEND CR
- CALL SEND_CHAR
- MOV AL,0AH ;SEND LF
- JMPS SEND_CHAR ;EXIT TO CALLER FROM TYPE
- ;
- ; SEPARATE THE DIRECTORY OUTPUT ON A LINE WITH A SPACE, THE DELIMITER,
- ; FOLLOWED BY ANOTHER SPACE.
- ;
- FENCE: CALL SPACE
- MOV AL,DELIM ;FENCE CHARACTER
- FPAD: CALL SEND_CHAR ;PRINT IT, FALL INTO SPACE
- SPACE: MOV AL,' ' ;FALL THROUGH TO TYPE
- ;
- ; OUTPUT CHARACTER IN A TO CONSOLE, AND OPTIONALLY TO PRINTER AND/OR
- ; THE OUTPUT FILE.
- ;
- SEND_CHAR:
- PUSH CX
- PUSH DX
- PUSH BX
-
- IF FOPT OR POPT OR PGPAWZ
- LAHF ;SAVE THE CHARACTER TO OUTPUT
- XCHG AL,AH
- PUSH AX
- XCHG AL,AH
- ENDIF
-
- CALL TYPE1 ;SEND IT TO CONSOLE
-
- IF FOPT OR POPT OR PGPAWZ
- POP AX ;RESTORE THE OUTPUT CHARACTER
- XCHG AL,AH
- AND AL,7FH ;STRIP PARITY BIT ON CHARACTER
- ENDIF
-
- ;
- ; TEST FILE OUTPUT MODE AND SKIP TO PAGE PAUSE TEST IF NOT ACTIVE.
- ;
-
- IF FOPT
- MOV CH,AL ;SAVE STRIPPED CHARACTER TO B
- MOV AL,Byte Ptr FOPFLG ;IS FILE OUTPUT ACTIVE?
- OR AL,AL
- 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.
- ;
- MOV BX,Word Ptr BUFPNT ;GET CURRENT BUFFER POINTER
- MOV AL,Byte Ptr BUFCNT ;GET BUFFER CAPACITY REMAINING
- OR AL,AL
- JNZ PUTBUF ;CONTINUE IF BUFFER NOT FULL
- MOV DX,(Offset OUTFCB) ;OTHERWISE, WRITE THE CURRENT BUFFER OUT
- MOV CL,WRITE
- CALL CPM ;(NOTE CALL MUST SAVE CHARACTER IN B)
- OR AL,AL
- JZ L_23
- JMP WRTERR ;TAKE WRITE ERROR EXIT IF DISK FULL OR R/O
- L_23:
- MOV BX,(Offset OUTBUF) ;RESET BUFFER POINTER
- MOV AL,128 ;RESET BUFFER CAPACITY
- PUTBUF: MOV M,CH ;SHOVE CHARACTER TO NEXT BUFFER POSITION
- INC BX ;BUMP BUFFER POINTER
- MOV Word Ptr BUFPNT,BX ;.. AND SAVE IT
- DEC AL ;DOCK COUNT OF CHARACTERS LEFT IN BUFFER
- MOV Byte Ptr BUFCNT,AL ;..AND SAVE IT
- NOWRIT: MOV AL,CH ;RECALL STRIPPED CHARACTER
- ENDIF
-
- ;
- ;IF PRINTER OPTION
- ;
-
- IF POPT
- MOV DL,AL ;SETUP LIST OUTPUT CALL
- MOV CL,5
- MOV AL,Byte Ptr POPFLG ;TEST PRINTER FLAG
- OR AL,AL
- JNZ L_24
- CALL CPM ;PRINT CHARACTER IF FLAG TRUE
- L_24:
- MOV AL,DL ;RECALL CHARACTER
- ENDIF
-
-
- IF PGPAWZ
- CMP AL,0AH ;DO WE HAVE A LF?
- JNZ TYPRET ;EXIT IF NOT
- ENDIF
-
- IF NOPT AND PGPAWZ
- MOV AL,Byte Ptr NOPFLG ;IS THE PAGE PAUSE FUNCTION DISABLED?
- OR AL,AL
- JZ TYPRET ;EXIT IF SO
- ENDIF
-
- IF PGPAWZ
- MOV AL,Byte Ptr LINCNT ;GET LINE COUNT
- INC AL ;BUMP IT
- CMP AL,LPS ;ARE WE AT THE END OF THE SCREEN?
- JB NOTEOS ;SKIP IF NOT
- MOV DX,(Offset EOSMSG) ;ELSE, DISPLAY PAUSE MESSAGE
- MOV CL,9 ;..WITHOUT CHECKING FOR LFS
- INT 224
- CALL CINPUT ;WAIT FOR CHARACTER
- CMP AL,'C'-40H
- JNZ L_25
- JMP EXIT ;ABORT ON CTRL-C
- L_25:
- XOR AL,AL ;RESET LINE COUNT
- NOTEOS: MOV Byte Ptr LINCNT,AL ;SAVE NEW LINE COUNT
- ENDIF
-
- TYPRET: POP BX ;EXIT FROM TYPE
- POP DX
- POP CX
- RET
- ;
- ; OUTPUT CHARACTER
- ;
- TYPE1: MOV DL,AL ;GET CHARACTER INTO BDOS ENTRY REGISTER
- MOV CL,WRCHR
- INT 224 ;CALL CONOUT VIA THE BDOS
- RET
- ;
- ; PRINT A STRING AT HL OF LENGTH B
- ;
- TYPEIT: MOV AL,M
- CALL SEND_CHAR
- LAHF
- INC BX
- SAHF
- DEC CH
- JNZ TYPEIT
- RET
- ;
- ; PRINT STRING TERMINATED WITH LAST BYTE HIGH ON CONSOLE.
- ;
- PRINT: MOV SI,DX
- MOV AL,[SI]
- LAHF
- XCHG AL,AH
- PUSH AX
- XCHG AL,AH
- AND AL,7FH
- CALL SEND_CHAR
- POP AX
- XCHG AL,AH
- OR AL,AL
- JNS L_26
- RET
- L_26:
- LAHF
- INC DX
- SAHF
- JMPS PRINT
- ;
- ; FETCH CHARACTER FROM CONSOLE (WITHOUT ECHO)
- ;
- CINPUT: MOV Byte Ptr FUNC,3 ;bios console input function
- MOV Word Ptr BIOS_DESC,CX ;pass disk number to bios descriptor
- MOV Word Ptr BIOS_DESC+2,0 ;fill remaining descriptor (DX) zero
- MOV DX,(Offset FUNC) ;point to function parameter block
- MOV CL,50 ;direct bios call
- INT 224 ;do it, to it...
- AND AL,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: MOV Byte Ptr FUNC,2 ;bios console status function
- MOV Word Ptr BIOS_DESC,CX ;pass disk number to bios descriptor
- MOV Word Ptr BIOS_DESC+2,0 ;fill remaining descriptor (DX) zero
- MOV DX,(Offset FUNC) ;point to function parameter block
- MOV CL,50 ;direct bios call
- INT 224 ;do it, to it...
- OR AL,AL
- JNZ L_27
- RET ;NO, RETURN TO CALLER
- L_27:
- CALL CINPUT ;GET CHARACTER
- CMP AL,'C'-40H ;CTRL-C?
- JNZ L_28
- JMP EXIT ;IF CTRL-C THEN QUIT
- L_28:
- CMP AL,'S'-40H ;CTRL-S?
- JZ L_29
- RET ;NO, RETURN TO CALLER
- L_29:
- CALL CINPUT ;YES, WAIT FOR ANOTHER CHAR.
- CMP AL,'C'-40H ;MIGHT BE CTRL-C
- JNZ L_30
- JMP EXIT ;EXIT IF CTRL-C, ELSE FALL THRU AND CONTINUE
- L_30:
- RET
- ;
- ; ENTRY TO BDOS SAVING ALL EXTENDED REGISTERS
- ;
- CPM: PUSH CX
- PUSH DX
- PUSH BX
- INT 224
- POP BX
- POP DX
- POP CX
- RET
- ;
- ; FOR FILE OUTPUT MODE, RETURN TO OLD USER AREA AND SET DMA FOR
- ; THE FILE OUTPUT BUFFER.
- ;
-
- IF UOPT OR AOPT
- SETFOP:
- MOV AL,Byte Ptr OLDUSR ;GET USER NUMBER AT STARTUP
- MOV DL,AL
- MOV CL,CURUSR
- CALL CPM ;RESET THE OLD USER NUMBER IF CP/M 2
- ENDIF
-
- IF FOPT
- MOV DX,(Offset OUTBUF) ;MOVE DMA FROM SEARCH BUFFER INTO THE
- JMPS SET2 ;..OUTPUT BUFFER
- ENDIF
-
- RET
- ;
- ; MOVE DISK BUFFER DMA TO DEFAULT BUFFER FOR DIRECTORY SEARCH OPERATIONS
- ; AND BDOS MEDIA CHANGE ROUTINES.
- ;
- SETSRC: MOV DX,BASE+80H
- SET2: MOV CL,SETDMA
- JMPS CPM
- ;
- ; PRINT THE AMOUNT OF FREE SPACE REMAINING ON THE SELECTED DRIVE
- ;
- PRTFRE: MOV BX,Word Ptr FREEBY ;GET SPACE LEFT BEFORE ADDING TO MASTER.DIR
- CALL DECPRT ;PRINT K FREE
- MOV DX,(Offset TOTMS6) ;PRINT " FREE."
- JMP PRINT
- ;
- ; COMPARE ROUTINE FOR SORT
- ;
- COMPR: PUSH BX ;SAVE TABLE ADDR
- MOV DL,M ;LOAD LOW ORDER
- INC BX
- MOV DH,M ;LOAD HIGH ORDER
- INC BX
- MOV CL,M
- INC BX
- MOV CH,M
- ;
- ; BC, DE NOW POINT TO ENTRIES TO BE COMPARED
- ;
- XCHG BX,DX
- MOV DL,AL ;GET COUNT
- CMPLP: MOV SI,CX
- MOV AL,[SI]
- CMP AL,M
- LAHF
- INC BX
- SAHF
- LAHF
- INC CX
- SAHF
- JNZ NOTEQL ;QUIT ON MISMATCH
- DEC DL ;OR END OF COUNT
- JNZ CMPLP
- NOTEQL: POP BX
- RET ;COND CODE TELLS ALL
- ;
- ; SWAP ENTRIES IN THE ORDER TABLE
- ;
- SWAP: MOV CX,(Offset ORDER)-2 ;TABLE BASE
- SHL BX,1 ;*2
- LAHF ;+ BASE
- ADD BX,CX
- SAHF
- XCHG BX,DX
- SHL BX,1 ;*2
- LAHF ;+ BASE
- ADD BX,CX
- RCR SI,1
- SAHF
- RCL SI,1
- MOV CL,M
- MOV SI,DX
- MOV AL,[SI]
- XCHG BX,DX
- MOV M,CL
- MOV SI,DX
- MOV [SI],AL
- LAHF
- INC BX
- SAHF
- LAHF
- INC DX
- SAHF
- MOV CL,M
- MOV SI,DX
- MOV AL,[SI]
- XCHG BX,DX
- MOV M,CL
- MOV SI,DX
- MOV [SI],AL
- RET
- ;
- ; NEW COMPARE ROUTINE
- ;
- COMPARE:MOV CX,(Offset ORDER)-2
- SHL BX,1
- ADD BX,CX
- XCHG BX,DX
- SHL BX,1
- ADD BX,CX
- XCHG BX,DX
- MOV CL,M
- INC BX
- MOV CH,M
- XCHG BX,DX
- MOV DL,M
- INC BX
- MOV DH,M
- XCHG BX,DX
- MOV DL,AL ;COUNT
- CMPLPE: MOV SI,CX
- MOV AL,[SI]
- CMP AL,M
- LAHF
- INC CX
- SAHF
- LAHF
- INC BX
- SAHF
- JZ L_31
- RET
- L_31:
- DEC DL
- JNZ CMPLPE
- RET
- ;
- ; ERROR EXIT
- ;
-
- IF FOPT
- ERXIT:
- MOV AL,0FFH
- MOV Byte Ptr FOPFLG,AL ;DISABLE FILE OUTPUT MODE ON ERROR
- ENDIF
-
- CALL CRLF ;SPACE DOWN
- POP DX ;GET POINTER TO MESSAGE STRING
- CALL PRINT ;PRINT IT
- MOV DX,(Offset ERRMS1) ;PRINT " ERROR"
- CALL PRINT
- CALL CRLF ;SPACE DOWN
- ;
- ; EXIT - ALL DONE, RESTORE STACK
- ;
- EXIT: MOV CL,CONST ;CHECK CONSOLE STATUS
- CALL CPM
- OR AL,AL ;CHAR WAITING?
- MOV CL,RDCHR
- JZ L_32
- CALL CPM ;GOBBLE UP CHAR
- L_32:
- MOV AL,Byte Ptr ROPFLG ;IF DISK SYSTEM WAS RESET
- OR AL,AL
- MOV AL,Byte Ptr OLDDSK ;GET DEFAULT DISK AT STARTUP
- MOV DL,AL
- MOV CL,SELDSK ;RESELECT IT
- JNZ L_33
- CALL CPM
- L_33:
- ;
- MOV CL,0 ;BDOS FUNCTION, WARM BOOT
- MOV DL,0
- INT 224 ;RETURN TO CP/M-86
- ;
- ; END OF PROGRAM CODE
- ;
- ; INITIALIZED DATA AREA
- ;
- DREMSG DB 'Driv','e' OR 80H
- ;
-
- IF PGPAWZ
- EOSMSG DB 0AH,'Press any key to continue, or CTRL-C to exit',0DH,0AH,0AH,'$'
- ENDIF
-
- ;
- ERRMS1 DB ' '
- ;
- ERRMS2 DB 'Erro','r' OR 80H
- ;
-
- IF REPERR
- ERRTAG DB ' -','>' OR 80H
- ENDIF
-
- ;
- NOFMS1 DB 0DH,0AH,'No such file on Drive '
- ;
- NOFMS2 DB ' -',' ' OR 80H
- ;
- TOTMS1 DB 0DH,0AH,0DH,0AH,'Drive',' ' OR 80H
- ;
- TOTMS2 DB ', User',' ' OR 80H
- ;
- 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
- ;
- USRMSG DB 'User ','#' OR 80H
- ;
- 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.
- ;
- LODRV EQU (Offset $) ;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 (Offset $) ;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, XDIR WILL FLAG IT AS UNRECOGNIZED.
- ;
- OTBL EQU (Offset $) ;MARK START OF OPTION TABLE
- ;
- ;ALL USERS-OPTION FLAG
- ;
-
- IF AOPT
- AOPFLG DB 'A'
- ENDIF
-
- ;
- ;MULTI-DISK-OPTION FLAG
- ;
-
- IF DOPT
- DOPFLG DB 'D'
- ENDIF
-
- ;
- ;FILE-OUTPUT-OPTION FLAG
- ;
-
- IF FOPT
- FOPFLG DB 'F'
- ENDIF
-
- ;
- ;NO PAGE-PAUSE OPTION FLAG
- ;
-
- IF NOPT AND PGPAWZ
- NOPFLG DB 'N'
- ENDIF
-
- ;
- ;PRINTER OPTION FLAG
- ;
-
- IF POPT
- POPFLG DB 'P'
- ENDIF
-
- ;
- ;RESET OPTION FLAG
- ;
- ROPFLG DB 'R'
- ;
- ;SYSTEM FILE OPTION FLAG
- ;
-
- IF SOPT
- SOPFLG DB 'S'
- ;
- ENDIF
-
- OEND EQU (Offset $) ;MARK END OF OPTION TABLE
- ;
- ; END OF OPTION LOOKUP TABLE
- ;
-
- IF FOPT
- BUFPNT DW (Offset 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,'XDIR DIR'
- DB 0 ;REST OF XDIR.DIR FILE CONTROL BLOCK
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- DB 0
- ;
- OUTBUF RS 128 ;OUTPUT FILE BUFFER
- ENDIF
-
- ;
- ; UNINITIALIZED DATA AREA
- ;
- ;storage for 5 byte BIOS function descriptor
- ;
- FUNC RS 1 ;bios function code goes here
- BIOS_DESC RS 2 ;[CX] data goes here
- RS 2 ;[DX] data goes here
- ;
- BASUSR RS 1 ;DUPE OF ORIGINAL DIRECTORY USER # TO SEARCH
- BLKMAX RS 2 ;HIGHEST BLOCK # ON DRIVE
- BLKMSK RS 1 ;SEC/BLK - 1
- BLKSHF RS 1 ;# SHIFTS TO MULT BY SEC/BLK
- COUNT RS 2 ;ENTRY COUNT
- dsksiz RS 2 ;HIGHEST FILE # IN DIRECTORY
- FREEBY RS 2 ;CONTAINS NUMBER OF K LEFT ON DIRECTORY DRIVE
- GAP RS 2 ;SORT ROUTINE STORAGE
- I RS 2 ;SORT ROUTINE STORAGE
- J RS 2 ;SORT ROUTINE STORAGE
- JGAP RS 2 ;SORT ROUTINE STORAGE
- LZFLG RS 1 ;0 WHEN PRINTING LEADING ZEROS
- MAXUSR RS 1 ;MAXIMUM USER # FOR DRIVE FROM LOOKUP TABLE
- NEWUSR RS 1 ;CONTAINS USER NUMBER SELECTED BY "$U" OPTION
- NEXTT RS 2 ;NEXT TABLE ENTRY
- OLDDSK RS 1 ;HOLDER FOR CURRENTLY LOGGED-IN DRIVE
- OLDUSR RS 1 ;CONTAINS USER NUMBER UPON INVOCATION
- SCOUNT RS 2 ;# TO SORT
- SUPSPC RS 1 ;LEADING SPACE FLAG FOR DECIMAL ROUTINE
- TBLOC RS 2 ;POINTER TO START OF NAME TABLE
- TEMP RS 2 ;SAVE DIR ENTRY
- TOTFIL RS 2 ;TOTAL NUMBER OF FILES
- TOTSIZ RS 2 ;TOTAL SIZE OF ALL FILES
- ORDER EQU (Offset $) ;ORDER TABLE STARTS HERE
- ;
- RS 4000H
- DB 0
- ;
- END
-