mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1050 lines
21 KiB
1050 lines
21 KiB
; 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
|
|
|