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.
1465 lines
32 KiB
1465 lines
32 KiB
;
|
|
; Program: DIR
|
|
; Author: Richard Conn
|
|
; Version: 1.0
|
|
; Date: 23 Mar 84
|
|
;
|
|
VERS EQU 11 ; Changed manner of calculating disk size
|
|
; Using all0 and all1 instead of drm
|
|
; Added modified dirqs and fsize jww
|
|
; Trial to list files vertically jww
|
|
;
|
|
;VERS EQU 10 ; Release
|
|
;
|
|
MONTH EQU 1
|
|
DAY EQU 2
|
|
YEAR EQU 85
|
|
;
|
|
Z3ENV SET 0F400H ; Set zcpr3 environment descriptor address
|
|
;
|
|
; Equates
|
|
;
|
|
YES EQU 0FFH
|
|
NO EQU 0
|
|
;
|
|
VIDEO EQU YES ; Enhanced video?
|
|
VOPT EQU YES ; Print signon and vers no
|
|
VERT EQU YES ; List files vertically (default)
|
|
;
|
|
FCB EQU 5CH
|
|
FCB2 EQU 6CH
|
|
CTRLC EQU 03H
|
|
CR EQU 0DH
|
|
LF EQU 0AH
|
|
;
|
|
; VLIB, Z3LIB and SYSLIB References
|
|
;
|
|
EXT Z3VINIT,TINIT,STNDOUT,STNDEND,BDOS
|
|
EXT CODEND,RETUD,PFN1,DFREE,DUTDIR,DPARAMS
|
|
EXT CRLF,COUT,PAFDC,PHLDC,PHLFDC,Z3LOG,FILLB,GETCRT,CIN
|
|
;
|
|
; 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 Z3VINIT ; Initialize the zcpr3 env
|
|
CALL TINIT ; Initialize the terminal
|
|
;
|
|
; Make FCB Wild if No Entry
|
|
;
|
|
LXI H,FCB+1 ; Pt to first char
|
|
MOV A,M ; Get it
|
|
CPI ' ' ; Check for space
|
|
MVI B,11 ; Prepare to set 11 bytes
|
|
MVI A,'?' ; To "?"
|
|
CZ FILLB ; Do it if space
|
|
;
|
|
; Check for Help
|
|
;
|
|
LXI D,FCB+1 ; Pt to first char of fcb
|
|
LDAX D ; Get first char of fcb
|
|
CPI '/'
|
|
JNZ DOIT
|
|
CALL PRINT
|
|
DB 'DIR Vers '
|
|
DB (VERS/10)+'0','.',(VERS MOD 10)+'0',CR,LF
|
|
DB ' Syntax: DIR dir:afn o',CR,LF
|
|
DB ' Options: A=All, S=Sys, H=Horiz, V=Vert, '
|
|
DB 'T=File Type/Name Sor','t'+80H
|
|
RET
|
|
;
|
|
; Perform Directory Function
|
|
;
|
|
DOIT:
|
|
DCX D ; Pt to fcb
|
|
CALL Z3LOG ; Log into dir
|
|
XRA A ; Clear disk selection byte
|
|
STAX D
|
|
;
|
|
; Process Options in FCB2
|
|
;
|
|
LXI H,FCB2+1 ; Pt to options
|
|
MVI B,8 ; Allow for up to 8 options
|
|
MVI C,10000000B ; Assume just normal files
|
|
OPTLOOP:
|
|
MOV A,M ; Get next char
|
|
INX H ; Advance
|
|
DCR B ; Count down
|
|
JZ SETDATA ; Done - set data
|
|
CPI ' '
|
|
JZ OPTLOOP
|
|
CPI 'H' ; Select horizontal listing
|
|
JZ SETHORIZ
|
|
CPI 'V' ; Select vertical listing
|
|
JZ SETVERT
|
|
CPI 'T' ; File type?
|
|
JZ SETTYPE
|
|
CPI 'S' ; System?
|
|
JZ SETSYS
|
|
CPI 'A' ; System and normal?
|
|
JNZ OPTLOOP
|
|
;
|
|
; Select Both System and Normal Files
|
|
;
|
|
MVI A,11000000B ; Normal and system files
|
|
JMP SETSYS1
|
|
;
|
|
; Select Horizontal listing
|
|
;
|
|
SETHORIZ:
|
|
MVI A,YES
|
|
STA HORIZ
|
|
JMP OPTLOOP
|
|
;
|
|
; Select Vertical listing
|
|
;
|
|
SETVERT:
|
|
MVI A,NO
|
|
STA HORIZ
|
|
JMP OPTLOOP
|
|
;
|
|
HORIZ: DB NOT VERT ; Horizontal listing flag
|
|
;
|
|
; Select File Type/Name Alphabetization
|
|
;
|
|
SETTYPE:
|
|
MOV A,C ; Get flag
|
|
ORI 00100000B
|
|
MOV C,A
|
|
JMP OPTLOOP
|
|
;
|
|
; Select Just System Files
|
|
;
|
|
SETSYS:
|
|
MVI A,01000000B ; System
|
|
SETSYS1:
|
|
PUSH PSW
|
|
MOV A,C
|
|
ANI 00111111B ; Mask out
|
|
MOV C,A
|
|
POP PSW
|
|
ORA C
|
|
MOV C,A
|
|
JMP OPTLOOP
|
|
;
|
|
; Set Selection Byte in A
|
|
;
|
|
SETDATA:
|
|
CALL DPARAMS ; Init parameters
|
|
CALL CODEND ; Pt to free area
|
|
MOV A,C ; Selection in a
|
|
;
|
|
; Load and Sort Directory
|
|
;
|
|
CALL DIRQS ; Quick load
|
|
SHLD DIRBEG ; Beginning of directory area
|
|
JNZ DISPLAY
|
|
CALL PRINT
|
|
DB ' Ovf','l'+80H
|
|
RET
|
|
;
|
|
; Display Directory
|
|
;
|
|
DISPLAY:
|
|
PUSH H ; Save ptr to first entry
|
|
;
|
|
; Init:
|
|
; Total of All File Sizes
|
|
; Number of Files Displayed
|
|
; Line Counter
|
|
; Entry Counter
|
|
;
|
|
IF VOPT ; Signon and version
|
|
PUSH B
|
|
IF VIDEO
|
|
CALL STNDOUT
|
|
ENDIF
|
|
MVI C,22 ; Print 22 spaces
|
|
DIS0: MVI A,' '
|
|
CALL COUT
|
|
DCR C
|
|
JNZ DIS0
|
|
CALL PRINT
|
|
DB 'DIRectory Version '
|
|
DB VERS/10+'0','.',VERS MOD 10+'0'
|
|
DB ' ',MONTH/10+'0',MONTH MOD 10+'0','/'
|
|
DB DAY/10+'0',DAY MOD 10+'0','/'
|
|
DB YEAR/10+'0',YEAR MOD 10+'0'
|
|
DB CR,LF+80H
|
|
IF VIDEO
|
|
CALL STNDEND
|
|
ENDIF
|
|
POP B
|
|
ENDIF ; Vopt
|
|
;
|
|
LXI H,0 ; Set total size count
|
|
SHLD TOTCOUNT
|
|
LXI H,FCOUNT ; Save file count
|
|
MOV M,C
|
|
INX H
|
|
MOV M,B ; File count saved from bc
|
|
PUSH B ; Save file count
|
|
MOV H,B
|
|
MOV L,C ; Move it to hl
|
|
LXI D,4
|
|
CALL DIVIDE ; Divide by four columns
|
|
JZ DIS1
|
|
INX B ; Round up if remainder from division
|
|
DIS1: MOV H,B
|
|
MOV L,C ; Quotient to hl
|
|
CALL X16
|
|
SHLD LINES
|
|
POP H ; Get file count
|
|
PUSH H ; And put it back
|
|
DCX H ; File count -1 points to last file
|
|
CALL X16 ; Multiply by 16 chars/line
|
|
XCHG ; Directory size to de
|
|
LHLD DIRBEG
|
|
DAD D
|
|
SHLD DIREND
|
|
POP B ; Get file count
|
|
POP H ; Pt to first entry
|
|
XRA A
|
|
STA LCOUNT ; Init line count
|
|
STA COUNT ; Init entry count
|
|
MOV A,B ; Check for done
|
|
ORA C
|
|
JZ PRREMAIN ; Print remaining space on disk and exit
|
|
CALL PRINT
|
|
DB ' '+80H ; Print first leading space
|
|
;
|
|
; Loop to Display File Entries
|
|
;
|
|
DISPLOOP:
|
|
;
|
|
; Print Separator if Within a Line
|
|
;
|
|
LDA COUNT ; See if new entry on line
|
|
ANI 3
|
|
JZ DISPL1
|
|
;
|
|
; Print Separator if Entry is Within a List
|
|
;
|
|
IF VIDEO
|
|
CALL STNDOUT
|
|
ENDIF
|
|
CALL PRINT ; Print separator
|
|
DB '|',' '+80H
|
|
IF VIDEO
|
|
CALL STNDEND
|
|
ENDIF
|
|
;
|
|
; Print Next Entry
|
|
;
|
|
DISPL1:
|
|
PUSH H ; Save key regs
|
|
PUSH B ; Hl pts to next entry, bc = count
|
|
;
|
|
; Print File Name
|
|
;
|
|
INX H ; Pt to file name
|
|
XCHG
|
|
CALL PFN1 ; Print file name
|
|
XCHG
|
|
DCX H ; Pt to first byte of file entry
|
|
;
|
|
; Print File Size and Increment Total of All File Sizes
|
|
;
|
|
PUSH H ; Save ptr to first byte of file entry
|
|
CALL FSIZE ; Compute file size (to de)
|
|
LHLD TOTCOUNT ; Increment total count
|
|
DAD D
|
|
SHLD TOTCOUNT
|
|
XCHG
|
|
CALL PHLDC ; Print file size
|
|
POP H ; Get ptr to first byte of file entry
|
|
;
|
|
; Check R/O Byte
|
|
;
|
|
MVI B,' ' ; Assume r/w
|
|
LXI D,9 ; Pt to r/o
|
|
DAD D
|
|
MOV A,M ; Get r/o byte
|
|
ANI 80H ; Look at it
|
|
JZ ROOUT
|
|
MVI B,'r' ; Set r/o
|
|
ROOUT:
|
|
MOV A,B ; Get char
|
|
CALL COUT
|
|
;
|
|
; Increment Entry Count and Issue New Line if Limit Reached
|
|
;
|
|
LDA COUNT ; Increment entry count
|
|
INR A
|
|
STA COUNT
|
|
LDA HORIZ ; Check horiz/vert listing
|
|
ORA A
|
|
JZ DISPL2 ; Vertical listing
|
|
LDA COUNT
|
|
ANI 3 ; New line?
|
|
CZ NEWLIN
|
|
JMP DISPL2
|
|
;
|
|
; New Line - Increment Line Count and Issue Page Break if Limit Reached
|
|
;
|
|
NEWLIN: CALL PRNL
|
|
LDA LCOUNT ; Count down lines
|
|
INR A
|
|
STA LCOUNT
|
|
CALL GETCRT ; Get crt data
|
|
INX H ; Pt to text line count
|
|
INX H
|
|
DCR A ; Back up again
|
|
CMP M ; Compare
|
|
RNZ
|
|
XRA A ; Reset line count
|
|
STA LCOUNT
|
|
IF VIDEO
|
|
CALL STNDOUT
|
|
ENDIF
|
|
CALL PRINT
|
|
DB ' Pause -',' '+80H
|
|
IF VIDEO
|
|
CALL STNDEND
|
|
ENDIF
|
|
CALL CIN
|
|
CALL PRNL ; Print new line with leading space
|
|
CPI CTRLC ; Abort?
|
|
RNZ
|
|
POP PSW ; Clear the rest of the stack
|
|
POP PSW
|
|
POP PSW
|
|
RET ; To zcpr3
|
|
;
|
|
; Advance to Next Entry
|
|
;
|
|
DISPL2:
|
|
POP B ; Restore count and ptr to current entry
|
|
POP H
|
|
LDA HORIZ ; Check horiz/vert listing
|
|
ORA A
|
|
JNZ DISP2 ; Horizontal
|
|
XCHG ; Pointer to de
|
|
LHLD LINES
|
|
DAD D ; Point to next entry
|
|
XCHG ; New pointer to de
|
|
LHLD DIREND
|
|
CALL SUBDE ; Check if new ptr is within the directory
|
|
XCHG ; New pointer to hl
|
|
JNC DISP3 ; New pointer is ok
|
|
LHLD DIRBEG ; Otherwise start new line
|
|
LXI D,16 ; Next line
|
|
DAD D
|
|
SHLD DIRBEG ; Save it
|
|
XRA A
|
|
STA COUNT ; Clear column count
|
|
PUSH H
|
|
PUSH B
|
|
CALL NEWLIN
|
|
POP B
|
|
POP H
|
|
JMP DISP3
|
|
DISP2: LXI D,16 ; Skip to next entry
|
|
DAD D
|
|
DISP3: DCX B ; Count down
|
|
MOV A,B ; Done?
|
|
ORA C
|
|
JNZ DISPLOOP
|
|
LDA COUNT ; See if new line required
|
|
ANI 3
|
|
CNZ CRLF ; New line if any entries on line
|
|
;
|
|
; Print Remaining Space on Disk and Exit
|
|
;
|
|
PRREMAIN:
|
|
;
|
|
; Print DU
|
|
;
|
|
IF VIDEO
|
|
CALL STNDOUT
|
|
ENDIF
|
|
MVI B,8 ; Space over 8 spaces
|
|
MVI A,' '
|
|
SPACER:
|
|
CALL COUT
|
|
DCR B
|
|
JNZ SPACER
|
|
CALL RETUD ; Get du in bc
|
|
MOV A,B ; Print disk letter
|
|
ADI 'A' ; Convert to ascii
|
|
CALL COUT
|
|
MOV A,C ; Print user number
|
|
CALL PAFDC ; Print floating
|
|
CALL PRINT ; Print separator
|
|
DB ':'+80H
|
|
CALL DUTDIR ; See if matching dir
|
|
JZ PRREM1
|
|
;
|
|
; Print DIR if any
|
|
;
|
|
MVI B,8 ; 8 chars max
|
|
PRREM0:
|
|
MOV A,M ; Get char
|
|
INX H ; Pt to next
|
|
CPI ' ' ; Space?
|
|
CNZ COUT ; Echo char
|
|
DCR B ; Count down
|
|
JNZ PRREM0
|
|
;
|
|
; Print File Count
|
|
;
|
|
PRREM1:
|
|
LHLD FCOUNT ; Print number of files
|
|
CALL PRINT
|
|
DB ' --',' '+80H
|
|
CALL PHLFDC
|
|
;
|
|
; Print Total of All File Sizes
|
|
;
|
|
LHLD TOTCOUNT ; Print total count
|
|
CALL PRINT
|
|
DB ' files using',' '+80H
|
|
CALL PHLFDC ; Print as floating
|
|
;
|
|
; Print Amount of Free Space Remaining
|
|
;
|
|
CALL DFREE ; Compute amount of free space
|
|
XCHG ; In hl
|
|
CALL PRINT
|
|
DB 'k ','('+80H
|
|
CALL PHLFDC
|
|
CALL PRINT
|
|
DB 'k remain of',' '+80H
|
|
CALL DSIZE
|
|
CALL PHLFDC
|
|
CALL PRINT
|
|
DB 'k total',')'+80H
|
|
IF VIDEO
|
|
CALL STNDEND
|
|
ENDIF
|
|
RET
|
|
;
|
|
; Print New Line with Leading Space
|
|
;
|
|
PRNL:
|
|
CALL PRINT
|
|
DB CR,LF,' '+80H ; New line with leading space
|
|
RET
|
|
;
|
|
; Print Routine (String at Return Address) which is terminated by MSB
|
|
;
|
|
PRINT:
|
|
XTHL ; Pt to string and save hl
|
|
PUSH PSW
|
|
PRINT1:
|
|
MOV A,M ; Get next char
|
|
ANI 7FH ; Mask msb
|
|
CALL COUT
|
|
MOV A,M ; Get next char
|
|
INX H ; Pt to next
|
|
ANI 80H ; Check msb
|
|
JZ PRINT1
|
|
POP PSW ; Get a
|
|
XTHL ; Restore return address and hl
|
|
RET
|
|
;
|
|
; DSIZE returns the size of the current disk in HL (k)
|
|
;
|
|
DSIZE: PUSH D
|
|
PUSH B
|
|
;
|
|
MVI C,31 ; Return dpb address in hl
|
|
CALL BDOS
|
|
INX H
|
|
INX H ; Point to bls
|
|
MOV A,M ; Bls in a
|
|
STA BLS
|
|
INX H
|
|
INX H
|
|
INX H ; Point to dsm
|
|
MOV E,M
|
|
INX H
|
|
MOV D,M ; Dsm in de
|
|
INX D ; Rel 1
|
|
PUSH D ; Save dsm on stack
|
|
INX H ; Point to drm
|
|
INX H
|
|
INX H ; Point to all0
|
|
MOV D,M
|
|
INX H ; Point to all1
|
|
MOV E,M
|
|
XCHG ; Allocation vector in hl
|
|
LXI D,-1 ; Clear a counter
|
|
DS0: INX D
|
|
CALL SHLHL
|
|
JC DS0
|
|
CALL SUBDE ; Get complement of count
|
|
POP D ; Get dsm from stack
|
|
DAD D ; Hl = groups available
|
|
LDA BLS ; Block shift factor
|
|
SUI 3 ; From bls in a
|
|
JZ DSX
|
|
DSIZ0: DAD H
|
|
DCR A
|
|
JNZ DSIZ0
|
|
DSX:
|
|
POP B
|
|
POP D
|
|
RET
|
|
;
|
|
; DIVIDE divides HL by DE returning quotient in BC and remainder in HL
|
|
; Zero flag is set if no remainder
|
|
;
|
|
DIVIDE: LXI B,0 ; Clear quotient
|
|
DIV0: CALL SUBDE ; Subtract de from hl
|
|
JC DIV1 ; Overflow
|
|
INX B ; Increment quotient
|
|
JMP DIV0 ; Again..
|
|
DIV1: DAD D ; Restore remainder in hl
|
|
MOV A,H ; Check for remainder
|
|
ORA L ; Equal zero
|
|
RET
|
|
;
|
|
; SUBDE subtracts DE from HL returning carry set if de > hl
|
|
;
|
|
SUBDE: MOV A,L
|
|
SUB E
|
|
MOV L,A
|
|
MOV A,H
|
|
SBB D
|
|
MOV H,A
|
|
RET
|
|
;
|
|
; X16 simply shifts HL left four times
|
|
;
|
|
X16: DAD H
|
|
DAD H
|
|
DAD H
|
|
DAD H
|
|
RET
|
|
;
|
|
; SHLHL shifts HL left into carry
|
|
;
|
|
SHLHL: ORA A ; Reset carry
|
|
MOV A,L
|
|
RAL
|
|
MOV L,A
|
|
MOV A,H
|
|
RAL
|
|
MOV H,A
|
|
RET
|
|
;
|
|
; SYSLIB Module Name: SDIRQS
|
|
; Author: Richard Conn
|
|
; Part of SYSLIB3 SDIR Series
|
|
; SYSLIB Version Number: 3.0
|
|
; Module Version Number: 1.4
|
|
; Module Entry Points:
|
|
; DIRQS
|
|
; Module External References:
|
|
; None
|
|
;
|
|
|
|
;*
|
|
;* EQUATES
|
|
;*
|
|
CPM EQU 0
|
|
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 D ; Save ptr to fcb
|
|
|
|
STA SELFLG ; Save select flag for selection and alphabetization
|
|
SHLD HOLD ; Set ptr to hold buffer
|
|
LXI B,36 ; Allow 36 bytes
|
|
DAD B ; Hl now points to temp fcb
|
|
SHLD TFCB ; Set ptr to temp fcb
|
|
DAD D ; Hl now pts to scratch area
|
|
|
|
PUSH D ; Save ptr to fcb
|
|
CALL DBUFFER ; Get ptrs
|
|
POP D ; Get ptr to fcb
|
|
PUSH H ; Save ptr to buffer
|
|
CALL DIRLOAD ; Load directory (fast load)
|
|
POP H ; Get ptr to buffer
|
|
|
|
POP D ; Get ptr to fcb
|
|
|
|
RZ ; Abort if tpa overflow
|
|
|
|
PUSH PSW ; Save flag to indicate no tpa overflow
|
|
CALL DIRALPHA ; Alphabetize
|
|
POP PSW ; 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:
|
|
SHLD ORDER ; Pt to order table
|
|
CALL DPARAMS0 ; 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
|
|
XRA A ; Ok
|
|
DCR A ; Set flags (nz)
|
|
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
|
|
POP PSW ; Clear stack
|
|
XRA 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)
|
|
;*
|
|
DPARAMS0:
|
|
;*
|
|
;* 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
|
|
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
|
|
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:
|
|
SHLD DSTART ; Set start of buffer area
|
|
INX D ; Pt to file name
|
|
LHLD TFCB ; Pt to tfcb
|
|
MVI M,0 ; Select current disk
|
|
INX H ; Pt to file name in tfcb
|
|
MVI B,11 ; 11 chars
|
|
DLLOOP:
|
|
LDAX D ; Copy
|
|
MOV M,A
|
|
INX H ; Pt to next
|
|
INX D
|
|
DCR B ; Count down
|
|
JNZ DLLOOP
|
|
MVI M,'?' ; Select all extents
|
|
INX H ; Pt to next char
|
|
MVI M,0
|
|
INX H
|
|
MVI M,'?' ; And all modules
|
|
INX H
|
|
MVI B,21 ; 23 chars
|
|
XRA A ; Zero rest of tfcb
|
|
DLLOOP1:
|
|
MOV M,A ; Store zero
|
|
INX H ; Pt to next
|
|
DCR B ; Count down
|
|
JNZ DLLOOP1
|
|
|
|
;*
|
|
;* THIS SECTION OF CODE INITIALIZES THE COUNTERS USED
|
|
;*
|
|
LXI H,0 ; Hl=0
|
|
SHLD FCOUNT0 ; Total files on disk = 0
|
|
;*
|
|
;* NOW WE BEGIN SCANNING FOR FILES TO PLACE INTO THE MEMORY BUFFER
|
|
;*
|
|
MVI C,17 ; Search for file
|
|
JMP DIRLP1
|
|
DIRLP:
|
|
CALL PENTRY ; Place entry in dir
|
|
JZ DIROVFL ; Memory overflow error
|
|
MVI C,18 ; Search for next match
|
|
DIRLP1:
|
|
LHLD TFCB ; Pt to fcb
|
|
XCHG
|
|
CALL BDOS
|
|
CPI 255 ; Done?
|
|
JNZ DIRLP
|
|
;*
|
|
;* NOW WE ARE DONE WITH THE LOAD -- SET UP RETURN VALUES
|
|
;*
|
|
DIRDN:
|
|
XRA A ; Load ok
|
|
DCR A ; Set flags (nz)
|
|
DIRDNX:
|
|
LHLD FCOUNT0 ; Get total number of files
|
|
MOV B,H ; In bc
|
|
MOV C,L
|
|
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
|
|
;* FCOUNT0=NUMBER OF FILES IN DIR SO FAR
|
|
;* ON OUTPUT, FCOUNT0=NUMBER OF FILES IN DIR SO FAR
|
|
;* A=0 AND ZERO FLAG SET IF MEMORY OVERFLOW ERROR
|
|
;*
|
|
PENTRY:
|
|
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
|
|
;*
|
|
;* HL=ADR OF FCB IN BUFF
|
|
;*
|
|
CALL ATTEST ; Test attributes
|
|
JZ 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
|
|
JZ PEDONE ; Skip if duplicate
|
|
|
|
;*
|
|
;* 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 SDMOVE ; 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?
|
|
RZ
|
|
|
|
;* INCREMENT TOTAL NUMBER OF FILES
|
|
LHLD FCOUNT0 ; Total files = total files + 1
|
|
INX H
|
|
SHLD FCOUNT0
|
|
|
|
;* DONE WITH PENTRY AND NO ERROR
|
|
PEDONE:
|
|
XRA A ; No error
|
|
DCR 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 H ; Save ptr
|
|
LXI B,10 ; Pt to system attribute
|
|
DAD B
|
|
MOV A,M ; Get system attribute
|
|
POP H ; Restore ptr
|
|
ANI 80H ; Check for sys
|
|
LDA SELFLG ; Get selection flag
|
|
JZ ATDIR
|
|
ANI 01000000B ; Check system attribute
|
|
RET
|
|
ATDIR:
|
|
ANI 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, FCOUNT0 = 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 FCOUNT0 ; 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
|
|
INX H ; Pt to fn
|
|
INX D
|
|
MVI B,11 ; Compare fn and ft
|
|
CALL COMP
|
|
JNZ NODUPL ; Continue looking for another entry
|
|
; DUPLICATE ENTRIES HAVE BEEN IDENTIFIED AT THIS POINT
|
|
MOV C,M ; Extent in low order
|
|
INX H
|
|
INX H
|
|
MOV B,M ; Module in high order
|
|
PUSH B ; Save entry size a moment
|
|
XCHG ; Point hl to target
|
|
MOV E,M ; Extent in low order
|
|
INX H
|
|
INX H
|
|
MOV D,M ; Module in high order
|
|
POP H ; Dir in hl, target in de
|
|
XCHG
|
|
CALL SUBDE ; Subtract dir size from target size
|
|
POP D ; Get ptrs
|
|
POP H
|
|
JC DUPSMALL ; Target is smaller
|
|
; NEW TARGET IS LARGER THAN STORED ENTRY
|
|
XCHG ; Hl pts to target, de pts to dir entry
|
|
MVI B,ESIZE ; Number of bytes to move
|
|
CALL SDMOVE ; Move it
|
|
; NEW TARGET IS SMALLER THAN STORED ENTRY
|
|
DUPSMALL:
|
|
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:
|
|
POP D ; Restore ptrs
|
|
POP H
|
|
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
|
|
NODUP:
|
|
XRA A ; Indicate dup not found
|
|
DCR A ; Set flags (nz)
|
|
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:
|
|
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:
|
|
MVI E,7 ; Ring bell
|
|
MVI C,2 ; Output
|
|
CALL BDOS
|
|
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 HOLD ; Pt to hold buffer
|
|
XCHG
|
|
LHLD PTDIR ; Pt to entry
|
|
PUSH B ; Save b=number of bytes/entry
|
|
CALL SDMOVE
|
|
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 SDMOVE
|
|
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
|
|
LHLD 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
|
|
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 SELFLG ; Group by file type?
|
|
ANI 00100000B
|
|
JZ CMP$FN$FT
|
|
;*
|
|
;* COMPARE BY FILE TYPE AND FILE NAME (IN THAT ORDER)
|
|
;*
|
|
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
|
|
MVI B,8 ; 8 bytes
|
|
JMP CMP$FT1
|
|
;*
|
|
;* COMPARE BY FILE NAME AND FILE TYPE (IN THAT ORDER)
|
|
;*
|
|
CMP$FN$FT:
|
|
MVI B,11 ; 11 bytes for fn and ft
|
|
CMP$FT1:
|
|
PUSH H
|
|
PUSH D
|
|
INX H ; Pt to fn
|
|
INX D
|
|
CALL COMP ; Do comparison
|
|
POP D
|
|
POP H
|
|
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
|
|
|
|
;*
|
|
;* COPY FROM HL TO DE FOR B BYTES
|
|
;*
|
|
SDMOVE:
|
|
MOV A,M ; Copy
|
|
STAX D
|
|
INX H ; Pt to next
|
|
INX D
|
|
DCR B ; Count down
|
|
JNZ SDMOVE
|
|
RET
|
|
|
|
;*
|
|
;* BUFFERS
|
|
;*
|
|
HOLD:
|
|
DS 2 ; 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
|
|
|
|
TFCB:
|
|
DS 2 ; Address of temporary fcb
|
|
DSTART:
|
|
DS 2 ; Pointer to first directory entry
|
|
FCOUNT0:
|
|
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
|
|
;
|
|
; Buffers
|
|
;
|
|
COUNT: DS 1 ; Counter used in display
|
|
FCOUNT: DS 2 ; Number of files displayed
|
|
LCOUNT: DS 1 ; Line counter
|
|
TOTCOUNT: DS 2 ; Total of sizes of all files
|
|
BLS: DS 1 ; Block shift factor
|
|
LINES: DS 2 ; Lines to be displayed
|
|
DIRBEG: DS 2 ; Beginning of directory area
|
|
DIREND: DS 2 ; End of directory area
|
|
|
|
; END
|
|
;
|
|
; SYSLIB Module Name: SDIR04
|
|
; Author: Richard Conn
|
|
; Part of SYSLIB3 SDIR Series
|
|
; SYSLIB Version Number: 3.0
|
|
; Module Version Number: 1.4
|
|
; Module Entry Points:
|
|
; FSIZE
|
|
; Module External References:
|
|
;
|
|
;
|
|
|
|
; INCLUDE SDIRHDR.LIB
|
|
|
|
;*
|
|
;* 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 ; S1
|
|
INX H ; S2 is the module number (512 k)
|
|
MOV A,M ; Get module #
|
|
ORA A ; Reset carry
|
|
RAL
|
|
RAL
|
|
RAL
|
|
RAL
|
|
RAL ; * 32 extents
|
|
ORA E
|
|
MOV E,A ; Add to e
|
|
JNC FS0 ; Check high order bit
|
|
INR D ; If carry
|
|
FS0: 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
|
|
|
|
END
|
|
|