home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
FINDF.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
22KB
|
1,050 lines
; PROGRAM: FINDF
; AUTHOR: RICHARD CONN
; VERSION: 2.0
; DATE: 18 May 84
; PREVIOUS VERSIONS: 1.1 (25 July 83), 1.0 (24 JULY 83)
;
VERS EQU 20 ;version number
z3env SET 0f400h
;
; FINDF searches through all of the known disks for one or more
; files matching the passed file specification. AFNs (Ambiguous File Names)
; are permitted. FINDF is invoked by the following command line:
; FINDF afn,afn,afn,... o
; where "afn" refers to the file sought and "o" is none or more of:
; S - Include System Files
;
;
; 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
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
;
; SYSLIB and Z3LIB Routines
;
ext z3init,codend
ext cout,crlf,print,padc
;
; Environment Definition
;
if z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
jmp start
db 'Z3ENV' ;This is a ZCPR3 Utility
db 1 ;External Environment Descriptor
z3eadr:
dw z3env
start:
lhld z3eadr ;pt to ZCPR3 environment
;
else
;
; Internal ZCPR3 Environment Descriptor
;
MACLIB Z3BASE.LIB
MACLIB SYSENV.LIB
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
;
call z3init ;initialize the ZCPR3 Env and the VLIB Env
LXI H,0 ;SAVE STACK PTR
DAD SP
SHLD STACK
CALL CODEND ;DETERMINE FREE SPACE
SHLD FNTAB ;FILE NAME TABLE
LXI D,512 ;1/2 K SPACE
DAD D
SHLD SCRATCH ;BEGINNING OF SCRATCH AREA
SPHL ;AND TOP OF STACK
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 'FINDF, 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,'Syntax:'
DB CR,LF,' FINDF afn,afn,afn,... o'
db cr,lf,'Options:'
DB CR,LF,' S - Include System Files'
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
LHLD FNTAB ;PT TO TABLE
XCHG ;... IN DE
LXI H,TBUFF+1 ;SCAN THRU TBUFF, BUILDING A FILE NAME TABLE
CALL SBLANK ;SKIP BLANKS
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 COUT
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 NXTDISK ;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
PUSH H
LHLD FNTAB ;PT TO TABLE
XCHG ;... IN DE
POP H
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
MVI A,31 ;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
;
; ADVANCE TO NEXT DISK
;
NXTDISK:
LXI B,TBUFF ;SET DMA ADDRESS
CALL SETDMA
LDA FCB
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 COUT
CALL PRINT
DB ' --',CR,LF,0
LHLD 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
;
; 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:
CALL PRINT ;2 SPACES
DB ' ',0
MOV A,M ;GET USER NUMBER
CALL PADC ;PRINT IT
MVI A,':'
CALL COUT
INX H
PR0:
MVI B,8
CALL PR1
MVI A,'.'
CALL COUT
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 COUT
INX H
DCR B
JNZ PR1
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
;
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 2 ;FILE NAME TABLE
SCRATCH:
DS 2 ;SCRATCH AREA
END