mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
1465 lines
32 KiB
Plaintext
1465 lines
32 KiB
Plaintext
;
|
||
; 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
|
||
|