home *** CD-ROM | disk | FTP | other *** search
Text File | 1984-04-29 | 32.1 KB | 1,377 lines |
- ;
- ; SYSLIB Module Name: SDIR
- ; Author: Richard Conn
- ; SYSLIB Version Number: 2.0
- ; Module Version Number: 1.0
- ; Module Entry Points:
- ; DBUFFER DFREE DIRALPHA DIRF
- ; DIRFS DIRLOAD DIRNPACK DIRPACK
- ; DIRSEL DIRSLOAD DPARAMS FSIZE
- ; Module External References:
- ; PRINT
- ;
- ;*
- ;* EXTERNALS
- ;*
- EXT PRINT ; PRINT STRING PTED TO BY RETURN ADDRESS
-
- ;*
- ;* BASIC EQUATES
- ;*
- CPM EQU 0 ; CP/M WARM BOOT
- BIOS EQU CPM+1 ; BIOS BASE ADDRESS
- BDOS EQU CPM+5 ; BDOS ENTRY POINT
- ESIZE EQU 16 ; NUMBER OF BYTES/ENTRY IN MEMORY BUFFER
- BUFF EQU CPM+80H ; DEFAULT DMA BUFFER
-
- ;**************************************************************************
-
- ;*
- ;* 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 DIRF CONTAINS ENTRIES WHICH MAY NOT
- ;* BE USED TO COMPUTE THE SIZE OF THE FILES USING THE FSIZE ROUTINE. THE
- ;* DIRFS ROUTINE IS DESIGNED FOR THIS PURPOSE. THE BASIC TRADEOFF BETWEEN
- ;* THE TWO ROUTINES IS THE DIRF RUNS FASTER THAN DIRFS, AND THIS IS NOTICABLE
- ;* IF THERE IS A SIGNIFICANT NUMBER OF FILES TO BE PROCESSED.
- ;*
- ;* 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 - Select All Users, Bits 4-0 - User Number
- ;* OUTPUT PARAMETERS:
- ;* HL PTS TO FIRST FILE IN BUFFER
- ;* BC = NUMBER OF FILES
- ;* PSW, DE UNCHANGED
- ;*
- DIRF::
- PUSH PSW ; SAVE PSW
- PUSH D ; SAVE PTR TO FCB
-
- ORI 20H ; SET ALL USERS DUE TO THE WAY DIRLOAD WORKS
- STA SELFLG ; SAVE SELECT FLAG FOR DIRSEL
-
- CALL DBUFFER ; GET PTRS
-
- CALL DIRLOAD ; LOAD DIRECTORY WITHOUT SIZING INFORMATION (FAST LOAD)
-
- POP D ; GET PTR TO FCB
- LDA SELFLG ; GET SELECT FLAG
- CALL DIRSEL ; SELECT FILES
-
- CALL DIRPACK ; PACK DIRECTORY
-
- MVI A,0 ; SORT FLAG
- CALL DIRALPHA ; ALPHABETIZE
-
- POP PSW ; GET PSW
- RET
-
- ;**************************************************************************
-
- ;*
- ;* BUFFERS
- ;*
- TFCB:
- DB 0,'???????????',0,0,0,0 ; TEMPORARY FCB (FN,FT WILD)
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- DB 0,0,0
- BLKSHF:
- DS 1 ; BLOCK SHIFT FACTOR
- BLKMSK:
- DS 1 ; BLOCK MASK
- BLKMAX:
- DS 2 ; MAX NUMBER OF BLOCKS
- DIRMAX:
- DS 2 ; MAX NUMBER OF DIRECTORY ENTRIES
- SELFLG:
- DS 1 ; FILE ATTRIBUTE FLAG
- CMP$FLAG:
- DS 1 ; 0=SORT BY FILE NAME/TYPE, ELSE BY TYPE/NAME
- ORDER:
- DS 2 ; POINTER TO ORDER TABLE
- DIRBUF:
- DS 2 ; POINTER TO DIRECTORY
- DSTART:
- DS 2 ; POINTER TO FIRST DIRECTORY ENTRY
- EXTENT:
- DB 0 ; NUMBER OF EXTENT "0" (INITIALIZED TO 0)
- FCOUNT:
- DS 2 ; TOTAL NUMBER OF FILES/NUMBER OF SELECTED FILES
- HOLD:
- DS 35 ; 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
-
- ;**************************************************************************
-
- ;*
- ;* GENERAL-PURPOSE DIRECTORY SELECT ROUTINE WITH 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 DIRFS CONTAINS ENTRIES WHICH MAY
- ;* BE USED TO COMPUTE THE SIZE OF THE FILES USING THE FSIZE ROUTINE. THE
- ;* DIRFS ROUTINE IS DESIGNED FOR THIS PURPOSE. THE BASIC TRADEOFF BETWEEN
- ;* THE DIRF AND DIRFS ROUTINES IS THE DIRF RUNS FASTER THAN DIRFS, AND THIS
- ;* IS NOTICABLE IF THERE IS A SIGNIFICANT NUMBER OF FILES TO BE PROCESSED.
- ;*
- ;* 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 - Select All Users, Bits 4-0 - User Number
- ;* OUTPUT PARAMETERS:
- ;* HL PTS TO FIRST FILE IN BUFFER
- ;* BC = NUMBER OF FILES
- ;* PSW, DE UNCHANGED
- ;*
- DIRFS::
- PUSH PSW ; SAVE PSW
- PUSH D ; SAVE PTR TO FCB
-
- STA SELFLG ; SAVE SELECT FLAG FOR DIRSEL
-
- CALL DBUFFER ; GET PTRS
-
- CALL DIRSLOAD ; LOAD DIRECTORY WITH SIZING INFORMATION
-
- POP D ; GET PTR TO FCB
- LDA SELFLG ; GET SELECT FLAG
- CALL DIRSEL ; SELECT FILES
-
- CALL DIRPACK ; PACK DIRECTORY
-
- MVI A,0 ; SORT FLAG
- CALL DIRALPHA ; ALPHABETIZE
-
- POP PSW ; GET PSW
- 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 BDOS OVERRUN
- ;*
- DBUFFER::
- PUSH D ; SAVE DE
- PUSH B ; SAVE BC
- SHLD ORDER ; PT TO ORDER TABLE
- CALL DPARAMS ; GET PARAMETERS
- LHLD DIRMAX ; NUMBER OF ENTRIES IN DIR
- XCHG ; ... IN DE
- LHLD ORDER ; ADD TO ORDER BASE
- DAD D ; *1
- CALL MEMCHK ; CHECK FOR WITHIN RANGE
- DAD D ; HL PTS TO DIRBUF
- CALL MEMCHK ; CHECK FOR WITHIN RANGE
- SHLD DIRBUF ; SET PTR AND HL PTS TO DIRECTORY BUFFER
- POP B ; RESTORE BC
- POP D ; RESTORE DE
- MVI A,0FFH ; OK
- ORA A ; SET FLAGS
- RET
-
- MEMCHK:
- PUSH H ; SAVE REGS
- PUSH D
- XCHG ; NEXT ADDRESS IN DE
- LHLD BDOS+1 ; GET ADDRESS OF BDOS
- MOV A,D ; CHECK FOR PAGE OVERRUN
- CMP H
- JNC MEMORUN ; OVERRUN IF D>=H
- POP D
- POP H
- RET
- MEMORUN:
- POP D ; RESTORE
- POP H
- XRA A ; RETURN 0
- POP B ; CLEAR STACK
- POP B ; RESTORE BC
- 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)
- ;* BLKMAX <-- MAX NUMBER OF BLOCKS ON DISK (2 BYTES)
- ;* DIRMAX <-- MAX NUMBER OF DIRECTORY ENTRIES (2 BYTES)
- ;*
- DPARAMS::
- PUSH B ; SAVE REGS
- PUSH D
- PUSH H
- PUSH PSW
- MVI C,12 ; GET VERSION NUMBER
- CALL BDOS
- MOV A,H ; CHECK FOR 1.4
- ORA L
- JZ DPARM1 ; PRE-2.x...GET PARAMS THE 1.4 WAY
-
- ;*
- ;* VERSION 2.x OR MP/M
- ;*
- MVI C,31 ; 2.x OR MP/M...REQUEST DPB
- CALL BDOS
- INX H
- INX H
- MOV A,M ; GET BLOCK SHIFT
- STA BLKSHF ; BLOCK SHIFT FACTOR
- INX H ; GET BLOCK MASK
- MOV A,M
- STA BLKMSK ; BLOCK MASK
- INX H
- MOV A,M ; GET MAX EXTENT NUMBER
- STA EXTENT ; THIS IS CALLED THE EXTENT MASK
- INX H
- MOV E,M ; GET MAX BLOCK NUMBER
- INX H
- MOV D,M
- XCHG
- INX H ; ADD 1 FOR MAX NUMBER OF BLOCKS
- SHLD BLKMAX ; MAXIMUM NUMBER OF BLOCKS
- XCHG
- INX H
- MOV E,M ; GET DIRECTORY SIZE
- INX H
- MOV D,M
- XCHG
- INX H ; ADD 1 FOR NUMBER OF ENTRIES
- SHLD DIRMAX ; MAXIMUM NUMBER OF DIRECTORY ENTRIES
- JMP DPARM2
-
- ;*
- ;* CP/M 1.4
- ;*
- DPARM1:
- LHLD BDOS+1 ; GET PARAMS 1.4 STYLE
- MVI L,3BH ; POINT TO DIRECTORY SIZE ENTRY IN 1.4 BDOS
- MOV E,M ; GET IT
- MVI D,0 ; FORCE HI ORDER BYTE TO 0
- XCHG ; SAVE SIZE OF DIRECTORY ENTRY
- INX H ; ADD 1
- SHLD DIRMAX ; MAXIMUM NUMBER OF ENTRIES
- XCHG
- INX H ; POINT TO BLOCK SHIFT
- MOV A,M
- STA BLKSHF ; BLOCK SHIFT FACTOR
- INX H ; POINT TO BLOCK MASK
- MOV A,M
- STA BLKMSK ; BLOCK MASK
- INX H
- MOV E,M ; GET MAXIMUM BLOCK NUMBER
- MVI D,0
- XCHG
- INX H ; ADD 1
- SHLD BLKMAX ; MAXIMUM NUMBER OF BLOCKS
- XRA A ; A=0
- STA EXTENT ; SET EXTENT MASK TO 0 FOR CP/M 1.4 EXTENT SIZE
-
- ;*
- ;* ALL PARAMETERS EXTRACTED
- ;*
- DPARM2:
- POP PSW ; RESTORE REGS
- POP H
- POP D
- POP B
- RET
-
- ;**************************************************************************
-
- ;*
- ;* COMPUTE AMOUNT OF FREE SPACE LEFT ON DISK
- ;* ON EXIT, DE=AMOUNT OF FREE SPACE ON DISK IN K
- ;* THE DPARAMS ROUTINE MUST BE CALLED BEFORE THIS ROUTINE IS USED
- ;*
- DFREE::
- PUSH B ; SAVE REGS
- PUSH H
- PUSH PSW
- MVI C,27 ; GET ADDRESS OF ALLOCATION VECTOR
- CALL BDOS
- XCHG
- LHLD BLKMAX ; GET LENGTH OF ALLOCATION VECTOR
- LXI B,0 ; INIT BLOCK COUNT TO 0
-
- ;*
- ;* BC IS ACCUMULATOR FOR SPACE
- ;*
- FREE1:
- PUSH D ; SAVE ALLOC ADDRESS
- LDAX D ; GET BIT PATTERN OF ALLOCATION BYTE
- MVI E,8 ; SET TO PROCESS 8 BLOCKS
- FREE2:
- RAL ; ROTATE ALLOCATED BLOCK BIT INTO CARRY FLAG
- JC FREE3 ; IF SET (BIT=1), BLOCK IS ALLOCATED
- INX B ; IF NOT SET, BLOCK IS NOT ALLOCATED, SO INCREMENT
- ; FREE BLOCK COUNT
- FREE3:
- MOV D,A ; SAVE REMAINING ALLOCATION BITS IN D
- DCX H ; COUNT DOWN NUMBER OF BLOCKS ON DISK
- MOV A,L
- ORA H
- JZ FREE4 ; DONE IF NO MORE BLOCKS LEFT
- MOV A,D ; A=CURRENT ALLOCATION BIT PATTERN
- DCR E ; HAVE ALL 8 BITS BEEN EXAMINED?
- JNZ FREE2 ; CONTINUE IF NOT
- POP D ; GET POINTER TO ALLOCATION VECTOR
- INX D ; POINT TO NEXT ALLOCATION BYTE
- JMP FREE1 ; CONTINUE BY PROCESSING NEXT ALLOCATION BYTE
-
- ;*
- ;* BC = TOTAL AMOUNT OF FREE SPACE IN TERMS OF BLOCKS
- ;*
- FREE4:
- POP D ; CLEAR DE FROM STACK
- MOV L,C ; HL=BC=NUMBER OF FREE BLOCKS
- MOV H,B
- LDA BLKSHF ; GET BLOCK SHIFT FACTOR
- SUI 3 ; CONVERT NUMBER OF BLOCKS TO K
- JZ FREE6 ; DONE IF SINGLE DENSITY (1K PER BLOCK)
-
- ;*
- ;* WE ARE AT A MORE ADVANCED DENSITY LEVEL; MULTIPLY THE NUMBER OF BLOCKS
- ;* BY THE SIZE OF A BLOCK IN K
- ;*
- FREE5:
- DAD H ; 2, 4, 8, 16, ETC K/BLK, SO BLOCK SHIFT FACTOR
- DCR A ; IS A POWER-OF-TWO MULTIPLE
- JNZ FREE5
-
- ;*
- ;* AT THIS POINT, HL=AMOUNT OF FREE SPACE ON DISK IN K
- ;*
- FREE6:
- XCHG ; DE=ANSWER
- POP PSW ; RESTORE REGS
- POP H
- POP B
- RET
-
- ;**************************************************************************
-
- ;*
- ;* COMPUTE SIZE OF FILE WHOSE LAST EXTENT IS POINTED TO BY HL
- ;* FILE SIZE IS RETURNED IN DE IN K
- ;* NOTE THAT THE ROUTINE DPARAMS MUST HAVE BEEN CALLED BEFORE THIS ROUTINE
- ;* IS USED
- ;*
- FSIZE::
- PUSH B ; SAVE REGS
- PUSH H
- PUSH PSW
- LXI D,12 ; POINT TO EXTENT
- DAD D
- MOV E,M ; GET EXTENT #
- MVI D,0
- INX H ; SKIP S1
- INX H ; SKIP S2
- INX H ; HL PTS TO RECORD COUNT FIELD
- MOV A,M ; GET RECORD COUNT OF LAST EXTENT
- XCHG
- DAD H ; NUMBER OF EXTENTS TIMES 16K
- DAD H
- DAD H
- DAD H
- XCHG ; TOTAL SIZE OF PREVIOUS EXTENTS IN DE
- LXI H,BLKMSK
- ADD M ; ROUND LAST EXTENT TO BLOCK SIZE
- RRC
- RRC ; CONVERT FROM RECORDS TO K
- RRC
- ANI 1FH
- MOV L,A ; ADD SIZE OF LAST EXTENT TO TOTAL OF PREVIOUS EXTENTS
- MVI H,0 ; HL=SIZE OF LAST EXTENT, DE=TOTAL OF PREVIOUS EXTENTS
- DAD D ; HL=TOTAL FILE SIZE IN BLOCKS
- LDA BLKMSK ; GET RECORDS/BLK-1
- RRC
- RRC ; CONVERT TO K/BLK
- RRC
- ANI 1FH
- CMA ; USE TO FINISH ROUNDING
- ANA L
- MOV L,A ; HL NOW EQUALS THE SIZE OF THE FILE IN K INCREMENTS
- XCHG ; DE=FILE SIZE IN K
- POP PSW ; RESTORE REGS
- POP H
- POP B
- 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)
- ;* ON OUTPUT, BC IS NUM OF FILES
- ;* DE, HL, PSW UNAFFECTED
- ;*
- DIRLOAD::
- PUSH H ; SAVE REGISTERS
- PUSH D
- XRA A ; JUST SELECT FILES FROM CURRENT DISK
- STA TFCB ; SET DR FIELD TO ZERO TO DO THIS
- SHLD DIRBUF ; SAVE PTR TO DIRECTORY BUFFER
- ;*
- ;* THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
- ;*
- LXI H,0 ; HL=0
- SHLD FCOUNT ; TOTAL FILES ON DISK = 0
- ;*
- ;* NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
- ;*
- MVI C,17 ; SEARCH FOR FILE
- LXI D,TFCB ; PT TO WILD NAME
- CALL BDOS
- CPI 255 ; NO MATCH?
- JZ DIRDN
- DIRLP:
- CALL PENTRY ; PLACE ENTRY IN DIR
- JZ DIROVFL ; MEMORY OVERFLOW ERROR
- MVI C,18 ; SEARCH FOR NEXT MATCH
- CALL BDOS
- CPI 255 ; DONE?
- JNZ DIRLP
- ;*
- ;* NOW WE ARE DONE WITH THE LOAD -- SET UP RETURN VALUES
- ;*
- DIRDN:
- MVI A,0FFH ; LOAD OK
- ORA A ; SET FLAGS
- DIRDNX:
- LHLD FCOUNT ; GET TOTAL NUMBER OF FILES
- MOV B,H ; ... IN BC
- MOV C,L
- ;*
- ;* RESTORE REGISTERS AND RETURN
- ;*
- POP D
- POP H
- RET
- ;*
- ;* MEMORY OVERFLOW ERROR
- ;*
- DIROVFL:
- XRA A ; LOAD ERROR
- JMP 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:
- PUSH B ; SAVE REGS
- PUSH D
- PUSH H
- RRC ; MULTIPLY BY 32 FOR OFFSET COMPUTATION
- RRC
- RRC
- ANI 60H ; A=BYTE OFFSET
- LXI D,BUFF ; PT TO BUFFER ENTRY
- MOV L,A ; LET HL=OFFSET
- MVI H,0
- DAD D ; HL=PTR TO FCB
- MOV A,M ; GET USER NUMBER
- CPI 0E5H ; DELETED?
- JZ PEDONE ; SKIP IT IF DELETED
- ;*
- ;* HL=ADR OF FCB IN BUFF
- ;*
-
- ;* INCREMENT TOTAL NUMBER OF FILES
- PUSH H ; SAVE PTR TO FCB
- LHLD FCOUNT ; TOTAL FILES = TOTAL FILES + 1
- INX H
- SHLD FCOUNT
- POP H ; GET PTR TO FCB
-
- ;*
- ;* COPY FCB PTED TO BY HL INTO DIRECTORY BUFFER
- ;*
- XCHG ; SAVE PTR IN DE
- LHLD DIRBUF ; PT TO NEXT ENTRY LOCATION
- XCHG ; HL PTS TO FCB, DE PTS TO NEXT ENTRY LOCATION
- MVI B,ESIZE ; NUMBER OF BYTES/ENTRY
- CALL MOVE ; COPY FCB INTO MEMORY BUFFER
- XCHG ; HL PTS TO NEXT ENTRY
- SHLD DIRBUF ; SET PTR
- XCHG ; PTR TO NEXT ENTRY IN DE
- LHLD BDOS+1 ; BASE ADDRESS OF BDOS IN HL
- MOV A,H ; GET BASE PAGE OF BDOS
- SUI 9 ; COMPUTE 1 PAGE IN FRONT OF BASE PAGE OF CCP
- CMP D ; IS PTR TO NEXT ENTRY BEYOND THIS?
- JNZ PEDONE ; OK IF NOT AT BUFFER OVERFLOW LEVEL
-
- ;* DONE WITH PENTRY WITH MEMORY OVERFLOW ERROR
- PEOVFL:
- XRA A ; ERROR
- POP H ; RESTORE REGS
- POP D
- POP B
- RET
-
- ;* DONE WITH PENTRY AND NO ERROR
- PEDONE:
- MVI A,0FFH ; NO ERROR
- ORA A ; SET FLAGS
- POP H ; RESTORE REGS
- POP D
- POP B
- RET
-
- ;*
- ;* COPY FROM HL TO DE FOR B BYTES
- ;*
- MOVE:
- MOV A,M ; GET BYTE
- STAX D ; PUT BYTE
- INX H ; PT TO NEXT
- INX D
- DCR B ; COUNT DOWN
- JNZ MOVE
- RET
-
- ;**************************************************************************
-
- ;*
- ;* BUILD DIRECTORY TABLE AT DIRBUF
- ;* THIS DIRECTORY LOAD ROUTINE IS MUST LESS EFFICIENT THAN DIRLOAD,
- ;* BUT IT DOES LOAD ENOUGH INFORMATION TO COMPUTE THE FILE
- ;* SIZES USING THE FSIZE ROUTINE
- ;* ON INPUT, HL PTS TO DIRECTORY BUFFER (16 x N MAX)
- ;* ON OUTPUT, BC IS NUM OF FILES
- ;* DE, HL, PSW UNAFFECTED
- ;*
- DIRSLOAD::
- PUSH H ; SAVE REGISTERS
- PUSH D
- MVI A,'?' ; SELECT ALL ENTRIES FROM CURRENT DISK
- STA TFCB ; SET DR FIELD TO '?' TO DO THIS
- SHLD DIRBUF ; SAVE PTR TO DIRECTORY BUFFER
- SHLD DSTART ; SET PTR TO FIRST DIRECTORY ELEMENT
- ;*
- ;* THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
- ;*
- LXI H,0 ; HL=0
- SHLD FCOUNT ; TOTAL FILES ON DISK = 0
- ;*
- ;* NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
- ;*
- MVI C,17 ; SEARCH FOR FILE
- LXI D,TFCB ; PT TO WILD NAME
- CALL BDOS
- CPI 255 ; NO MATCH?
- JZ DIRDN
- DIRSLP:
- CALL PSENTRY ; PLACE ENTRY IN DIR
- JZ DIROVFL ; MEMORY OVERFLOW ERROR
- MVI C,18 ; SEARCH FOR NEXT MATCH
- CALL BDOS
- CPI 255 ; DONE?
- JNZ DIRSLP
- JMP DIRDN ; DONE
-
- ;*
- ;* PSENTRY --
- ;* PLACE ENTRY IN DIRECTORY BUFFER IF NOT AN ERASED ENTRY
- ;* IF ANOTHER ENTRY BY THE SAME NAME IS ALREADY THERE, DETERMINE WHICH
- ;* HAS THE LARGER EXTENT AND PLACE THAT ONE
- ;*
- ;* 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
- ;*
- PSENTRY:
- PUSH B ; SAVE REGS
- PUSH D
- PUSH H
- RRC ; MULTIPLY BY 32 FOR OFFSET COMPUTATION
- RRC
- RRC
- ANI 60H ; A=BYTE OFFSET
- LXI D,BUFF ; PT TO BUFFER ENTRY
- MOV L,A ; LET HL=OFFSET
- MVI H,0
- DAD D ; HL=PTR TO FCB
- MOV A,M ; GET USER NUMBER
- CPI 0E5H ; DELETED?
- JZ PEDONE ; SKIP IT IF DELETED
- ;*
- ;* HL=ADR OF FCB IN BUFF
- ;*
-
- ;*
- ;* 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 ; SCAN FOR DUPLICATE ENTRIES (BY NAME ONLY)
- JZ PEDONE ; SKIP IF DUPLICATE
-
- ;* INCREMENT TOTAL NUMBER OF FILES
- PUSH H ; SAVE PTR TO FCB
- LHLD FCOUNT ; TOTAL FILES = TOTAL FILES + 1
- INX H
- SHLD FCOUNT
- POP H ; GET PTR TO FCB
-
- ;*
- ;* COPY FCB PTED TO BY HL INTO DIRECTORY BUFFER
- ;*
- XCHG ; SAVE PTR IN DE
- LHLD DIRBUF ; PT TO NEXT ENTRY LOCATION
- XCHG ; HL PTS TO FCB, DE PTS TO NEXT ENTRY LOCATION
- MVI B,ESIZE ; NUMBER OF BYTES/ENTRY
- CALL MOVE ; COPY FCB INTO MEMORY BUFFER
- XCHG ; HL PTS TO NEXT ENTRY
- SHLD DIRBUF ; SET PTR
- XCHG ; PTR TO NEXT ENTRY IN DE
- LHLD BDOS+1 ; BASE ADDRESS OF BDOS IN HL
- MOV A,H ; GET BASE PAGE OF BDOS
- SUI 9 ; COMPUTE 1 PAGE IN FRONT OF BASE PAGE OF CCP
- CMP D ; IS PTR TO NEXT ENTRY BEYOND THIS?
- JNZ PEDONE ; OK IF NOT AT BUFFER OVERFLOW LEVEL
-
- ;* DONE WITH PENTRY WITH MEMORY OVERFLOW ERROR
- JMP PEOVFL
-
- ;*
- ;* 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 H ; SAVE PTR TO ENTRY TO SCAN FOR
- XCHG ; PTR IN DE
- LHLD FCOUNT ; CHECK COUNT
- MOV A,H ; NO ENTRIES?
- ORA L
- JZ NODUP ; NO DUPLICATE ENTRY RETURN
- MOV B,H ; BC=NUMBER OF ENTRIES
- MOV C,L
- LHLD DSTART ; HL PTS TO FIRST ENTRY
- DUPELOOP:
- PUSH B ; SAVE COUNT
- PUSH H ; SAVE PTRS
- PUSH D
- MVI B,12 ; COMPARE USER NUMBER, FN, AND FT
- CALL COMP
- POP D ; RESTORE PTRS
- POP H
- JNZ NODUPL ; CONTINUE LOOKING FOR ANOTHER ENTRY
- ; DUPLICATE ENTRIES HAVE BEEN IDENTIFIED AT THIS POINT
- PUSH H ; SAVE PTRS AGAIN
- PUSH D
- LXI B,12 ; PT TO EX FIELD
- DAD B
- XCHG
- DAD B ; DE PTS TO DIRECTORY ENTRY, HL PTS TO TARGET
- LDAX D ; GET EXTENT FIELD FROM DIRECTORY ENTRY
- CMP M ; COMPARE WITH THAT IN TARGET
- POP D ; GET PTRS
- POP H
- JNC DUPFND
- ; NEW TARGET IS LARGER THAN STORED ENTRY
- XCHG ; MAKE HL PT TO NEW TARGET, DE PT TO DEST
- MVI B,ESIZE ; NUMBER OF BYTES TO MOVE
- CALL MOVE ; MOVE IT
- ; RETURN INDICATOR THAT DUPLICATE WAS FOUND
- DUPFND:
- POP B ; CLEAR COUNT FROM STACK
- XRA A ; INDICATE DUP FOUND
- POP H ; RESTORE PTR TO ENTRY TO SCAN FOR
- RET
- ; NO DUPLICATE FOUND; ADVANCE TO NEXT ENTRY
- NODUPL:
- LXI B,ESIZE ; HL PTS TO CURRENT ENTRY IN BUFFER, SO ADD ESIZE TO IT
- DAD B
- POP B ; GET COUNT
- DCX B ; COUNT DOWN
- MOV A,B ; CHECK FOR DONE
- ORA C
- JNZ DUPELOOP
- ; NO DUPLICATE FOUND, PERIOD
- NODUP:
- MVI A,0FFH ; INDICATE DUP NOT FOUND
- ORA A ; SET FLAGS
- POP H ; 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::
- STA CMP$FLAG ; SET FLAG
- MOV A,B ; ANY FILES?
- ORA C
- RZ
- PUSH H ; SAVE REGS
- PUSH D
- PUSH B
- SHLD DIRBUF ; SAVE PTR TO DIRECTORY
- PUSH H ; SAVE HL
- MOV H,B ; HL=BC=FILE COUNT
- MOV L,C
- SHLD N ; SET "N"
- POP H
- ;*
- ;* 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:
- 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 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:
- 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
- POP B ; RESTORE REGS
- POP D
- POP H
- 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:
- LDA CMP$FLAG ; GROUP BY FILE TYPE?
- ORA A
- JZ CMP$FN$FT
- ;*
- ;* COMPARE BY FILE TYPE, FILE NAME, EXTENSION, AND USER (IN THAT ORDER)
- ;*
- CMP$FCB1:
- PUSH H
- PUSH D
- LXI B,9 ; PT TO FT (8 BYTES + 1 BYTE FOR USER NUMBER)
- DAD B
- XCHG
- DAD B
- XCHG ; DE, HL NOW PT TO THEIR FT'S
- MVI B,3 ; 3 BYTES
- CALL COMP ; COMPARE FT'S
- POP D
- POP H
- RNZ ; CONTINUE IF COMPLETE MATCH
- PUSH H
- PUSH D
- INX H ; PT TO FILE NAME
- INX D
- MVI B,8 ; 8 BYTES
- CALL COMP ; COMPARE FN'S
- POP D
- POP H
- RNZ ; CONTINUE IF COMPLETE MATCH
- PUSH H
- PUSH D
- LXI B,12 ; PT TO EXT (11 BYTES FOR FN/FT AND 1 BYTE FOR USER)
- DAD B
- XCHG
- DAD B
- XCHG ; DE, HL NOW PT TO THEIR EXT'S
- LDAX D ; COMPARE
- CMP M
- POP D
- POP H
- RNZ
- LDAX D ; COMPARE USER NUMBERS
- CMP M
- RET
- ;*
- ;* COMPARE BY FILE NAME, FILE TYPE, EXTENSION, AND USER NUM (IN THAT ORDER)
- ;*
- CMP$FN$FT:
- PUSH H
- PUSH D
- INX H ; PT TO FN
- INX D
- MVI B,12 ; COMPARE FN, FT, EX
- 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
-
- ;*
- ;* DIRSEL -- SELECT DIRECTORY ENTRIES WHICH MATCH USER NUMBER, FILE
- ;* NAME, AND FILE TYPE PTED TO BY DE
- ;*
- ;* ON INPUT, HL PTS TO DIRECTORY, DE PTS TO FCB, BC=NUMBER OF FILES, A=FLAG:
- ;* Bit 7 - Select Non-Sys, Bit 6 - Select Sys
- ;* Bit 5 - Select All Users, Bits 4-0 - User Number
- ;* ON OUTPUT, THE MS BIT OF THE USER OF THE SELECTED FILES IS SET
- ;*
- DIRSEL::
- PUSH H ; SAVE REGS
- PUSH D
- PUSH B
- PUSH PSW
- STA SELFLG ; SAVE SELECT FLAG
- SHLD DIRBUF ; SAVE PTR
- PUSH B ; SAVE COUNT
-
- ;* CHECK FOR MATCH
- DSMAT:
- POP B ; GET COUNT
- MOV A,B ; CHECK FOR NO ENTRIES
- ORA C
- JZ DSDONE ; DONE IF NONE
- DCX B ; COUNT DOWN
- PUSH B ; SAVE COUNT
- PUSH H ; SAVE PTRS
- PUSH D
- INX H ; PT TO FN
- INX D
- MVI B,8 ; CHECK 8 CHARS
- XCHG ; LET HL PT TO FCB
- CALL COMP2 ; COMPARE WITH '?' MATCH
- POP D ; GET PTRS
- POP H
- JNZ DSMATNX ; ADVANCE TO NEXT ENTRY IF NO MATCH
- PUSH H ; SAVE PTRS
- PUSH D
- LXI B,9 ; CHECK R/O FLAG, SYS FLAG, LAST BYTE
- DAD B
- XCHG
- DAD B ; DON'T EXCHANGE -- HL PTS TO FCB, DE PTS TO DIR
- MVI B,3 ; CHECK 3 BYTES
- CALL COMP2 ; COMPARE WITH '?' MATCH
- POP D ; RESTORE PTRS
- POP H
- JNZ DSMATNX ; NO MATCH?
- CALL FLGCHK ; CHECK FLAGS
- JNZ DSMATNX ; NO MATCH?
-
- ;*
- ;* WE HAVE A MATCH -- MARK ENTRY
- ;*
- DSMARK:
- MOV A,M ; GET BYTE
- ORI 80H ; SET MSB
- MOV M,A ; PUT BYTE
-
- ;*
- ;* ADVANCE TO NEXT ENTRY
- ;*
- DSMATNX:
- LXI B,ESIZE ; NUMBER OF BYTES/ENTRY
- DAD B ; PT TO NEXT ENTRY
- JMP DSMAT ; CONTINUE
-
- ;*
- ;* DONE WITH SCAN
- ;*
- DSDONE:
- POP PSW ; RESTORE REGS
- POP B
- POP D
- POP H
- RET
-
- ;*
- ;* WE HAVE A NAME MATCH -- NOW CHECK FLAGS
- ;* RETURN Z IF MATCH, NZ IF NO MATCH
- ;*
- FLGCHK:
- PUSH D ; SAVE FCB PTR
- PUSH H ; SAVE ENTRY PTR
- LXI D,10 ; CHECK SYSTEM BIT
- DAD D ; HL PTS TO SYSTEM BIT
- MOV A,M ; GET BYTE
- POP H ; RESTORE PTRS
- POP D
- ANI 80H ; MASK FOR SYSTEM BIT
- LDA SELFLG ; GET FLAG BYTE
- JZ DSNSBIT
- ; IT IS A SYSTEM FILE, SO LOOK AT BIT 6 OF FLAG
- ANI 40H ; LOOK AT BIT 6
- JNZ DSUSER ; OK, SO LOOK AT USER
- JMP DSNOMAT ; CONTINUE PROCESSING
- ; IT IS A NON-SYSTEM FILE, SO LOOK AT BIT 7 OF FLAG
- DSNSBIT:
- ANI 80H ; LOOK AT BIT 7
- JZ DSNOMAT ; NOT SET, SO SKIP ENTRY AS FAILING TEST
- ; NOW CHECK FOR PROPER USER AREA
- DSUSER:
- LDA SELFLG ; GET FLAG
- ANI 20H ; CHECK FOR ALL USERS
- JNZ DSYESMAT ; MATCH IF SET
- LDA SELFLG ; GET FLAG
- ANI 1FH ; GET USER NUMBER (LOW 5 BITS)
- MOV B,A ; SAVE IN B
- MOV A,M ; COMPARE USER NUMBER TO DIR ENTRY
- ANI 1FH ; LOOK AT USER NUMBER
- CMP B ; COMPARE TO PASSED USER NUMBER
- JNZ DSNOMAT ; SKIP IF NOT SAME USER NUMBER
- ; MATCH, SO RETURN Z
- DSYESMAT:
- XRA A ; SET ZERO
- RET
- ; NOT A MATCH, SO RETURN NZ
- DSNOMAT:
- MVI A,0FFH ; SET NO ZERO
- ORA A
- RET
-
- ;**************************************************************************
-
- ;*
- ;* NEGATIVE DIRECTORY PACK UTILITY -- RESTRUCTURE THE DIRECTORY TO INCLUDE
- ;* ONLY THOSE ENTRIES NOT MARKED BY DIRSEL
- ;*
- ;* ON INPUT, HL PTS TO DIRECTORY BUFFER AND BC=NUMBER OF FILES
- ;* ON EXIT, BC=NUMBER OF SELECTED FILES
- ;* REQUIRED SIDE EFFECT IS THAT FLAG EXTENT (SET BY DIR::) BE CORRECT
- ;* (IN MOST CASES, DEFAULT OF 0 IS OK, EXCEPT WHEN EXTENT SIZE >16K)
- ;*
- DIRNPACK::
- PUSH H ; SAVE REGS
- PUSH D
- PUSH B
- PUSH PSW
- DNPACK:
- MOV A,B ; DONE?
- ORA C
- JZ DNPAK1
- DCX B ; COUNT DOWN
- MOV A,M ; GET FIRST BYTE
- CMA ; FLIP BITS
- ANI 80H ; LOOK AT MOST SIG BIT
- MOV D,A ; SAVE IN D
- MOV A,M ; GET FIRST BYTE AGAIN
- ANI 7FH ; MASK OUT MS BIT
- ORA D ; MASK IN NEW MOST SIG BIT
- MOV M,A ; PUT BYTE BACK
- ANI 80H ; SELECTED NOW?
- JZ DNPAK0 ; SKIP IF NOT SELECTED
- PUSH B ; SAVE COUNTER
- CALL FLGCHK ; CHECK FOR FLAGS
- POP B ; GET COUNTER
- JZ DNPAK0
- MOV A,M ; GET BYTE
- ANI 7FH ; DESELECT IT
- MOV M,A ; PUT BYTE BACK
- DNPAK0:
- LXI D,ESIZE ; POINT TO NEXT ENTRY
- DAD D
- JMP DNPACK
- DNPAK1:
- POP PSW ; RESTORE REGS
- POP B
- POP D
- POP H ; NOW FALL THRU TO DIRPACK
-
- ;**************************************************************************
-
- ;*
- ;* DIRECTORY PACK UTILITY -- RESTRUCTURE THE DIRECTORY TO INCLUDE ONLY
- ;* THOSE ENTRIES MARKED BY DIRSEL
- ;*
- ;* ON INPUT, HL PTS TO DIRECTORY BUFFER AND BC=NUMBER OF FILES
- ;* ON EXIT, BC=NUMBER OF SELECTED FILES
- ;* REQUIRED SIDE EFFECT IS THAT FLAG EXTENT (SET BY DIR::) BE CORRECT
- ;* (IN MOST CASES, DEFAULT OF 0 IS OK, EXCEPT WHEN EXTENT SIZE >16K)
- ;*
- DIRPACK::
- PUSH H ; SAVE REGS
- PUSH D
- PUSH PSW
- PUSH H ; SAVE HL
- LXI H,0
- SHLD FCOUNT ; INIT FILE COUNT
- POP H ; GET HL
- SHLD DIRBUF ; SAVE PTR
- PUSH B ; SAVE COUNTER
- DPLOOP:
- POP B ; GET COUNTER
- MOV A,B ; CHECK FOR DONE
- ORA C
- JZ DPDONE
- DCX B ; COUNT DOWN
- PUSH B ; SAVE COUNTER
- MOV A,M ; GET 1ST BYTE OF ENTRY
- ANI 80H ; SELECTED?
- JZ DPNEXT
- ;* FOUND SELECTED ENTRY
- MOV A,M ; CLEAR MSB OF SELECTED ENTRY
- ANI 7FH
- MOV M,A
- PUSH H ; SAVE PTR
- LHLD FCOUNT ; INCREMENT FILE COUNT
- INX H
- SHLD FCOUNT
- POP D ; PT TO CURRENT ENTRY IN DE
- LHLD DIRBUF ; PT TO NEXT ENTRY POSITION
- XCHG ; HL PTS TO CURRENT, DE PTS TO NEXT ENTRY
- MVI B,ESIZE ; COPY ENTRY
- CALL MOVE
- XCHG ; HL PTS TO NEXT ENTRY
- SHLD DIRBUF ; SAVE IT
- XCHG ; HL PTS TO NEXT ENTRY TO CHECK
- JMP DPLOOP ; CONTINUE
- ;* SKIP TO NEXT ENTRY
- DPNEXT:
- LXI B,ESIZE ; SKIP ENTRY
- DAD B
- JMP DPLOOP ; CONTINUE
- ;* COMPRESSION COMPLETE -- SET UP RETURNED VALUES
- DPDONE:
- LHLD FCOUNT ; PUT FILE COUNT
- MOV B,H ; ... IN BC
- MOV C,L
- POP PSW ; RESTORE REGS
- POP D
- POP H
- RET
-
- END
-