home *** CD-ROM | disk | FTP | other *** search
- ; PROGRAM: FIND
- ; AUTHOR: RICHARD CONN
- ; VERSION: 1.1
- ; DATE: 25 July 83
- ; PREVIOUS VERSIONS: 1.0 (24 JULY 83)
-
- VERS EQU 11 ;version number
-
- ;
- ; FIND searches through all of the known disks for one or more
- ; files matching the passed file specification. AFNs (Ambiguous File Names)
- ; are permitted. FIND is invoked by the following command line:
- ; FIND afn,afn,afn,... o
- ; where "afn" refers to the file sought and "o" is none or more of:
- ; S - Include System Files
- ; FIND may be installed by GENINS to restrict the disks and user
- ; areas searched.
- ;
-
- ;
- ; System equates:
- ;
- BOOT EQU 0000H ;CP/M WARM BOOT JUMP VECTOR
- BDOS EQU BOOT+05H ;CP/M BDOS CALL JUMP VECTOR
- TBUFF EQU BOOT+80H ;DISK I/O BUFFER
- FCB EQU BOOT+5CH ;DEFAULT FILE CONTROL BLOCK
- FCB2 EQU BOOT+6CH ;SECONDARY FILE CONTROL AREA
- CR EQU 'M'-'@' ;CTL-M FOR CARRIAGE RETURN
- LF EQU 'J'-'@' ;CTL-J FOR LINE FEED
- CTRLC EQU 'C'-'@' ;ABORT
- CTRLS EQU 'S'-'@' ;PAUSE
- ESIZE EQU 12 ;12 BYTES/DIR ENTRY
-
- ;
- ; This program is Copyright (c) 1983 by Richard Conn
- ; All Rights Reserved
- ;
- ; ZCPR2 and its utilities, including this one, are released
- ; to the public domain. Anyone who wishes to USE them may do so with
- ; no strings attached. The author assumes no responsibility or
- ; liability for the use of ZCPR2 and its utilities.
- ;
- ; The author, Richard Conn, has sole rights to this program.
- ; ZCPR2 and its utilities may not be sold without the express,
- ; written permission of the author.
- ;
-
- ;
- ; Branch to Start of Program
- ;
- ORG BOOT+100H
- JMP START
-
- ;
- ;******************************************************************
- ;
- ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
- ;
- ; This data block precisely defines the data format for
- ; initial features of a ZCPR2 system which are required for proper
- ; initialization of the ZCPR2-Specific Routines in SYSLIB.
- ;
-
- ;
- ; EXTERNAL PATH DATA
- ;
- EPAVAIL:
- DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
- EPADR:
- DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
-
- ;
- ; INTERNAL PATH DATA
- ;
- INTPATH:
- DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT
- ; DISK = 1 FOR A, '$' FOR CURRENT
- ; USER = NUMBER, '$' FOR CURRENT
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT
- DB 0 ; END OF PATH
-
- ;
- ; MULTIPLE COMMAND LINE BUFFER DATA
- ;
- MCAVAIL:
- DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
- MCADR:
- DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
-
- ;
- ; DISK/USER LIMITS
- ;
- MDISK:
- DB 4 ; MAXIMUM NUMBER OF DISKS
- MUSER:
- DB 31 ; MAXIMUM USER NUMBER
-
- ;
- ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
- ;
- DOK:
- DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
- UOK:
- DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
-
- ;
- ; PRIVILEGED USER DATA
- ;
- PUSER:
- DB 10 ; BEGINNING OF PRIVILEGED USER AREAS
- PPASS:
- DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS
- DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
-
- ;
- ; CURRENT USER/DISK INDICATOR
- ;
- CINDIC:
- DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS)
-
- ;
- ; DMA ADDRESS FOR DISK TRANSFERS
- ;
- DMADR:
- DW 80H ; TBUFF AREA
-
- ;
- ; NAMED DIRECTORY INFORMATION
- ;
- NDRADR:
- DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
- NDNAMES:
- DB 64 ; MAX NUMBER OF DIRECTORY NAMES
- DNFILE:
- DB 'NAMES ' ; NAME OF DISK NAME FILE
- DB 'DIR' ; TYPE OF DISK NAME FILE
-
- ;
- ; REQUIREMENTS FLAGS
- ;
- EPREQD:
- DB 000H ; EXTERNAL PATH?
- MCREQD:
- DB 000H ; MULTIPLE COMMAND LINE?
- MXREQD:
- DB 0FFH ; MAX USER/DISK?
- UDREQD:
- DB 000H ; ALLOW USER/DISK CHANGE?
- PUREQD:
- DB 000H ; PRIVILEGED USER?
- CDREQD:
- DB 000H ; CURRENT INDIC AND DMA?
- NDREQD:
- DB 000H ; NAMED DIRECTORIES?
- Z2CLASS:
- DB 0 ; CLASS 0
- DB 'ZCPR2'
- DS 10 ; RESERVED
-
- ;
- ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
- ;
- ;******************************************************************
- ;
-
- ;
- ; Start of Program
- ;
- START:
- ;
- LXI H,0 ;SAVE STACK PTR
- DAD SP
- SHLD STACK
- LXI SP,STACK ;SET STACK POINTER
- CALL GTBIOS ;GET BIOS JUMP TABLE
- CALL HELLO ;SIGN ON MESSAGE
- CALL HELPCHK ;CHECK FOR AND PRINT HELP MESSAGE
- CALL OPTCHK ;BUILD FILE NAME TABLE AND PROCESS OPTIONS
- CALL CRLF ;NEW LINE
- CALL FIND ;DO THE SEARCHES
- CALL BYE ;SIGN OFF MESSAGE
- RETURN:
- LHLD STACK ;QUIET RETURN
- SPHL
- RET
- ;
- ; ** Main Routines **
- ;
-
- ;
- ; SAY WHO WE ARE
- ;
- HELLO:
- CALL PRINT
- DB 'FIND, Version '
- DB (VERS/10)+'0','.',(VERS MOD 10)+'0'
- DB 0
- RET
- ;
- ; CHECK FOR HELP REQUEST
- ;
- HELPCHK:
- LDA FCB+1 ;GET 1ST BYTE OF FILENAME
- CPI '/' ;HELP?
- JZ HCK1
- CPI ' ' ;MAKE SURE IT IS NON-BLANK
- RNZ ;OK - KEEP GOING
- ;
- ; IF NO FILE NAME IS SPECIFIED, ABORT WITH NOTICE
- ;
- HCK1:
- CALL PRINT
- DB CR,LF
- DB CR,LF,' FIND is used to search through all logged-in disks'
- DB CR,LF,'for any files matching an ambiguous file name (wild'
- DB CR,LF,'cards ar permitted). It is invoked as follows:'
- DB CR,LF,' FIND afn,afn,afn,... o'
- DB CR,LF,'where "afn" is the ambigous file name to search for'
- DB CR,LF,'(as many afns as desired may be specified), and'
- DB CR,LF,'"o" is none or more of the following options:'
- DB CR,LF,' S - Include System Files'
- DB CR,LF,'Drive prefixes (DU:) are ignored.'
- DB CR,LF
- DB 0
- JMP RETURN
- ;
- ; CHECKS FOR S OPTION IN COMMAND LINE AND EXTRACTS FILE NAMES INTO TABLE
- ;
- OPTCHK:
- XRA A ;TURN OFF FLAGS
- STA SYSTEM ;NO SYSTEM FILES
- STA FFLAG ;NO FILES FOUND
- STA ECOUNT ;NO ENTRIES
- STA FNCOUNT ;NO FILE NAMES
- LXI H,TBUFF ;SCAN THRU TBUFF, BUILDING A FILE NAME TABLE
- MOV A,M ;GET CHAR COUNT
- INX H ;PT TO FIRST CHAR
- PUSH H ;SAVE PTR
- ADD L ;PT TO AFTER LAST CHAR
- MOV L,A
- MVI M,0 ;STORE ENDING ZERO
- POP H ;GET PTR TO FIRST CHAR
- CALL SBLANK ;SKIP BLANKS
- LXI D,FNTAB ;PT TO TABLE
- FNLOOP:
- PUSH D ;SAVE TABLE PTR
- CALL GETFN ;EXTRACT FILE NAME
- POP D
- PUSH H
- LXI H,11 ;PT TO NEXT TABLE ENTRY
- DAD D
- XCHG
- POP H
- LDA FNCOUNT ;INCREMENT COUNT
- INR A
- STA FNCOUNT
- MOV A,M ;GET TERMINATING CHAR
- INX H ;PT TO NEXT
- CPI ',' ;ANOTHER FOLLOWS?
- JZ FNLOOP
- DCX H ;POINT BACK TO DELIM
- CALL SBLANK ;SKIP TO NON-BLANK
- OPTCK1:
- MOV A,M ;GET OPTION
- CALL DELCHK ;DONE IF DELIM
- RZ
- CPI 'S' ;SYSTEM?
- JZ OPTCKS
- CALL PRINT
- DB CR,LF,'Invalid Option -- ',0
- MOV A,M
- CALL TYPE
- JMP HCK1
- OPTCKS:
- MVI A,0FFH ;SET FLAG
- STA SYSTEM
- INX H
- JMP OPTCK1
- GETFN:
- PUSH D ;FILL TARGET FCB
- MVI B,11 ;11 BYTES
- MVI A,' ' ;SPACE FILL
- GETFN0:
- STAX D ;PUT SPACE
- INX D
- DCR B
- JNZ GETFN0
- POP D ;PT TO ENTRY AGAIN
- CALL SCANCOL ;SCAN FOR COLON
- MVI B,8 ;8 CHARS MAX
- CALL GETFN1 ;GET AND FILL ENTRY
- MOV A,M ;GET CHAR
- CPI '.' ;DELIM?
- RNZ ;DONE
- INX H ;PT TO AFTER PERIOD
- MVI B,3 ;3 CHARS MAX AND DO IT AGAIN
- GETFN1:
- MOV A,M ;GET CHAR
- CPI '.' ;END OF FIELD?
- JZ GETFN3
- CALL DELCHK ;CHECK DELIMITER
- RZ
- CPI '*' ;WILD?
- JZ GETFNQ
- STAX D ;STORE CHAR
- INX H ;PT TO NEXT
- INX D
- DCR B ;COUNT DOWN
- JNZ GETFN1
- GETFN2:
- MOV A,M ;FLUSH CHARS TO DELIM
- CALL DELCHK ;CHECK FOR DELIMITER
- RZ
- INX H ;PT TO NEXT
- JMP GETFN2
- GETFN3:
- INX D ;PT TO AFTER FIELD
- DCR B ;COUNT DOWN
- JNZ GETFN3
- RET
- GETFNQ:
- MVI A,'?' ;FILL WITH QUESTION MARKS
- STAX D
- INX D
- DCR B
- JNZ GETFNQ
- JMP GETFN2 ;SKIP TO DELIM
- DELCHK:
- ORA A ;END OF LINE?
- RZ
- CPI '.' ;END OF FIELD?
- RZ
- CPI ',' ;END OF ENTRY?
- RZ
- CPI ' '
- RET
- SBLANK:
- MOV A,M ;SKIP TO NON-BLANK
- CPI ' '
- RNZ
- INX H
- JMP SBLANK
- SCANCOL:
- PUSH D ;SAVE TABLE PTR
- PUSH H ;SAVE PTR
- SCOL1:
- MOV A,M ;GET CHAR
- INX H ;PT TO NEXT
- CPI ':' ;COLON?
- JZ SCOLX
- CALL DELCHK ;CHECK FOR DELIMITER
- JNZ SCOL1
- SCOL2:
- POP H ;RESTORE
- POP D
- RET
- SCOLX:
- XCHG ;DE PTS TO AFTER COLON
- POP H ;GET OLD PTR
- XCHG ;REPLACE IT
- POP D ;GET TABLE PTR
- RET
- ;
- ; LOOK THROUGH DIRECTORY
- ;
- FIND:
- XRA A ;SELECT FIRST DISK
- STA FCB
- CALL CPMCHK ;GET INFO THE FIRST TIME
- FIND1:
- RZ ;ABORT IF ERROR
- FIND2:
- CALL NXTSEC ;GET A DIRECTORY SECTOR
- JZ FIND3 ;RETURNS ZERO FLAG IF NO MORE
- CALL CHKENT ;CHECK IT OUT
- JMP FIND2 ;KEEP IT UP TILL DONE
- FIND3:
- CALL DIRALPHA ;SORT ENTRIES
- CALL PRFILES ;PRINT SORTED ENTRIES
- LDA FCB ;NEXT DISK
- INR A
- STA FCB
- CALL NXTDISK ;SELECT NEXT DISK
- JMP FIND1
-
- ;
- ; SIGN OFF
- ;
- BYE:
- MVI C,13 ;RESET SYSTEM
- CALL BDOS
- LDA FFLAG ;GET FILE FOUND FLAG
- ORA A ;NO FILES FOUND?
- JNZ RETURN
- CALL PRINT
- DB CR,LF,'NO Files Found',0
- JMP RETURN
- ;
- ; CHECKS THE CURRENT 4 DIRECTORY ENTRIES AGAINST ARGUMENT
- ; IF MATCH, REWRITES SECTOR WITH REACTIVATED 1ST BYTES
- ;
- CHKENT:
- MVI B,4 ;NUMBER OF ENTRIES PER SECTOR
- LXI H,TBUFF ;BEGINNING OF BUFFER
- CKLUP:
- PUSH B
- MOV A,M
- CPI 0E5H ;CHECK FOR UNUSED
- JZ CKINC
- XRA A ;A=0
- STA CLPFLG ;SET FLAG FOR NO ENTRIES FOUND
- LDA FNCOUNT ;GET NUMBER OF FILE NAMES TO LOOK THRU
- MOV B,A ;... IN B
- LXI D,FNTAB ;PT TO TABLE
- CKLUP1:
- PUSH B ;SAVE COUNT
- PUSH H ;SAVE BEGINNING ADDRESS
- PUSH D
- CALL COMPAR ;COMPARE WITH ARGUMENT AND SAVE IF MATCH
- POP D
- LXI H,11 ;PT TO NEXT ENTRY
- DAD D
- XCHG
- POP H
- POP B
- DCR B ;COUNT DOWN
- JNZ CKLUP1
- CKINC:
- POP B
- LXI D,32 ;LENGTH OF ENTRY
- DAD D
- DCR B
- JNZ CKLUP
- LHLD DIRMAX
- DCX H ;REDUCE SECTORS LEFT
- SHLD DIRMAX
- LHLD SECTOR ;POINT TO NEXT SECTOR
- INX H
- SHLD SECTOR
- XCHG
- LHLD MAXSEC ;REACHED LIMIT?
- INX H ;ONE MORE
- MOV A,H ;CHECK HIGH
- CMP D
- RNZ
- MOV A,L ;CHECK LOW
- CMP E
- RNZ
- LHLD TRACK ;NEXT TRACK
- INX H
- SHLD TRACK
- LXI H,1 ;FIRST SECTOR OF NEXT TRACK
- SHLD SECTOR
- RET
- ;
- ; COMPARE 11 BYTES OF DIRECTORY ENTRY AGAINST ARGUMENT; RNZ IF NOT MATCHED
- ; DE PTS TO TABLE ENTRY TO COMPARE TO
- ;
- COMPAR:
- LDA CLPFLG ;GET FOUND FLAG
- ORA A ;0=NO
- RNZ
- SHLD TEMP ;Hold pointer in case of match
- INX H
- XCHG
- MVI B,11
- CMPR1:
- LDAX D ;GET DIRECTORY ENTRY CHARACTER
- ANI 7FH ;STRIP ANY FLAGS
- CMP M
- JZ CMPR2
- MOV A,M
- CPI '?'
- RNZ
- CMPR2:
- INX D
- INX H ;BUMP TO NEXT CHARACTER
- DCR B
- JNZ CMPR1 ;LOOP FOR 11 CHARACTERS
- PUSH D ;SAVE ENTRY PTR
- LDAX D ;GET EXTENT IN B
- MOV B,A
- LDA EXTENT ;GET EXTENT MASK
- CMP B
- POP D ;GET ENTRY PTR
- JC CMPR4 ;NO MATCH
- LDA SYSTEM ;INCLUDE SYSTEM FILES?
- ORA A ;0=NO
- JNZ CMPR3
- DCX D ;BACK UP 2 BYTES
- DCX D
- LDAX D ;GET T2
- ANI 80H ;CHECK FOR SYS
- RNZ
- CMPR3:
- LHLD TEMP ;CHECK FOR USER LIMIT
- LDA MUSER ;GET MAX USER
- CMP M ;BEYOND MAX?
- JC CMPR4
- LHLD FCOUNT ;INCREMENT COUNT
- INX H
- SHLD FCOUNT
- LHLD DSTART ;GET PTR TO NEXT ENTRY
- XCHG
- LHLD TEMP
- MVI B,ESIZE ;COPY ENTRY
- CALL MOVE
- XCHG
- SHLD DSTART ;PTR TO NEXT ENTRY
- XCHG
- LHLD BDOS+1 ;CHECK FOR MEMORY OVERFLOW
- MOV A,H
- SUI 10 ;BELOW CCP
- CMP D ;PT BEYOND LIMIT?
- JC MOVFL
- MVI A,0FFH ;SET FOUND FLAG
- STA FFLAG
- XRA A
- RET ;RETURNS 'ZERO' FLAG SET FOR MATCH
- CMPR4:
- MVI A,0FFH ;NO MATCH
- ORA A
- RET
- MOVFL:
- CALL PRINT
- DB CR,LF,'ABORT -- Not Enough Memory for Buffers',0
- JMP RETURN
- ;
- ; CHECK FOR CP/M VERSION AND SET THINGS
- ;
- CPMCHK:
- MVI C,12 ;VERSION NUMBER REQUEST
- CALL BDOS
- CPI 20H ;EARLIER THAN 2.2?
- JC VERERR
- ;
- ; ADVANCE TO NEXT DISK
- ;
- NXTDISK:
- LXI B,TBUFF ;SET DMA ADDRESS
- CALL SETDMA
- LDA MDISK ;GET MAX DISK
- MOV B,A
- LDA FCB
- CMP B
- RZ ;ABORT IF BEYOND MAX
- MOV C,A
- MVI B,0
- CALL SELDSK ;MAKE SURE DRIVE IS
- MOV A,H ; SELECTED
- ORA L
- RZ ;ERROR RETURN
- SHLD DPH ;SAVE THE ADDRESS
- LXI D,10 ;PT TO DPB
- DAD D
- MOV E,M ;GET DPB ADDRESS IN HL
- INX H
- MOV D,M
- XCHG
- MOV E,M ;NUMBER OF SECTORS/TRACK
- INX H ;AS 2-BYTE QUANTITY IN DE
- MOV D,M
- INX H
- XCHG
- SHLD MAXSEC ;SET MAX SECTORS/TRACK
- XCHG
- INX H
- INX H
- MOV A,M ;GET EXM
- STA EXTENT
- INX H ;PT TO DRM
- INX H
- INX H
- MOV E,M ;GET NUMBER OF
- INX H ; DIRECTORY ENTRIES
- MOV D,M
- XCHG
- INX H ;ACCOUNT FOR - 1
- SHLD DSTART ;SAVE NUMBER OF DIRECTORY ENTRIES
- CALL SHFHL2 ;SHIFT 'HL' RIGHT 2
- SHLD DIRMAX ;SAVE NUMBER DIRECTORY SECTORS
- LXI H,5 ;NOW POINT TO SYSTEM
- DAD D ; TRACK OFFSET
- MOV A,M ;PICK UP NUMBER OF
- INX H
- MOV H,M
- MOV L,A
- SHLD TRACK
- LXI H,1 ;SET SECTOR
- SHLD SECTOR
- LDA ECOUNT ;LAST NEW LINE?
- ANI 3
- CNZ CRLF
- CALL PRINT
- DB 'Disk ',0
- LDA FCB
- ADI 'A'
- CALL TYPE
- CALL PRINT
- DB ' --',CR,LF,0
- LXI H,SCRATCH ;PT TO SCRATCH AREA
- SHLD ORDER ;ADDRESS OF ORDER TABLE
- XCHG
- LHLD DSTART ;GET NUMBER OF DIRECTORY ENTRIES
- DAD H ;DOUBLE FOR NUMBER OF BYTES IN ORDER TABLE
- DAD D ;PT TO FIRST BYTE OF DIRBUF
- SHLD DIRBUF ;SET PTR
- SHLD DSTART ;SET LOOP PTR
- LXI H,0 ;SET FILE COUNT
- SHLD FCOUNT
- XRA A ;SET COUNT
- STA ECOUNT
- CMA ;FLIP
- ORA A ;OK TO CONTINUE
- RET
- VERERR:
- CALL PRINT
- DB CR,LF,'ABORT -- NOT CP/M 2.x or Later',0
- JMP RETURN
- ;
- ; GET BIOS JUMPS VECTORS FOR EASY REFERENCE
- ;
- GTBIOS:
- LHLD BOOT+1 ;POINTS TO BIOS JUMP TABLE+3
- LXI D,WBOOT ;WHERE WE WILL KEEP A COPY
- MVI B,16*3 ;MOVE 48 BYTES AND FALL THRU TO MOVE
- ;
- ; GENERAL PURPOSE MOVE ROUTINE
- ; FROM 'HL' TO 'DE' FOR COUNT OF 8
- ;
- MOVE:
- MOV A,M ;GET A BYTE
- STAX D ;PUT A BYTE
- INX D ;INCREMENT TO NEXT
- INX H
- DCR B ;COUNT DOWN
- JNZ MOVE
- RET
- ;
- ; READS NEXT SECTOR (GROUP OF FOUR DIRECTORY ENTRIES)
- ; RETURNS WITH ZERO FLAG SET IF NO MORE
- ;
- NXTSEC:
- LHLD DIRMAX ;SEE IF MORE SECTORS
- MOV A,H
- ORA L
- RZ ;RETURNS ZERO FLAG IF NO MORE
- LHLD TRACK ;SET TRACK
- MOV B,H
- MOV C,L
- CALL SETTRK
- LHLD SECTOR ;SET SECTOR
- MOV B,H
- MOV C,L
- CALL TRNSLT
- CALL SETSEC
- CALL READ ;READ A SECTOR
- ANI 1 ;REVERSE SENSE OF ERROR FLAG
- XRI 1 ;RETURNS WITH ZERO FLAG SET
- RET ;IF BAD READ
- ;
- ; PRINT FILES IN DIRBUF
- ;
- PRFILES:
- LHLD FCOUNT ;GET COUNT
- MOV A,H ;ANY?
- ORA L
- RZ
- MOV B,H ;COUNT IN BC
- MOV C,L
- LHLD DIRBUF ;PT TO FIRST ONE
- PRFLOOP:
- PUSH B ;SAVE COUNT
- PUSH H ;SAVE PTR
- CALL PRINTFCB ;PRINT FCB
- POP H ;GET REGS BACK
- POP B
- LXI D,ESIZE ;PT TO NEXT
- DAD D
- DCX B ;COUNT DOWN
- MOV A,B
- ORA C
- JNZ PRFLOOP
- MVI A,0FFH ;SET OK
- ORA A
- RET
- ;
- ; FCB PRINTING ROUTINE
- ;
- PRINTFCB:
- MVI A,' ' ;SPACE IN
- CALL TYPE
- CALL TYPE
- MOV A,M ;GET USER NUMBER
- CALL DECOUT ;PRINT IT
- MVI A,':'
- CALL TYPE
- INX H
- PR0:
- MVI B,8
- CALL PR1
- MVI A,'.'
- CALL TYPE
- MVI B,3
- CALL PR1
- LDA ECOUNT ;INCREMENT COUNT
- INR A
- STA ECOUNT
- ANI 3 ;EVERY 4
- CZ CRLF ;NEW LINE
- RET
- PR1:
- MOV A,M
- ANI 7FH
- CALL TYPE
- INX H
- DCR B
- JNZ PR1
- RET
- ;
- ; PRINT VALUE IN A AS DECIMAL
- ;
- DECOUT:
- PUSH B ;SAVE REG
- MVI C,'0' ;SET VALUE
- DEC1:
- SUI 10 ;DIVIDE BY 10
- JC DEC2
- INR C
- JMP DEC1
- DEC2:
- ADI 10 ;ADD 10 BACK IN
- MOV B,A ;SAVE VALUE
- MOV A,C ;CHECK DIGITS
- CPI '0'
- JNZ DEC3
- MVI A,' ' ;LEADING SPACE
- DEC3:
- CALL TYPE ;DON'T TYPE LEADING ZERO
- MOV A,B ;GET ONES
- ADI '0' ;CONVERT TO ASCII
- CALL TYPE
- POP B ;GET REG
- RET
- ;
- ; PRINT CHAR IN A ON TERMINAL; AFFECT NO REGS
- ;
- TYPE:
- PUSH H ;SAVE REGS
- PUSH D
- PUSH B
- PUSH PSW
- CALL CONST ;CHAR PENDING?
- ORA A ;0=NONE
- JZ TYPE1
- CALL CONIN ;GET CHAR
- ANI 7FH ;MASK
- CPI CTRLC ;ABORT?
- JZ RETURN
- CPI CTRLS ;PAUSE?
- JNZ TYPE1
- CALL CONIN ;GET ANOTHER CHAR
- CPI CTRLC
- JZ RETURN
- TYPE1:
- POP PSW ;GET CHAR TO SEND
- PUSH PSW
- MOV C,A ;CHAR IN C
- CALL CONOUT
- POP PSW ;RESTORE REGS
- POP B
- POP D
- POP H
- RET
- ;
- ; NEW LINE
- ;
- CRLF:
- MVI A,0DH ;NEW LINE
- CALL TYPE
- MVI A,0AH
- JMP TYPE
- ;
- ; PRINT MESSAGE AT RETURN ADDRESS
- ;
- PRINT:
- XTHL ;SAVE HL, GET PTR
- PRINTL:
- MOV A,M ;GET BYTE
- INX H ;PT TO NEXT
- ANI 7FH ;MASK
- JZ PRINTD ;DONE IF ZERO
- CALL TYPE
- JMP PRINTL
- PRINTD:
- XTHL
- RET
- ;
- ; SHIFT REGS 'HL' RIGHT 2 BITS LOGICAL
- ;
- SHFHL2:
- CALL SHFHL ;ROTATE RIGHT 1 BIT AND FALL THRU
- SHFHL:
- XRA A ;CLEAR CARRY
- MOV A,H
- RAR ;SHIFTED BIT IN CARRY
- MOV H,A
- MOV A,L
- RAR
- MOV L,A
- RET
- ;
- ; TRANSLATE REG 'BC' FROM LOGICAL TO PHYSICAL SECTOR NUMBER
- ;
- TRNSLT:
- LHLD DPH ;GET PTR TO DPH
- MOV E,M ;GET ADDRESS OF XLT
- INX H
- MOV D,M
- CALL SECTRAN ;USE BIOS ROUTINE
- MOV C,L ;RETURN VALUE IN BC
- MOV B,H
- RET
-
- ;
- ; DIRALPHA -- ALPHABETIZES DIRECTORY PTED TO BY HL; BC CONTAINS
- ; THE NUMBER OF FILES IN THE DIRECTORY
- ;
- DIRALPHA:
- LHLD FCOUNT ; GET FILE COUNT
- MOV A,H ; ANY FILES?
- ORA L
- RZ
- SHLD N ; SET "N"
- MOV B,H ; BC=COUNT
- MOV C,L
- LHLD DIRBUF ; PT TO DIRECTORY
- ;
- ; SHELL SORT --
- ; THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
- ; BY KERNIGAN AND PLAUGHER, PAGE 106. COPYRIGHT, 1976, ADDISON-WESLEY.
- ; ON ENTRY, BC=NUMBER OF ENTRIES AND HL=ADDRESS OF FIRST ENTRY
- ;
- SORT:
- XCHG ; POINTER TO DIRECTORY IN DE
- LHLD ORDER ; PT TO ORDER TABLE
- ;
- ; SET UP ORDER TABLE; HL PTS TO NEXT ENTRY IN ORDER TABLE, DE PTS TO NEXT
- ; ENTRY IN DIRECTORY, BC = NUMBER OF ELEMENTS REMAINING
- ;
- SORT1:
- MOV M,E ; STORE LOW-ORDER ADDRESS
- INX H ; PT TO NEXT ORDER BYTE
- MOV M,D ; STORE HIGH-ORDER ADDRESS
- INX H ; PT TO NEXT ORDER ENTRY
- PUSH H ; SAVE PTR
- LXI H,ESIZE ; HL=NUMBER OF BYTES/ENTRY
- DAD D ; PT TO NEXT DIR1 ENTRY
- XCHG ; DE PTS TO NEXT ENTRY
- POP H ; GET PTR TO ORDER TABLE
- DCX B ; COUNT DOWN
- MOV A,B ; DONE?
- ORA C
- JNZ SORT1
- ;
- ; THIS IS THE MAIN SORT LOOP FOR THE SHELL SORT IN "SOFTWARE TOOLS" BY K&P
- ;
-
- ;
- ; SHELL SORT FROM "SOFTWARE TOOLS" BY KERNINGHAN AND PLAUGER
- ;
- LHLD N ; NUMBER OF ITEMS TO SORT
- SHLD GAP ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
-
- ; FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
- SRTL0:
- ORA A ; CLEAR CARRY
- LHLD GAP ; GET PREVIOUS GAP
- MOV A,H ; ROTATE RIGHT TO DIVIDE BY 2
- RAR
- MOV H,A
- MOV A,L
- RAR
- MOV L,A
-
- ; TEST FOR ZERO
- ORA H
- JZ SDONE ; DONE WITH SORT IF GAP = 0
-
- SHLD GAP ; SET VALUE OF GAP
- SHLD I ; SET I=GAP FOR FOLLOWING LOOP
-
- ; FOR (I = GAP + 1; I <= N; I = I + 1)
- SRTL1:
- LHLD I ; ADD 1 TO I
- INX H
- SHLD I
-
- ; TEST FOR I <= N
- XCHG ; I IS IN DE
- LHLD N ; GET N
- MOV A,L ; COMPARE BY SUBTRACTION
- SUB E
- MOV A,H
- SBB D ; CARRY SET MEANS I > N
- JC SRTL0 ; DON'T DO FOR LOOP IF I > N
-
- LHLD I ; SET J = I INITIALLY FOR FIRST SUBTRACTION OF GAP
- SHLD J
-
- ; FOR (J = I - GAP; J > 0; J = J - GAP)
- SRTL2:
- LHLD GAP ; GET GAP
- XCHG ; ... IN DE
- LHLD J ; GET J
- MOV A,L ; COMPUTE J - GAP
- SUB E
- MOV L,A
- MOV A,H
- SBB D
- MOV H,A
- SHLD J ; J = J - GAP
- JC SRTL1 ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
- MOV A,H ; J=0?
- ORA L
- JZ SRTL1 ; IF ZERO, J=0 AND ABORT
-
- ; SET JG = J + GAP
- XCHG ; J IN DE
- LHLD GAP ; GET GAP
- DAD D ; J + GAP
- SHLD JG ; JG = J + GAP
-
- ; IF (V(J) <= V(JG))
- CALL ICOMPARE ; J IN DE, JG IN HL
-
- ; ... THEN BREAK
- JC SRTL1
-
- ; ... ELSE EXCHANGE
- LHLD J ; SWAP J, JG
- XCHG
- LHLD JG
- CALL ISWAP ; J IN DE, JG IN HL
-
- ; END OF INNER-MOST FOR LOOP
- JMP SRTL2
-
- ;
- ; SORT IS DONE -- RESTRUCTURE DIR1 IN SORTED ORDER IN PLACE
- ;
- SDONE:
- LHLD N ; NUMBER OF ENTRIES
- MOV B,H ; ... IN BC
- MOV C,L
- LHLD ORDER ; PTR TO ORDERED POINTER TABLE
- SHLD PTPTR ; SET PTR PTR
- LHLD DIRBUF ; PTR TO UNORDERED DIRECTORY
- SHLD PTDIR ; SET PTR DIR BUFFER
-
- ; FIND PTR TO NEXT DIR1 ENTRY
- SRTDN:
- LHLD PTPTR ; PT TO REMAINING POINTERS
- XCHG ; ... IN DE
- LHLD PTDIR ; HL PTS TO NEXT DIR ENTRY
- PUSH B ; SAVE COUNT OF REMAINING ENTRIES
-
- ; FIND PTR TABLE ENTRY
- SRTDN1:
- LDAX D ; GET CURRENT POINTER TABLE ENTRY VALUE
- INX D ; PT TO HIGH-ORDER POINTER BYTE
- CMP L ; COMPARE AGAINST DIR1 ADDRESS LOW
- JNZ SRTDN2 ; NOT FOUND YET
- LDAX D ; LOW-ORDER BYTES MATCH -- GET HIGH-ORDER POINTER BYTE
- CMP H ; COMPARE AGAINST DIR1 ADDRESS HIGH
- JZ SRTDN3 ; MATCH FOUND
- SRTDN2:
- INX D ; PT TO NEXT PTR TABLE ENTRY
- DCX B ; COUNT DOWN
- MOV A,C ; END OF TABLE?
- ORA B
- JNZ SRTDN1 ; CONTINUE IF NOT
-
- ; FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
- FERR$PTR:
- CALL PRINT
- DB 0DH,0AH,'DIRALPHA -- Pointer Error',0
- JMP RETURN
-
- ; FOUND THE POINTER TABLE ENTRY WHICH POINTS TO THE NEXT UNORDERED DIR1 ENTRY
- ; MAKE BOTH POINTERS (PTR TO NEXT, PTR TO CURRENT UNORDERED DIR1 ENTRY)
- ; POINT TO SAME LOCATION (PTR TO NEXT DIR1 ENTRY TO BE ORDERED)
- SRTDN3:
- LHLD PTPTR ; GET PTR TO NEXT ORDERED ENTRY
- DCX D ; DE PTS TO LOW-ORDER POINTER ADDRESS
- MOV A,M ; MAKE PTR TO NEXT UNORDERED DIR1 PT TO BUFFER FOR
- STAX D ; DIR1 ENTRY TO BE MOVED TO NEXT UNORDERED DIR1 POS
- INX H ; PT TO NEXT PTR ADDRESS
- INX D
- MOV A,M ; MAKE HIGH POINT SIMILARLY
- STAX D
-
- ; COPY NEXT UNORDERED DIR1 ENTRY TO HOLD BUFFER
- MVI B,ESIZE ; B=NUMBER OF BYTES/ENTRY
- LHLD PTDIR ; PT TO ENTRY
- LXI D,HOLD ; PT TO HOLD BUFFER
- PUSH B ; SAVE B=NUMBER OF BYTES/ENTRY
- CALL MOVE
- POP B
-
- ; COPY TO-BE-ORDERED DIR1 ENTRY TO NEXT ORDERED DIR1 POSITION
- LHLD PTPTR ; POINT TO ITS POINTER
- MOV E,M ; GET LOW-ADDRESS POINTER
- INX H
- MOV D,M ; GET HIGH-ADDRESS POINTER
- LHLD PTDIR ; DESTINATION ADDRESS FOR NEXT ORDERED DIR1 ENTRY
- XCHG ; HL PTS TO ENTRY TO BE MOVED, DE PTS TO DEST
- PUSH B ; SAVE B=NUMBER OF BYTES/ENTRY
- CALL MOVE
- POP B
- XCHG ; HL PTS TO NEXT UNORDERED DIR1 ENTRY
- SHLD PTDIR ; SET POINTER FOR NEXT LOOP
-
- ; COPY ENTRY IN HOLD BUFFER TO LOC PREVIOUSLY HELD BY LATEST ORDERED ENTRY
- LHLD PTPTR ; GET PTR TO PTR TO THE DESTINATION
- MOV E,M ; GET LOW-ADDRESS POINTER
- INX H
- MOV D,M ; HIGH-ADDRESS POINTER
- LXI H,HOLD ; HL PTS TO HOLD BUFFER, DE PTS TO ENTRY DEST
- CALL MOVE ; B=NUMBER OF BYTES/ENTRY
-
- ; POINT TO NEXT ENTRY IN POINTER TABLE
- LHLD PTPTR ; POINTER TO CURRENT ENTRY
- INX H ; SKIP OVER IT
- INX H
- SHLD PTPTR
-
- ; COUNT DOWN
- POP B ; GET COUNTER
- DCX B ; COUNT DOWN
- MOV A,C ; DONE?
- ORA B
- JNZ SRTDN
- RET ; DONE
-
- ;
- ; SWAP (Exchange) the pointers in the ORDER table whose indexes are in
- ; HL and DE
- ;
- ISWAP:
- PUSH H ; SAVE HL
- LHLD ORDER ; ADDRESS OF ORDER TABLE - 2
- MOV B,H ; ... IN BC
- MOV C,L
- POP H
- DCX H ; ADJUST INDEX TO 0...N-1 FROM 1...N
- DAD H ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
- ; OF ORIGINAL HL (1, 2, ...)
- DAD B ; HL NOW PTS TO POINTER INVOLVED
- XCHG ; DE NOW PTS TO POINTER INDEXED BY HL
- DCX H ; ADJUST INDEX TO 0...N-1 FROM 1...N
- DAD H ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
- ; OF ORIGINAL DE (1, 2, ...)
- DAD B ; HL NOW PTS TO POINTER INVOLVED
- MOV C,M ; EXCHANGE POINTERS -- GET OLD (DE)
- LDAX D ; -- GET OLD (HL)
- XCHG ; SWITCH
- MOV M,C ; PUT NEW (HL)
- STAX D ; PUT NEW (DE)
- INX H ; PT TO NEXT BYTE OF POINTER
- INX D
- MOV C,M ; GET OLD (HL)
- LDAX D ; GET OLD (DE)
- XCHG ; SWITCH
- MOV M,C ; PUT NEW (DE)
- STAX D ; PUT NEW (HL)
- RET
- ;
- ; ICOMPARE compares the entry pointed to by the pointer pointed to by HL
- ; with that pointed to by DE (1st level indirect addressing); on entry,
- ; HL and DE contain the numbers of the elements to compare (1, 2, ...);
- ; on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
- ; and Non-Zero and No-Carry means ((DE)) > ((HL))
- ;
- ICOMPARE:
- PUSH H ; SAVE HL
- LHLD ORDER ; ADDRESS OF ORDER - 2
- MOV B,H ; ... IN BC
- MOV C,L
- POP H
- DCX H ; ADJUST INDEX TO 0...N-1 FROM 1...N
- DAD H ; DOUBLE THE ELEMENT NUMBER TO POINT TO THE PTR
- DAD B ; ADD TO THIS THE BASE ADDRESS OF THE PTR TABLE
- XCHG ; RESULT IN DE
- DCX H ; ADJUST INDEX TO 0...N-1 FROM 1...N
- DAD H ; DO THE SAME WITH THE ORIGINAL DE
- DAD B
- XCHG
-
- ;
- ; HL NOW POINTS TO THE POINTER WHOSE INDEX WAS IN HL TO BEGIN WITH
- ; DE NOW POINTS TO THE POINTER WHOSE INDEX WAS IN DE TO BEGIN WITH
- ; FOR EXAMPLE, IF DE=5 AND HL=4, DE NOW POINTS TO THE 5TH PTR AND HL
- ; TO THE 4TH POINTER
- ;
- MOV C,M ; BC IS MADE TO POINT TO THE OBJECT INDEXED TO
- INX H ; ... BY THE ORIGINAL HL
- MOV B,M
- XCHG
- MOV E,M ; DE IS MADE TO POINT TO THE OBJECT INDEXED TO
- INX H ; ... BY THE ORIGINAL DE
- MOV D,M
- MOV H,B ; SET HL = OBJECT PTED TO INDIRECTLY BY BC
- MOV L,C
-
- ;
- ; COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
- ; NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
- ; RET W/ZERO SET MEANS DE=HL
- ;
- CMP$ENTRY:
- ;
- ; COMPARE BY FILE NAME, FILE TYPE, EXTENSION, AND USER NUM (IN THAT ORDER)
- ;
- PUSH H
- PUSH D
- INX H ; PT TO FN
- INX D
- MVI B,11 ; COMPARE FN, FT
- CALL COMP
- POP D
- POP H
- RNZ
- LDAX D ; COMPARE USER NUMBER
- CMP M
- RET
- ;
- ; COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
- ; MSB IS DISREGARDED
- ;
- COMP:
- MOV A,M ; GET (HL)
- ANI 7FH ; MASK MSB
- MOV C,A ; ... IN C
- LDAX D ; COMPARE
- ANI 7FH ; MASK MSB
- CMP C
- RNZ
- INX H ; PT TO NEXT
- INX D
- DCR B ; COUNT DOWN
- JNZ COMP
- RET
- ;
- ; AS COMP, BUT MATCH ON '?' PTED TO BY HL
- ;
- COMP2:
- MOV A,M ; GET (HL)
- ANI 7FH ; MASK MSB
- CPI '?' ; MATCH '?'
- JZ COMP2A
- MOV C,A ; ... IN C
- LDAX D ; COMPARE
- ANI 7FH ; MASK MSB
- CMP C
- RNZ
- COMP2A:
- INX H ; PT TO NEXT
- INX D
- DCR B ; COUNT DOWN
- JNZ COMP2
- RET
-
- ;
- ; SORT BUFFERS
- ;
- ORDER:
- DS 2 ; PTR TO ORDER TABLE
- DIRBUF:
- DS 2 ; POINTER TO DIRECTORY
- DSTART:
- DS 2 ; POINTER TO FIRST DIRECTORY ENTRY
- FCOUNT:
- DS 2 ; TOTAL NUMBER OF FILES/NUMBER OF SELECTED FILES
- HOLD:
- DS ESIZE ; EXCHANGE HOLD BUFFER FOR FCB'S
- PTPTR:
- DS 2 ; POINTER POINTER
- PTDIR:
- DS 2 ; DIRECTORY POINTER
- I:
- DS 2 ; INDEXES FOR SORT
- J:
- DS 2
- JG:
- DS 2
- N:
- DS 2 ; NUMBER OF ELEMENTS TO SORT
- GAP:
- DS 2 ; BINARY GAP SIZE
- ;
- ; THIS IS THE WORKING COPY OF THE BIOS JUMP TABLE
- ;
- WBOOT: DS 3
- CONST: DS 3
- CONIN: DS 3
- CONOUT: DS 3
- LIST: DS 3
- PUNCH: DS 3
- READER: DS 3
- HOME: DS 3
- SELDSK: DS 3
- SETTRK: DS 3
- SETSEC: DS 3
- SETDMA: DS 3
- READ: DS 3
- WRITE: DS 3
- LISTST: DS 3
- SECTRAN: DS 3
- ;
- DS 100 ;STACK DEPTH
- STACK:
- DS 2 ;LOCATION OF STACK
- ;
- ; DATA AREAS
- ;
- FNCOUNT:
- DS 1 ;NUMBER OF FILE NAMES FOUND
- CLPFLG: DS 1 ;0 FOR NO MATCH LOCALLY
- SYSTEM: DS 1 ;0 IF NO SYSTEM FILES
- ECOUNT: DS 1 ;COUNT OF ENTRIES PRINTED - 1
- FFLAG: DS 1 ;FILE FOUND FLAG (0=NO)
- TEMP: DS 2 ;TEMP STORAGE FOR FCB PRINT
- ;
- ; DISK PARAMETER DATA
- ;
- DPH: DS 2 ;ADDRESS OF DPH
- DIRMAX: DS 2 ;NUMBER OF SECTORS IN DIRECTORY =
- ; ; MAXIMUM NUMBER OF DIRECTORY ENTRIES
- ; ; DIVIDED BY 4 (ENTRIES PER SECTOR)
- EXTENT: DS 1 ;EXTENT MASK
- MAXSEC: DS 2 ;MAXIMUM NUMBER OF SECTORS/TRACK
- SECTOR: DS 2 ;CURRENT SECTOR NUMBER
- TRACK: DS 2 ;TRACK NUMBER OF DIRECTORY
-
- FNTAB: DS 11*40 ;ARBITRARILY LARGE
-
- SCRATCH EQU $/100H*100H+100H ;BEGINNING OF NEXT PAGE
-
- END