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
/
SYSLIB
/
SLIB1.LBR
/
SDIRQS.Z80
< prev
Wrap
Text File
|
2000-06-30
|
20KB
|
784 lines
;
; SYSLIB Module Name: SDIRQS
; Author: Richard Conn
; Part of SYSLIB3 SDIR Series
; SYSLIB Version Number: 3.6
; Module Version Number: 1.5
public dirqs
;
; EQUATES
;
CPM EQU 0
BDOS EQU 5
BUFF EQU 80H ; DMA BUFFER
ESIZE EQU 16 ; 16 BYTES/ENTRY
;
; GENERAL-PURPOSE DIRECTORY SELECT ROUTINE WITHOUT SIZING INFORMATION
; THIS ROUTINE SCANS FOR THE FCB PTED TO BY DE AND LOADS ALL ENTRIES
; WHICH MATCH IT INTO THE MEMORY BUFFER PTED TO BY HL. ON EXIT,
; BC=NUMBER OF FILES IN BUFFER, AND HL PTS TO FIRST FILE IN BUFFER.
; THE DIRECTORY BUFFER GENERATED BY DIRQ CONTAINS ENTRIES WHICH MAY NOT
; BE USED TO COMPUTE THE SIZE OF THE FILES USING THE FSIZE ROUTINE. THE
; DIRQS ROUTINE IS DESIGNED FOR THIS PURPOSE. THE BASIC TRADEOFF BETWEEN
; THE TWO ROUTINES IS THE DIRQ RUNS FASTER THAN DIRQS, AND THIS IS NOTICABLE
; IF THERE IS A SIGNIFICANT NUMBER OF FILES TO BE PROCESSED.
;
; THE DIRQ/DIRQS ROUTINES ARE INTENDED TO BE USED IN APPLICATIONS WHERE
; THE ONLY THING DESIRED IS A DIRECTORY LOAD OF THE CURRENT DIRECTORY
; (DISK AND USER). DIRF/DIRFS PROVIDE MORE FLEXIBILITY AT A GREATER COST
; IN TERMS OF SIZE.
;
; INPUT PARAMETERS:
; HL PTS TO BUFFER, DE PTS TO FCB, A IS SELECT FLAG:
; Bit 7 - Select Non-Sys, Bit 6 - Select Sys
; Bit 5 - Sort by File Name and Type (0) or other (1)
; Bits 4-0 - Unused
; OUTPUT PARAMETERS:
; HL PTS TO FIRST FILE IN BUFFER
; BC = NUMBER OF FILES
; A=0 and Z Flag Set if TPA Overflow
; DE UNCHANGED
;
DIRQS:
PUSH DE ; SAVE PTR TO FCB
LD (SELFLG),A ; SAVE SELECT FLAG FOR SELECTION AND ALPHA
LD (HOLD),HL ; SET PTR TO HOLD BUFFER
LD BC,36 ; ALLOW 36 BYTES
ADD HL,BC ; HL NOW POINTS TO TEMP FCB
LD (TFCB),HL ; SET PTR TO TEMP FCB
ADD HL,DE ; HL NOW PTS TO SCRATCH AREA
PUSH DE ; SAVE PTR TO FCB
CALL DBUFFER ; GET PTRS
POP DE ; GET PTR TO FCB
PUSH HL ; SAVE PTR TO BUFFER
CALL DIRLOAD ; LOAD DIRECTORY WITHOUT SIZING INFORMATION (FAST LOAD)
POP HL ; GET PTR TO BUFFER
POP DE ; GET PTR TO FCB
RET Z ; ABORT IF TPA OVERFLOW
PUSH AF ; SAVE FLAG TO INDICATE NO TPA OVERFLOW
CALL DIRALPHA ; ALPHABETIZE
POP AF ; GET PSW (TPA OVERFLOW FLAG)
RET
;
; THIS ROUTINE ACCEPTS A BASE ADDRESS FOR THE DYNAMIC BUFFERS
; REQUIRED, DETERMINES HOW MUCH SPACE IS REQUIRED FOR THE BUFFERS,
; AND SETS THE ORDER PTR TO PT TO THE FIRST AND DIRBUF TO PT TO
; THE SECOND (ORDER SPACE = DIRMAX*2 AND DIRBUF = DIRMAX * ESIZE)
; ON INPUT, HL PTS TO AVAILABLE BASE
; ON OUTPUT, HL PTS TO DIRBUF
; A=0 AND ZERO FLAG SET IF CCP OVERRUN
;
DBUFFER:
LD (ORDER),HL ; PT TO ORDER TABLE
CALL DPARAMS ; GET PARAMETERS
LD HL,(DIRMAX) ; NUMBER OF ENTRIES IN DIR
EX DE,HL ; ... IN DE
LD HL,(ORDER) ; ADD TO ORDER BASE
ADD HL,DE ; *1
CALL MEMCHK ; CHECK FOR WITHIN RANGE
ADD HL,DE ; HL PTS TO DIRBUF
CALL MEMCHK ; CHECK FOR WITHIN RANGE
LD (DIRBUF),HL ; SET PTR AND HL PTS TO DIRECTORY BUFFER
XOR A ; OK
DEC A ; SET FLAGS (NZ)
RET
MEMCHK:
PUSH HL ; SAVE REGS
PUSH DE
EX DE,HL ; NEXT ADDRESS IN DE
LD HL,(BDOS+1) ; GET ADDRESS OF BDOS
LD A,D ; CHECK FOR PAGE OVERRUN
CP H
JP NC,MEMORUN ; OVERRUN IF D>=H
POP DE
POP HL
RET
MEMORUN:
POP DE ; RESTORE
POP HL
POP AF ; CLEAR STACK
XOR A ; RETURN 0
RET
;
; THIS ROUTINE EXTRACTS DISK PARAMETER INFORMATON FROM THE DPB AND
; STORES THIS INFORMATION IN:
; BLKSHF <-- BLOCK SHIFT FACTOR (1 BYTE)
; BLKMSK <-- BLOCK MASK (1 BYTE)
; EXTENT <-- EXTENT MASK (1 BYTE) [NOT ANY MORE]
; BLKMAX <-- MAX NUMBER OF BLOCKS ON DISK (2 BYTES)
; DIRMAX <-- MAX NUMBER OF DIRECTORY ENTRIES (2 BYTES)
;
DPARAMS:
;
; VERSION 2.x OR MP/M
;
LD C,31 ; 2.x OR MP/M...REQUEST DPB
CALL BDOS
INC HL
INC HL
LD A,(HL) ; GET BLOCK SHIFT
LD (BLKSHF),A ; BLOCK SHIFT FACTOR
INC HL ; GET BLOCK MASK
LD A,(HL)
LD (BLKMSK),A ; BLOCK MASK
INC HL
INC HL
LD E,(HL) ; GET MAX BLOCK NUMBER
INC HL
LD D,(HL)
EX DE,HL
INC HL ; ADD 1 FOR MAX NUMBER OF BLOCKS
LD (BLKMAX),HL ; MAXIMUM NUMBER OF BLOCKS
EX DE,HL
INC HL
LD E,(HL) ; GET DIRECTORY SIZE
INC HL
LD D,(HL)
EX DE,HL
INC HL ; ADD 1 FOR NUMBER OF ENTRIES
LD (DIRMAX),HL ; MAXIMUM NUMBER OF DIRECTORY ENTRIES
RET
;
; BUILD DIRECTORY TABLE AT DIRBUF
; THIS IS THE OPTIMAL DIRECTORY LOAD ROUTINE; IT ONLY LOADS UNIQUE
; FILE NAMES FROM DISK, BUT THE INFORMATION IS NOT SUFFICIENT
; TO COMPUTE THE FILE SIZES
; ON INPUT, HL PTS TO DIRECTORY BUFFER (16 x N MAX)
; DE PTS TO FCB (ONLY 12 BYTES NEEDED)
; ON OUTPUT, BC IS NUM OF FILES
; A=0 AND ZERO FLAG SET IF TPA OVERFLOW
;
DIRLOAD:
LD (DSTART),HL ; SET START OF BUFFER AREA
INC DE ; PT TO FILE NAME
LD HL,(TFCB) ; PT TO TFCB
LD (HL),0 ; SELECT CURRENT DISK
INC HL ; PT TO FILE NAME IN TFCB
LD B,11 ; 11 CHARS
DLLOOP:
LD A,(DE) ; COPY
LD (HL),A
INC HL ; PT TO NEXT
INC DE
DEC B ; COUNT DOWN
JP NZ,DLLOOP
LD (HL),'?' ; SELECT ALL EXTENTS
INC HL ; PT TO NEXT CHAR
LD B,23 ; 23 CHARS
XOR A ; ZERO REST OF TFCB
DLLOOP1:
LD (HL),A ; STORE ZERO
INC HL ; PT TO NEXT
DEC B ; COUNT DOWN
JP NZ,DLLOOP1
;
; THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
;
LD HL,0 ; HL=0
LD (FCOUNT),HL ; TOTAL FILES ON DISK = 0
;
; NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
;
LD C,17 ; SEARCH FOR FILE
JP DIRLP1
DIRLP:
CALL PENTRY ; PLACE ENTRY IN DIR
JP Z,DIROVFL ; MEMORY OVERFLOW ERROR
LD C,18 ; SEARCH FOR NEXT MATCH
DIRLP1:
LD HL,(TFCB) ; PT TO FCB
EX DE,HL
CALL BDOS
CP 255 ; DONE?
JP NZ,DIRLP
;
; NOW WE ARE DONE WITH THE LOAD -- SET UP RETURN VALUES
;
DIRDN:
XOR A ; LOAD OK
DEC A ; SET FLAGS (NZ)
DIRDNX:
LD HL,(FCOUNT) ; GET TOTAL NUMBER OF FILES
LD B,H ; ... IN BC
LD C,L
RET
;
; MEMORY OVERFLOW ERROR
;
DIROVFL:
XOR A ; LOAD ERROR
JP DIRDNX
;
; PENTRY --
; PLACE ENTRY IN DIRECTORY BUFFER IF NOT AN ERASED ENTRY
;
; ON INPUT, A=0-3 FOR ADR INDEX IN BUFF OF ENTRY FCB
; FCOUNT=NUMBER OF FILES IN DIR SO FAR
; ON OUTPUT, FCOUNT=NUMBER OF FILES IN DIR SO FAR
; A=0 AND ZERO FLAG SET IF MEMORY OVERFLOW ERROR
;
PENTRY:
RRCA ; MULTIPLY BY 32 FOR OFFSET COMPUTATION
RRCA
RRCA
AND 60H ; A=BYTE OFFSET
LD DE,BUFF ; PT TO BUFFER ENTRY
LD L,A ; LET HL=OFFSET
LD H,0
ADD HL,DE ; HL=PTR TO FCB
;
; HL=ADR OF FCB IN BUFF
;
CALL ATTEST ; TEST ATTRIBUTES
JP Z,PEDONE ; SKIP IF ATTRIBUTE NOT DESIRED
;
; SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
; NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
; AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
; FOUND, RETURN WITH ZERO FLAG RESET (NZ)
;
CALL DUPENTRY ; CHECK FOR DUPLICATE AND SELECT EX
JP Z,PEDONE ; SKIP IF DUPLICATE
;
; COPY FCB PTED TO BY HL INTO DIRECTORY BUFFER
;
EX DE,HL ; SAVE PTR IN DE
LD HL,(DIRBUF) ; PT TO NEXT ENTRY LOCATION
EX DE,HL ; HL PTS TO FCB, DE PTS TO NEXT ENTRY LOCATION
LD B,ESIZE ; NUMBER OF BYTES/ENTRY
CALL SDMOVE ; COPY FCB INTO MEMORY BUFFER
EX DE,HL ; HL PTS TO NEXT ENTRY
LD (DIRBUF),HL ; SET PTR
EX DE,HL ; PTR TO NEXT ENTRY IN DE
LD HL,(BDOS+1) ; BASE ADDRESS OF BDOS IN HL
LD A,H ; GET BASE PAGE OF BDOS
SUB 9 ; COMPUTE 1 PAGE IN FRONT OF BASE PAGE OF CCP
CP D ; IS PTR TO NEXT ENTRY BEYOND THIS?
RET Z
; INCREMENT TOTAL NUMBER OF FILES
LD HL,(FCOUNT) ; TOTAL FILES = TOTAL FILES + 1
INC HL
LD (FCOUNT),HL
; DONE WITH PENTRY AND NO ERROR
PEDONE:
XOR A ; NO ERROR
DEC A ; SET FLAGS (NZ)
RET
;
; CHECK ATTRIBUTES OF FILE ENTRY PTED TO BY HL AGAINST SELFLG
; IF SYSTEM FILE AND SYSTEM ATTRIBUTE SET, RETURN NZ
; IF NORMAL FILE AND NORMAL ATTRIBUTE SET, RETURN NZ
;
ATTEST:
PUSH HL ; SAVE PTR
LD BC,10 ; PT TO SYSTEM ATTRIBUTE
ADD HL,BC
LD A,(HL) ; GET SYSTEM ATTRIBUTE
POP HL ; RESTORE PTR
AND 80H ; CHECK FOR SYS
LD A,(SELFLG) ; GET SELECTION FLAG
JP Z,ATDIR
AND 01000000B ; CHECK SYSTEM ATTRIBUTE
RET
ATDIR:
AND 10000000B ; CHECK NORMAL ATTRIBUTE
RET
;
; SCAN DIRECTORY ENTRIES AS LOADED SO FAR FOR ANOTHER ENTRY BY THE SAME
; NAME; IF FOUND, SET THAT ENTRY TO BE THE ENTRY WITH THE LARGER EX
; AND RETURN WITH THE ZERO FLAG SET, INDICATING NO NEW FILE; IF NOT
; FOUND, RETURN WITH ZERO FLAG RESET (NZ)
; ON INPUT, HL PTS TO ENTRY TO SCAN FOR, FCOUNT = NUMBER OF ENTRIES SO FAR,
; AND (DSTART) = STARTING ADDRESS OF DIRECTORY LOADED
; ON OUTPUT, A=0 AND ZERO FLAG SET IF DUPLICATE ENTRY FOUND; A=0FFH AND NZ
; IF NO DUP ENTRY FOUND
; ONLY HL NOT AFFECTED
;
DUPENTRY:
PUSH HL ; SAVE PTR TO ENTRY TO SCAN FOR
EX DE,HL ; PTR IN DE
LD HL,(FCOUNT) ; CHECK COUNT
LD A,H ; NO ENTRIES?
OR L
JP Z,NODUP ; NO DUPLICATE ENTRY RETURN
LD B,H ; BC=NUMBER OF ENTRIES
LD C,L
LD HL,(DSTART) ; HL PTS TO FIRST ENTRY
DUPELOOP:
PUSH BC ; SAVE COUNT
PUSH HL ; SAVE PTRS
PUSH DE
INC HL ; PT TO FN
INC DE
LD B,11 ; COMPARE FN AND FT
CALL COMP
JP NZ,NODUPL ; CONTINUE LOOKING FOR ANOTHER ENTRY
; DUPLICATE ENTRIES HAVE BEEN IDENTIFIED AT THIS POINT
LD A,(DE) ; GET EXTENT FIELD FROM TARGET
CP (HL) ; COMPARE WITH THAT IN DIRECTORY ENTRY
POP DE ; GET PTRS
POP HL
JP C,DUPSMALL
; NEW TARGET IS LARGER THAN STORED ENTRY
EX DE,HL ; HL PTS TO TARGET, DE PTS TO DIR ENTRY
LD B,ESIZE ; NUMBER OF BYTES TO MOVE
CALL SDMOVE ; MOVE IT
; NEW TARGET IS SMALLER THAN STORED ENTRY
DUPSMALL:
POP BC ; CLEAR COUNT FROM STACK
XOR A ; INDICATE DUP FOUND
POP HL ; RESTORE PTR TO ENTRY TO SCAN FOR
RET
; NO DUPLICATE FOUND; ADVANCE TO NEXT ENTRY
NODUPL:
POP DE ; RESTORE PTRS
POP HL
LD BC,ESIZE ; HL PTS TO CURRENT ENTRY IN BUFFER,
ADD HL,BC ; ... SO ADD ESIZE TO IT
POP BC ; GET COUNT
DEC BC ; COUNT DOWN
LD A,B ; CHECK FOR DONE
OR C
JP NZ,DUPELOOP
; NO DUPLICATE FOUND
NODUP:
XOR A ; INDICATE DUP NOT FOUND
DEC A ; SET FLAGS (NZ)
POP HL ; RESTORE PTR TO ENTRY TO SCAN FOR
RET
;
; DIRALPHA -- ALPHABETIZES DIRECTORY PTED TO BY HL; BC CONTAINS
; THE NUMBER OF FILES IN THE DIRECTORY AND A = SORT FLAG
; (0=SORT BY FILE NAME/TYPE, <>0 = SORT BY FILE TYPE/NAME)
;
DIRALPHA:
LD A,B ; ANY FILES?
OR C
RET Z
PUSH HL ; SAVE REGS
PUSH DE
PUSH BC
LD (DIRBUF),HL ; SAVE PTR TO DIRECTORY
PUSH HL ; SAVE HL
LD H,B ; HL=BC=FILE COUNT
LD L,C
LD (N),HL ; SET "N"
POP HL
;
; 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
;
SORT:
EX DE,HL ; POINTER TO DIRECTORY IN DE
LD HL,(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:
LD (HL),E ; STORE LOW-ORDER ADDRESS
INC HL ; PT TO NEXT ORDER BYTE
LD (HL),D ; STORE HIGH-ORDER ADDRESS
INC HL ; PT TO NEXT ORDER ENTRY
PUSH HL ; SAVE PTR
LD HL,ESIZE ; HL=NUMBER OF BYTES/ENTRY
ADD HL,DE ; PT TO NEXT DIR1 ENTRY
EX DE,HL ; DE PTS TO NEXT ENTRY
POP HL ; GET PTR TO ORDER TABLE
DEC BC ; COUNT DOWN
LD A,B ; DONE?
OR C
JP NZ,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
;
LD HL,(N) ; NUMBER OF ITEMS TO SORT
LD (GAP),HL ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
; FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
SRTL0:
OR A ; CLEAR CARRY
LD HL,(GAP) ; GET PREVIOUS GAP
LD A,H ; ROTATE RIGHT TO DIVIDE BY 2
RRA
LD H,A
LD A,L
RRA
LD L,A
; TEST FOR ZERO
OR H
JP Z,SDONE ; DONE WITH SORT IF GAP = 0
LD (GAP),HL ; SET VALUE OF GAP
LD (IVAL),HL ; SET I=GAP FOR FOLLOWING LOOP
; FOR (I = GAP + 1; I <= N; I = I + 1)
SRTL1:
LD HL,(IVAL) ; ADD 1 TO I
INC HL
LD (IVAL),HL
; TEST FOR I <= N
EX DE,HL ; I IS IN DE
LD HL,(N) ; GET N
LD A,L ; COMPARE BY SUBTRACTION
SUB E
LD A,H
SBC A,D ; CARRY SET MEANS I > N
JP C,SRTL0 ; DON'T DO FOR LOOP IF I > N
LD HL,(IVAL) ; SET J = I FOR FIRST SUBTRACTION OF GAP
LD (J),HL
; FOR (J = I - GAP; J > 0; J = J - GAP)
SRTL2:
LD HL,(GAP) ; GET GAP
EX DE,HL ; ... IN DE
LD HL,(J) ; GET J
LD A,L ; COMPUTE J - GAP
SUB E
LD L,A
LD A,H
SBC A,D
LD H,A
LD (J),HL ; J = J - GAP
JP C,SRTL1 ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
LD A,H ; J=0?
OR L
JP Z,SRTL1 ; IF ZERO, J=0 AND ABORT
; SET JG = J + GAP
EX DE,HL ; J IN DE
LD HL,(GAP) ; GET GAP
ADD HL,DE ; J + GAP
LD (JG),HL ; JG = J + GAP
; IF (V(J) <= V(JG))
CALL ICOMPARE ; J IN DE, JG IN HL
; ... THEN BREAK
JP C,SRTL1
; ... ELSE EXCHANGE
LD HL,(J) ; SWAP J, JG
EX DE,HL
LD HL,(JG)
CALL ISWAP ; J IN DE, JG IN HL
; END OF INNER-MOST FOR LOOP
JP SRTL2
;
; SORT IS DONE -- RESTRUCTURE DIR1 IN SORTED ORDER IN PLACE
;
SDONE:
LD HL,(N) ; NUMBER OF ENTRIES
LD B,H ; ... IN BC
LD C,L
LD HL,(ORDER) ; PTR TO ORDERED POINTER TABLE
LD (PTPTR),HL ; SET PTR PTR
LD HL,(DIRBUF) ; PTR TO UNORDERED DIRECTORY
LD (PTDIR),HL ; SET PTR DIR BUFFER
; FIND PTR TO NEXT DIR1 ENTRY
SRTDN:
LD HL,(PTPTR) ; PT TO REMAINING POINTERS
EX DE,HL ; ... IN DE
LD HL,(PTDIR) ; HL PTS TO NEXT DIR ENTRY
PUSH BC ; SAVE COUNT OF REMAINING ENTRIES
; FIND PTR TABLE ENTRY
SRTDN1:
LD A,(DE) ; GET CURRENT POINTER TABLE ENTRY VALUE
INC DE ; PT TO HIGH-ORDER POINTER BYTE
CP L ; COMPARE AGAINST DIR1 ADDRESS LOW
JP NZ,SRTDN2 ; NOT FOUND YET
LD A,(DE) ; LOW-ORDER BYTES MATCH -- GET HIGH-ORDER POINTER BYTE
CP H ; COMPARE AGAINST DIR1 ADDRESS HIGH
JP Z,SRTDN3 ; MATCH FOUND
SRTDN2:
INC DE ; PT TO NEXT PTR TABLE ENTRY
DEC BC ; COUNT DOWN
LD A,C ; END OF TABLE?
OR B
JP NZ,SRTDN1 ; CONTINUE IF NOT
; FATAL ERROR -- INTERNAL ERROR; POINTER TABLE NOT CONSISTENT
FERR$PTR:
LD E,7 ; RING BELL
LD C,2 ; OUTPUT
CALL BDOS
JP CPM
; 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:
LD HL,(PTPTR) ; GET PTR TO NEXT ORDERED ENTRY
DEC DE ; DE PTS TO LOW-ORDER POINTER ADDRESS
LD A,(HL) ; MAKE PTR TO NEXT UNORDERED DIR1 PT TO BUFFER FOR
LD (DE),A ; DIR1 ENTRY TO BE MOVED TO NEXT UNORDERED DIR1 POS
INC HL ; PT TO NEXT PTR ADDRESS
INC DE
LD A,(HL) ; MAKE HIGH POINT SIMILARLY
LD (DE),A
; COPY NEXT UNORDERED DIR1 ENTRY TO HOLD BUFFER
LD B,ESIZE ; B=NUMBER OF BYTES/ENTRY
LD HL,(HOLD) ; PT TO HOLD BUFFER
EX DE,HL
LD HL,(PTDIR) ; PT TO ENTRY
PUSH BC ; SAVE B=NUMBER OF BYTES/ENTRY
CALL SDMOVE
POP BC
; COPY TO-BE-ORDERED DIR1 ENTRY TO NEXT ORDERED DIR1 POSITION
LD HL,(PTPTR) ; POINT TO ITS POINTER
LD E,(HL) ; GET LOW-ADDRESS POINTER
INC HL
LD D,(HL) ; GET HIGH-ADDRESS POINTER
LD HL,(PTDIR) ; DESTINATION ADDRESS FOR NEXT ORDERED ENTRY
EX DE,HL ; HL PTS TO ENTRY TO BE MOVED, DE PTS TO DEST
PUSH BC ; SAVE B=NUMBER OF BYTES/ENTRY
CALL SDMOVE
POP BC
EX DE,HL ; HL PTS TO NEXT UNORDERED DIR1 ENTRY
LD (PTDIR),HL ; SET POINTER FOR NEXT LOOP
; COPY ENTRY IN HOLD BUFFER TO LOC PREVIOUSLY HELD BY LATEST ORDERED ENTRY
LD HL,(PTPTR) ; GET PTR TO PTR TO THE DESTINATION
LD E,(HL) ; GET LOW-ADDRESS POINTER
INC HL
LD D,(HL) ; HIGH-ADDRESS POINTER
LD HL,(HOLD) ; HL PTS TO HOLD BUFFER, DE PTS TO ENTRY DEST
CALL SDMOVE ; B=NUMBER OF BYTES/ENTRY
; POINT TO NEXT ENTRY IN POINTER TABLE
LD HL,(PTPTR) ; POINTER TO CURRENT ENTRY
INC HL ; SKIP OVER IT
INC HL
LD (PTPTR),HL
; COUNT DOWN
POP BC ; GET COUNTER
DEC BC ; COUNT DOWN
LD A,C ; DONE?
OR B
JP NZ,SRTDN
POP BC ; RESTORE REGS
POP DE
POP HL
RET ; DONE
;
; SWAP (Exchange) the pointers in the ORDER table whose indexes are in
; HL and DE
;
ISWAP:
PUSH HL ; SAVE HL
LD HL,(ORDER) ; ADDRESS OF ORDER TABLE - 2
LD B,H ; ... IN BC
LD C,L
POP HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
; OF ORIGINAL HL (1, 2, ...)
ADD HL,BC ; HL NOW PTS TO POINTER INVOLVED
EX DE,HL ; DE NOW PTS TO POINTER INDEXED BY HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; HL PTS TO OFFSET ADDRESS INDICATED BY INDEX
; OF ORIGINAL DE (1, 2, ...)
ADD HL,BC ; HL NOW PTS TO POINTER INVOLVED
LD C,(HL) ; EXCHANGE POINTERS -- GET OLD (DE)
LD A,(DE) ; -- GET OLD (HL)
EX DE,HL ; SWITCH
LD (HL),C ; PUT NEW (HL)
LD (DE),A ; PUT NEW (DE)
INC HL ; PT TO NEXT BYTE OF POINTER
INC DE
LD C,(HL) ; GET OLD (HL)
LD A,(DE) ; GET OLD (DE)
EX DE,HL ; SWITCH
LD (HL),C ; PUT NEW (DE)
LD (DE),A ; 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 HL ; SAVE HL
LD HL,(ORDER) ; ADDRESS OF ORDER - 2
LD B,H ; ... IN BC
LD C,L
POP HL
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; DOUBLE THE ELEMENT NUMBER TO POINT TO THE PTR
ADD HL,BC ; ADD TO THIS THE BASE ADDRESS OF THE PTR TABLE
EX DE,HL ; RESULT IN DE
DEC HL ; ADJUST INDEX TO 0...N-1 FROM 1...N
ADD HL,HL ; DO THE SAME WITH THE ORIGINAL DE
ADD HL,BC
EX DE,HL
;
; 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
;
LD C,(HL) ; BC IS MADE TO POINT TO THE OBJECT INDEXED TO
INC HL ; ... BY THE ORIGINAL HL
LD B,(HL)
EX DE,HL
LD E,(HL) ; DE IS MADE TO POINT TO THE OBJECT INDEXED TO
INC HL ; ... BY THE ORIGINAL DE
LD D,(HL)
LD H,B ; SET HL = OBJECT PTED TO INDIRECTLY BY BC
LD 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:
LD A,(SELFLG) ; GROUP BY FILE TYPE?
AND 00100000B
JP Z,CMP$FN$FT
;
; COMPARE BY FILE TYPE AND FILE NAME (IN THAT ORDER)
;
PUSH HL
PUSH DE
LD BC,9 ; PT TO FT (8 BYTES + 1 BYTE FOR USER NUMBER)
ADD HL,BC
EX DE,HL
ADD HL,BC
EX DE,HL ; DE, HL NOW PT TO THEIR FT'S
LD B,3 ; 3 BYTES
CALL COMP ; COMPARE FT'S
POP DE
POP HL
RET NZ ; CONTINUE IF COMPLETE MATCH
LD B,8 ; 8 BYTES
JP CMP$FT1
;
; COMPARE BY FILE NAME AND FILE TYPE (IN THAT ORDER)
;
CMP$FN$FT:
LD B,11 ; 11 BYTES FOR FN AND FT
CMP$FT1:
PUSH HL
PUSH DE
INC HL ; PT TO FN
INC DE
CALL COMP ; DO COMPARISON
POP DE
POP HL
RET
;
; COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
; MSB IS DISREGARDED
;
COMP:
LD A,(HL) ; GET (HL)
AND 7FH ; MASK MSB
LD C,A ; ... IN C
LD A,(DE) ; COMPARE
AND 7FH ; MASK MSB
CP C
RET NZ
INC HL ; PT TO NEXT
INC DE
DEC B ; COUNT DOWN
JP NZ,COMP
RET
;
; COPY FROM HL TO DE FOR B BYTES
;
SDMOVE:
LD A,(HL) ; COPY
LD (DE),A
INC HL ; PT TO NEXT
INC DE
DEC B ; COUNT DOWN
JP NZ,SDMOVE
RET
;
; BUFFERS
;
HOLD:
DS 2 ; EXCHANGE HOLD BUFFER FOR FCB'S
PTPTR:
DS 2 ; POINTER POINTER
PTDIR:
DS 2 ; DIRECTORY POINTER
IVAL:
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
TFCB:
DS 2 ; ADDRESS OF TEMPORARY FCB
DSTART:
DS 2 ; POINTER TO FIRST DIRECTORY ENTRY
FCOUNT:
DS 2 ; TOTAL NUMBER OF FILES/NUMBER OF SELECTED FILES
BLKSHF:
DB 0 ; BLOCK SHIFT FACTOR
BLKMSK:
DB 0 ; BLOCK MASK
BLKMAX:
DW 0 ; MAX NUMBER OF BLOCKS
DIRMAX:
DW 0 ; MAX NUMBER OF DIRECTORY ENTRIES
SELFLG:
DB 0 ; FILE ATTRIBUTE FLAG
ORDER:
DW 0 ; POINTER TO ORDER TABLE
DIRBUF:
DW 0 ; POINTER TO DIRECTORY
END