home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
VFILER.MAC
< prev
next >
Wrap
Text File
|
2000-06-30
|
99KB
|
4,466 lines
; TITLE 'VFILER'
; VERSION: 3.0
; DATE: 26 June 84
; AUTHOR: Richard Conn
; Changes to make Version 3.4 by Richard Conn:
; Symbol CCP changed to CCPLEN (when Z3BASE.LIB was added, the
; symbol CCP in Z3BASE.LIB conflicted with this symbol in VFILER;
; how did version 3.3 ever assemble in the first place, unless someone
; has modified Z3BASE.LIB from the original format?)
; Comments on version 3.3 changes added, prefixed by <RLC>
; THE FOLLOWING MAJOR CHANGES WERE MADE BY JAY SAGE AND BOB DEMROW TO
; MAKE VERSION 3.3. The changes were built from version 3.1.
; The following changes were contributed by Jay P. Sage and marked by
; <JPS> on the lines or at the blocks changed or added:
; 1. Code modified to eliminate double loading of program, once to
; establish shell and once to run shell. Program now checks after
; shell is established to see if any commands are pending in the
; command line. If there are none, the code is run immediately
; without reloading from disk. Otherwise, pending commands are run
; first as in previous versions.
; <RLC> Good idea
; 2. The disk logging command was extended to include setting of the
; file selection mask in system file name 4. This command was also
; renamed from 'N' to 'L' to be consistent with common usage in
; previous versions of VFILER and other programs. An equate is
; provided early in the code for those who want to change this.
; The response to the 'L' command is now a general ambiguous file
; specification. If it includes a directory specification, then
; that directory is logged into. Otherwise, one remains in the
; current directory. If it includes a file name specification,
; then that name is copied to system file name 4 and is used as a
; mask for file selection. Otherwise '*.*' is used automatically.
; Note that the colon must now be included to specify only a new
; directory. Since a carriage return alone cancels the command,
; '*.*' would have to be entered to stay in the currect directory
; but include all files. As a shortcut one can enter just a colon
; or semicolon.
; <RLC> Fine; note that the change of the command name to 'N' was
; <RLC> done in the first place to be consistent with FRIENDLY,
; <RLC> the "commercial VFILER" sold by Ampro Computers; but, then
; <RLC> again, if you use FRIENDLY, you probably don't use VFILER,
; <RLC> so the problem of consistency may not come up
; 3. Several changes were made in the command table to allow for
; synonyms. The 'X' abort operation was deleted from the 'L'
; command but was made equivalent to control-c in the main command
; table. The functions control-a and control-f, though included in
; the help screen, had not previously been implemented. They are
; here made synonyms for '-' and '+', respectively. (The built-in
; help screen was modified to make this clear.) For ease in
; entering commands, '<' and ',' were made the same as control-s,
; and '>' and '.' were made the same as control-d.
; <RLC> Fine; I debated for some time about adding synonyms, and
; <RLC> had originally decided against it; let's try this change
; <RLC> as-is and see how it works; however, re the addition of
; <RLC> ^A and ^F as synonyms for - and +, I'm sorry I forgot to
; <RLC> delete these from the Help screen -- they were intentionally
; <RLC> omitted because of potential conflict with arrow keys from
; <RLC> Z3TCAP -- if an arrow key generated ^A or ^F, then the ^A/^F
; <RLC> movement functions were overriddent by ^A/^F arrows, so I
; <RLC> decided to drop them completely and have only - and +; again,
; <RLC> let's try this change for a while and see how it works out
; 4. When files are deleted with the 'D' command, notice to that
; effect is displayed on the command line at the bottom of the
; screen.
; 5. Highlighting on the 'Z80 Code' and '8080 Code' messages was
; deleted.
; <RLC> Cosmetic
; 6. Rename function made to completely update file ring and display.
; This solves the problem of renamed files being out of place.
; <RLC> Good idea
; The following changes were contributed by R.I.Demrow and are marked by
; <RID> on all lines that were changed.
; 1. Replaced Z3ENV equate by MACLIB reference to Z3BASE.LIB. This
; library includes definitions for true and false, the value of
; Z3ENV, and the value of I8080 (indicates whether to use Z80
; opcodes)
; <RLC> Good idea; it is nice to have these equates carried in thru
; <RLC> Z3BASE.LIB, but don't expect to find matching CRCs from one
; <RLC> assembly to the next -- the COM files will differ depending
; <RLC> on values in Z3BASE; I feel, tho, that the convenience of
; <RLC> including Z3BASE outweighs the inconvenience of matching CRCs
; 2. Added highlighting to current file and current disk on top line
; of display.
; <RLC> See comment under next change
; 3. Tagged files are now highlighted on the screen.
; <RLC> There was a lot of debate during the design of FRIENDLY as
; <RLC> to whether to point to a file via a pointer or via highlighting;
; <RLC> the highlighting option was ruled against for the simple reason
; <RLC> that pointing is very important and fundamental to the VFILER
; <RLC> concept, and, on some terminals in certain kinds of lighting,
; <RLC> it is nearly impossible to distinguish a highlighted file from
; <RLC> one which is not highlighted; however, in this case, the file
; <RLC> is highlighted AND followed by a tag character, so the best of
; <RLC> both worlds is retained
; 4. Two new group functions were added: mass print and mass view.
; <RLC> Not a bad idea, but I prefer using the PRINT and PAGE
; <RLC> commands for these operations; note that a VFILER.CMD file
; <RLC> could provide PRINT and PAGE easily without any cost inside
; <RLC> of VFILER
; 5. The simulated clear-to-end-of-line function was corrected. It
; only cleared part of line before, and it had the wrong divisor in
; a modulus calculation.
; <RLC> Good
; 6. Changed code to make use of TCAP information about length of
; printer page. That information was obtained in the previous code
; but was not utilized.
; <RLC> Good
; PREVIOUS VERSIONS: 2.0 (18 Sep 83), 1.8 (17 Sep 83)
; PREVIOUS VERSIONS: 1.7 (9 Sep 83), 1.6 (18 Aug 83), 1.5 (20 July 83)
; PREVIOUS VERSIONS: 1.4 (19 July 83), 1.3 (18 July 83)
; PREVIOUS VERSIONS: 1.2 (18 July 83), 1.1 (17 July 83), 1.0 (16 July 83)
; DERIVATION: From FILER (Version 1.6) by Richard Conn
; FILER from DISK7, Version 7.6C, by Frank Gaude'
VERS EQU 34 ;<RLC> Version Number
;<JPS><RID> version number
MACLIB Z3BASE.LIB ;<RID> USE LIB TO GET Z3ENV, I8080, FALSE,
; and TRUE
; VFILER is copyright (c) 1983, 1984, 1985 by Richard Conn
; All Rights Reserved
; VFILER may be used freely by the ZCPR3 Community
; VFILER is a screen-oriented, ZCPR3-specific file utility. It can not be
; installed to run under conventional CP/M. VFILER
; extensively employs cursor addressing to position a pointer on the
; screen, allow the user to manipulate the pointer (up, down, right, left,
; next screen, previous screen, GOTO file). The pointer points to files
; in the current user directory and displays the user's position dynamically
; on the screen. Once pointing to a file, user commands can be used to
; manipulate the file (delete, copy, view on console, print on printer, tag
; for later copy or delete, and untag). In the way of being ZCPR3-specific,
; VFILER can chain to external programs via the MCL and then return (ala
; MENU), and it recognizes Named Directories (so the user can log into B:, B4:,
; and MYDIR:, for example).
; VFILER is installed by Z3INS.
; VFILER works with ZCPR3 only, with 32k or more of RAM. File copy
; functions are faster with large amounts of RAM.
; VFILER can be assembled for use with a Z80 or 8080 microprocessor.
; SYSLIB, Z3LIB, and VLIB References
;
ext z3vinit,cls,gotoxy,ereol,envptr,getcrt,getprt,vprint
ext z3log,retud
ext fi0$open,f0$get,dutdir,fi0$close
ext sksp,putcl,getmdisk
ext cin,cout,caps,lout,crlf,lcrlf,pafdc,phlfdc
ext pfind,dnscan
ext getsh,getcl1,qshell,shpush,getzrun,putzex,putcst
ext getefcb,shpop,getsh2,getfn2,getshm,putshm
ext codend
ext stndout,stndend,getcl2,zprsfn ;<JPS>
;
; Basic Definitions
;
DIM EQU 1 ;GOTO DIM
BRIGHT EQU 2 ;GOTO BRIGHT
;
; User-Customized Definition
;
VFNAME MACRO ;;Name of VFILER
DB 'VFILER'
ENDM
VFNFILL MACRO ;;Spaces to fill out name to 8 chars
DB ' '
ENDM
;
Z80 EQU NOT I8080 ;<JPS> from Z3BASE.LIB
BIHELP EQU TRUE ;TRUE to provide built-in help info
WARMBOOT EQU FALSE ;set TRUE to warmboot on exit
DEFALPHA EQU TRUE ;set TRUE to alpha by name and type, FALSE for
; ... type and name by default
EPS EQU 18*4 ;N lines x 4 cols per screen
; EPS = Entries Per Screen
TAGCH EQU '#' ;character used to mark tagged files
DIRCMD EQU 'L' ;command used to log new dir -- be sure it
;does not conflict with other commands -- used
;to be 'N' for new (I prefer 'L' for log) <JPS>
;
; Command Line Builder Constants
;
FPESC EQU '%' ;escape char
FPDISK EQU 'D' ;disk only (D)
FPUSER EQU 'U' ;user only (U)
FPFILE EQU 'F' ;file name only
MNOTE EQU '#' ;denotes comment area in macro file
UIN1 EQU 27H ;single quote for user input
UIN2 EQU 22H ;double quote for user input
;
; Cursor Positioning Addresses
;
EPSLINE EQU (EPS/4)+4 ;position of last line of EPS
BANADR EQU 1*256+24 ;banner address
CURHOME EQU 3*256+1 ;home address of cursor
BOTADR EQU 24*256+1 ;bottom of screen
CPMADR EQU EPSLINE*256+1 ;command prompt message
CPADR EQU EPSLINE*256+22 ;command prompt
ERADR EQU (EPSLINE+1)*256+15 ;error message
FSADR EQU ERADR ;file size message
FNADR EQU 1*256+62 ;address of current file name
DUADR EQU 1*256+4 ;address of current DU
;
; System Functions
;
RDCON EQU 1
WRCON EQU 2
PUNCH EQU 4
LIST EQU 5
DIRCON EQU 6
RDBUF EQU 10
CONST EQU 11
RESETDK EQU 13
LOGIN EQU 14
OPEN EQU 15
CLOSE EQU 16
SRCHF EQU 17
SRCHN EQU 18
ERASE EQU 19
READ EQU 20
WRITE EQU 21
MAKE EQU 22
REN EQU 23
INQDISK EQU 25
SETDMA EQU 26
INQALC EQU 27
ATTR EQU 30
GETPARM EQU 31
SGUSER EQU 32
COMPSZ EQU 35
;
; System Addresses
;
OS$BASE EQU 000H ;system base..
CCPLEN EQU 800H ;..and 'ccp' length in bytes.
;<RLC> Changed name from CCP to CCPLEN
GET EQU 0FFH ;get user area e-reg value
BDOS EQU OS$BASE+05H
FCB EQU OS$BASE+5CH
FCBEXT EQU FCB+12
FCBRNO EQU FCB+32
FCB2 EQU OS$BASE+6CH
TBUF EQU OS$BASE+80H
TPA EQU OS$BASE+100H
;
; ASCII Definitions
;
CTRLA EQU 'A'-'@' ;<JPS>
CTRLC EQU 'C'-'@' ;..control-C..
CTRLD EQU 'D'-'@'
CTRLE EQU 'E'-'@'
CTRLF EQU 'F'-'@' ;<JPS>
CTRLR EQU 'R'-'@'
CTRLS EQU 'S'-'@' ;..XOFF..
CTRLX EQU 'X'-'@'
BS EQU 08H ;..backspace..
TAB EQU 09H ;..tab..
LF EQU 0AH ;..linefeed..
FF EQU 0CH ;..formfeed..
CR EQU 0DH ;..carriage return..
CAN EQU 18H ;..cancel..
EOFCHAR EQU 1AH ;..end-of-file..
CTRLZ EQU 1AH ;..clear screen..
ESC EQU 1BH ;..and escape character.
;
; MACROS TO PROVIDE Z80 EXTENSIONS
; MACROS INCLUDE:
;
; BR - JUMP RELATIVE
; BRC - JUMP RELATIVE IF CARRY
; BRNC - JUMP RELATIVE IF NO CARRY
; BRZ - JUMP RELATIVE IF ZERO
; BRNZ - JUMP RELATIVE IF NO ZERO
; BJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO
;
BR MACRO ?N ;;JUMP RELATIVE
IF Z80
.z80
jr ?N
.8080
ELSE
jmp ?N
ENDIF
ENDM
;
BRC MACRO ?N ;;JUMP RELATIVE ON CARRY
IF Z80
.z80
jr c,?N
.8080
ELSE
jc ?N
ENDIF
ENDM
;
BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
IF Z80
.z80
jr nc,?N
.8080
ELSE
jnc ?N
ENDIF
ENDM
;
BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
IF Z80
.z80
jr z,?N
.8080
ELSE
jz ?N
ENDIF
ENDM
;
BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
IF Z80
.z80
jr nz,?N
.8080
ELSE
jnz ?N
ENDIF
ENDM
;
BJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
IF Z80
.z80
djnz ?N
.8080
ELSE
dcr b
jnz ?N
ENDIF
ENDM
;
; END OF Z80 MACRO EXTENSIONS
;
;
; 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 ;<JPS> already included above
MACLIB SYSENV
z3eadr:
jmp start
SYSENV
start:
lxi h,z3eadr ;pt to ZCPR3 environment
endif
;
; Start of Program -- Initialize ZCPR3 Environment
; Once Environment is Initialized, One of Three Major Functions
; will be Performed:
; 1. VFILER will be installed as a Shell if invoked explicitly
; by user command
; 2. The VFILER Function will be performed if VFILER is invoked
; by ZCPR3 as a Shell and ZEX is not Running
; 3. A Command Line will be Input by VFILER from ZEX and Passed
; on to ZCPR3 without Processing
;
call z3vinit ;initialize the ZCPR3 Env and the VLIB Env
;
; Set Opsys Stack Pointer
;
if not WARMBOOT
lxi h,0 ;clear hl-pair then..
dad sp ;..add stack address.
shld stack
endif ;not warmboot
;
; Check to see if VFILER was executed as a shell
;
call qshell ;get and test message from ZCPR3
jz runsh ;execute shell procedures
;
; Initialize VFILER as a Shell
;
call shtest1 ;there must be a shell stack
call shtest2 ;there must be a command line buffer
;
; FUNCTION 1: Set Up VFILER as a Shell
; Run Shell Via Exit to Opsys
;
call getefcb ;determine name of program
brz shgo1 ;name not given, so use default
inx h ;pt to name
lxi d,filercmd ;define name of program
mvi b,8
call moveb ;copy name
shgo1:
call idu ;set initial disk/user
lxi h,filercmd ;establish shell
call shpush ;push onto shell stack
brnz shgo2 ;error?
call filsel ;select file mask <JPS>
;
; Print Done Message
;
call vprint
db ' Shell Installed',cr,lf,0
mvi b,0 ;shell message 0
mvi a,0 ;no wait
call putshm ;set shell message
;changes made by <JPS>
; jmp chain2 ;set IDU into command line and go
call chain2 ;set IDU into command line
call getcl2 ;see if any more commands on line
ora a
brz runsh ;if none, run shell immediately
jmp os$ccp1 ;else return to opsys
;
; Establish File Selection (made into subroutine <JPS>)
;
filsel:
call getfn2 ;setup file name
lxi d,11*3 ;use 4th system file
dad d
lxi d,fcb+1 ;pt to FCB
xchg
mvi b,11 ;copy 11 chars
call moveb
lxi h,joker ;make wild if FCB is empty
mvi b,11 ;11 chars
ldax d ;check first char
cpi ' '
cz moveb
ret
;
; Error in Shell Stack Installation
;
shgo2:
cpi 2 ;shell stack full
brnz shgo3
call vprint
db ' Shell Stack Full',0
ret
shgo3:
call vprint
db ' Shell Entry Size',0
ret
;
; VFILER was invoked as a Shell
; Check for ZEX Input in Progress
;
runsh:
call getzrun ;check ZEX message byte
jnz zexrun ;process ZEX command line if ZEX running
;
; FUNCTION 2: Run VFILER and Perform Main Function
;
mvi a,0 ;set no shell message
call putcst
call setup ;init buffers and pointers
call stackset ;setup stack
;
; Process Initial Help if Available and Requested
;
if BIHELP ;built-in help available?
lda fcb+1 ;check for initial help
cpi '/'
brnz runsh1
call helpmsg ;print help message
call sak ;strike any key to continue
br runsh2
runsh1:
endif ;BIHELP
;
; Check for Delay Before Resuming VFILER and Delay if Set
;
mvi b,0
call getshm ;get shell message 0
ani 80h ;check MSB
cnz sak ;pause for input
;
; Begin VFILER Processing
;
runsh2:
call stackset ;reset stack
call fload ;load files
push psw
call setscr ;set up screen display variables
pop psw
brnz runsh4 ;continue if OK
;
; Entry Point to Log Into New Dir and Resume
;
runsh3:
call logdir ;error - log into another dir
br runsh2
;
; Entry Point for Command Processing
; Display Screen and Input/Process Command
;
runsh4:
call stackset ;reset stack
call refresh ;refresh screen display
;
; Display Current File and Input/Process Command
;
loopfn:
call loopfn1 ;print current file name
;
; Input/Process Command
;
loop:
call stackset ;reset stack
call loopfn2 ;get command from user
call loopfn3 ;process command in A
br loop ;continue
;
; Set Stack Pointer
;
stackset:
pop d ;get return address
lhld crctbl ;top of stack
sphl ;start local stack
push d ;return address on new stack
ret
;
; Check for Presence of Shell Stack
;
shtest1:
call getsh ;get shell stack data
rnz
pop psw ;clear stack
call vprint
db 'No Shell Stack',0
ret
;
; Check for Command Line
;
shtest2:
call getcl1 ;get command line data
rnz
pop psw ;clear stack
call vprint
db 'No Cmd Line',0
ret
;
; FUNCTION 3: Run ZEX on Top of VFILER
; Accept Command Line and Pass it to ZCPR3
;
zexrun:
call vprint ;print prompt
db 'VFILER> ',0
mvi a,1 ;tell ZEX that it is prompted
call putzex
call getcl1 ;pt to command line buffer
mov a,l ;set ptr to first char
adi 4
mov c,a
mov a,h
aci 0
mov b,a ;BC pts to first char
mov m,c ;store low
inx h
mov m,b ;store high
inx h ;pt to char count
xchg ;... in DE
mvi c,rdbuf ;input line via BDOS
push d ;save ptr
call bdos
pop h ;pt to char count
inx h
mov e,m ;get char count
inx h ;pt to first char
push h ;save ptr
mvi d,0 ;DE=char count
dad d
xra a ;A=0
mov m,a ;store ending 0
pop h ;pt to first char
call putzex ;resume ZEX (A=0)
call putcst ;set command status to normal (A=0)
ret ;return to opsys
;
;**************************************************
;
; CRT Routine for VFILER
;
VCLS:
CALL CLS ;try to clear the screen
RNZ ;OK if done
PUSH H ;save regs
PUSH B
CALL GETCRT ;get CRT Data
INX H ;get number of lines on screen
MOV B,M ;B=number of lines
VCLS1:
CALL CRLF ;new line
BJNZ VCLS1
POP B ;restore regs
POP H
RET
;
; EREOL Routine for VFILER
;
VEREOL:
CALL EREOL ;try to erase to EOL
RNZ ;OK if done
PUSH B ;save count
MVI A,' ' ;space out
CALL VEREOL1 ;send B spaces
POP B ;get count
MVI A,BS ;backspace in
VEREOL1:
CALL COUT ;send char
BJNZ VEREOL1 ;count down
RET
;
; Setup Screen Display Variables
;
SETSCR:
LXI H,CURHOME ;set cursor home
SHLD CURAT
LHLD RING ;set ring position
;
; Entry to Reset Ring Position at HL
;
SETSCR1:
SHLD RINGPOS
;
; Entry to Reset Local Ring Position at HL
;
SETSCR2:
SHLD LOCBEG ;front of ring
LXI D,EPS*13 ;new end?
DAD D
XCHG
LHLD RINGEND ;end of ring
XCHG
CALL CMPDEHL
BRC SETSCR3
XCHG
SETSCR3:
XCHG
SHLD LOCEND
RET
;
; Display file name of current file
;
LOOPFN1:
LXI H,FNADR ;position cursor for file name print
CALL GOTOXY
LHLD RINGPOS ;pt to current file name
INX H ;pt to first char
;<RID> JMP PRFN ;print file name
CALL STNDOUT ;<RID> turn on highlighting
CALL PRFN ;<RID> print file name
CALL STNDEND ;<RID> turnoff highlighting;
RET ;<RID>
; Get command from user and clear error line if any
;
LOOPFN2:
CALL ATCMD ;position at command prompt
CALL DKEYIN ;wait for character from keyboard
PUSH PSW ;save command
LDA ERMFLG ;error message?
ORA A ;0=no
CNZ ERCLR ;erase old error message
POP PSW ;get command
RET
;
; Process Command
;
LOOPFN3:
CPI MNOTE ;command summary
BRZ CPROCM
CPI '0' ;macro?
BRC CPROC0
CPI '9'+1 ;macro?
BRNC CPROC0
CPROCM:
CALL CMACRO ;process macro command
MOV B,A ;save command
CALL ERMSG
DB 'No U Fct ',0
MOV A,B ;get macro digit
JMP COUT ;return for loop processing
CPROC0:
CALL CTPROC ;process command or return if not found
CALL ERMSG
DB 'Invld Cmd: ',0
MOV A,B ;get char
CPI ' ' ;expand if less than space
BRNC CPROC1
MVI A,'^' ;control
CALL COUT
MOV A,B ;get byte
ADI '@' ;convert to letter
CPROC1:
JMP COUT ;return for loop processing
;
; SET UP BUFFERS
;
SETUP:
CALL RETUD ;get home DU
MOV A,B
STA H$DR ;home drive
MOV A,C
STA H$U$A ;home user area
CALL CODEND ;start of free space
LXI D,100H ;256 bytes/unit
DAD D
SHLD CRCTBL ;table for CRC list et al
DAD D
DAD D ;allow 512 bytes
SHLD CMDBUF ;command line buffer
MVI M,64 ;64 bytes in line
LXI D,70 ;arbitrary beyond EOL
DAD D
SHLD DUM$FCB ;dummy FCB
INR H
MVI L,0 ;next page
SHLD BUFENTRY ;free space to end of TPA
;
; Set CRT/Printer Data
;
CALL GETCRT ;CRT DATA
MOV A,M
STA CWIDTH ;WIDTH
INX H
MOV B,M
INX H
MOV A,M
STA CTPP ;TEXT
MOV C,A
MOV A,B ;TOTAL NUMBER OF LINES
SUB C
DCR A ;1 LESS
STA CSPP ;LINES TO SKIP
CALL GETPRT ;PRINTER DATA
MOV A,M
STA LWIDTH ;WIDTH
INX H
MOV B,M
INX H
MOV A,M
STA LTPP ;TEXT
MOV C,A
MOV A,B ;TOTAL NUMBER OF LINES
SUB C
STA LSPP ;LINES TO SKIP
INX H
MOV A,M
STA LFFEED ;CAN FORM FEED?
;
; Begin Further Inits
;
XRA A
STA HELPDISP ;no help display yet
;
MVI A,DEFALPHA ;alpha by name and type
STA ALPHA
;
LHLD ENVPTR ;pt to ZCPR3 Env Desc
LXI D,80H+10H ;pt to cursor commands
DAD D
LXI D,CTABLE ;pt to area
MVI B,4 ;4 commands
CURINIT:
MOV A,M ;get command
STAX D ;put it
INX H ;pt to next
INX D
INX D
INX D
BJNZ CURINIT
;
CALL IDU ;set initial disk/user
CALL LOGRDU ;log into it
;
LHLD BUFENTRY ;base address
SHLD RING ;beginning of ring
;
LXI H,CURHOME ;home address for cursor
SHLD CURAT
;
CALL GETMDISK ;get max disk number (1-N)
ADI '@' ;convert to ASCII (A-P)
STA MAXDR ;set letter
;
RET
; set initial disk/user
IDU:
LXI D,FCB ;log into DU specification
CALL Z3LOG ;perform login
IDU1:
CALL RETUD ;get current DU in BC
MOV A,C ;get current user
CALL IDU$USET ;set it
MOV A,B ;get current disk
CALL IDU$DSET ;set it
RET
IDU$USET:
STA C$U$A ;..store as current and..
STA O$USR ;..as original for exit.
STA R$U$A ;..requested user area
RET
IDU$DSET:
STA C$DR
STA R$DR ;requested disk
RET
; check for existance of file whose first 12 FCB bytes are pted to by DE
; return with A=0 if not found, A=0FFH if found
FILECHK:
LXI H,S$FCB ;copy into FCB
XCHG
MVI B,12 ;12 bytes
CALL MOVE ;copied into S$FCB
XCHG ;HL pts to FCB
CALL INITFCB ;init FCB
LXI D,S$FCB ;pt to FCB
JMP FFIND
;
; Select drive and user area (system reset for disk change on-the-fly)
; <JPS>
;
LOGDIR:
CALL CPRMPT ;prompt to get drive/user selection
DB 'Login DIR (and file mask): ',0
CALL DEFSPEC ;define full file specification
LOG1:
CALL LOGRDU ;set current and log in
JMP CRLF ;new line and exit
;
; Actually log into DU requested
;
LOGRDU:
LDA R$DR ;make requested disk current
STA C$DR
CALL RESET ;reset disk system
LDA R$U$A ;establish requested area..
STA C$U$A ;..as current area.
CALL SET$USR
LXI H,0 ;initialize tagged..
SHLD TAG$TOT ;..file size accumulator.
RET
;
; Define file specification <JPS>
; (comes before DEF$D$U and includes preparing to change system file 4 for new
; mask)
;
DEFSPEC:
CALL RDSPEC ;get user input
CALL TOKEN1 ;position HL to first token and test for end
JZ LOOP ;if no entry, loop back for another command
LXI D,FCB ;use default FCB
CALL ZPRSFN ;parse the filespec into FCB
CALL FILSEL ;copy filespec into system file 4
CALL TOKEN1 ;back to first token
XRA A ;scan for DIR before DU
CALL DNSCAN ;scan again to get drive and user values
BRNZ DEFDU2 ;if found, enter new values
RET ;otherwise, just return
;
; Define current drive and user area
; many modifications <JPS>
;
DEF$D$U:
CALL RDSPEC ;read DU and filespec <JPS>
CALL TOKEN1 ;position HL to first token
JZ LOOP
;delete this redundant test <JPS>
;
; MOV A,M ;check for exit
; CALL CAPS
; CPI 'X'
; BRNZ DEFDU1
; INX H ;check for space or EOL
; MOV A,M
; DCX H
; ANI 7FH ;mask MSB
; CPI ' '+1
; JC OS$CCP ;abort
;DEFDU1:
XRA A ;A=0 to scan for DIR before DU
CALL DNSCAN ;look for DU or DIR form and return DU
BRZ ERRET ;error
DEFDU2:
MOV A,B ;return disk and user
STA R$DR
INR A ;set FCB
STA FCB
MOV A,C
STA R$U$A
RET
;
; position to first token and set flag to show end of buffer
;
TOKEN1:
LHLD CMDBUF ;pt to possible drive
INX H
INX H
CALL SKSP ;skip over leading spaces and return
MOV A,M ;check for no input
ORA A
RET
;
; reads line of input from user -- pulled out as subroutine <JPS>
;
RDSPEC:
LHLD CMDBUF ;pt to command line buffer
INX H
INX H
MVI B,20 ; # of blanks to..
CALL FILL ;..clear 'cmdbuf'.
LHLD CMDBUF ;get DU selection from..
XCHG
MVI C,RDBUF ;..console buffer read.
CALL BDOS
JMP CONVERT ;make sure alpha is upper case and return
;
; Error return and recovery from command cancellation
;
ERRET:
CALL ERMSG
DB 'DIR Entry Error',0
JMP LOOP
COMCAN:
LDA CANFLG ;check for nature of abort
ORA A ;..from..
JZ RUNSH2 ;no file found, so run the shell again
JMP RUNSH4 ;..error/command abort.
;
; find file along path (file FCB pted to by DE)
; on return, A=0FFH if found, A=0 if not found, and flags set
;
FFIND:
MVI A,0FFH ;look in current dir also
JMP PFIND ;path search from Z3LIB
; log in default directory
DLOGIN:
LDA C$DR ;disk in B
MOV B,A
LDA C$U$A ;user in C
MOV C,A ;fall thru to SLOGIN
; log in DU in BC
SLOGIN:
PUSH H ;save regs
PUSH D
PUSH B
MOV A,C ;set user
CALL SET$USR
POP B
MOV A,B ;set disk
CALL SET$DR
POP D ;restore regs
POP H
RET
; e x i t
; return to ccp
;
; Entry point for VFILER exit
;
OS$CCP:
CALL SHPOP ;clear shell stack
;
; Entry point for command line exec
;
OS$CCP1:
LDA O$USR ;get and set original..
CALL SET$USR ;..user area and..
LXI D,TBUF ;..tidy up..
MVI C,SETDMA ;..before going home.
CALL BDOS
IF WARMBOOT
JMP OS$BASE
ENDIF ;warmboot
IF NOT WARMBOOT
LHLD STACK ;put pointer..
SPHL ;..back to 'sp'.
RET ;return to ccp
NOP ; to try jump to start
NOP
ENDIF ;not warmboot
;
; FLOAD loads the files into the buffer, setting up the ring
; Return with NZ if load OK, Z if no files loaded
;
FLOAD:
CALL FRESTOR ;get bytes remaining on drive (decode default)
;
; Set up file name from System File 4
; Select all files if no entry in System File 4
;
CALL GETFN2 ;pt to first system file name
LXI D,11*3 ;pt to 4th file name
DAD D
LXI D,FCB+1 ;pt to FCB
MVI B,11 ;11 bytes
CALL MOVEB
LXI H,JOKER ;..treat as '*.*' with 'joker'..
MVI B,11 ; # of characters to move
LDAX D ;get first char of file name
CPI ' ' ;if space, fill with *.*
CZ MOVEB ;set field to *.*
LDAX D ;get first char of file name
CPI '/' ;if opt, fill with *.*
CZ MOVEB
;
; Build ring with filename positioned in default FCB area
;
MVI C,SETDMA ;initialize dma address..
LXI D,TBUF ;..to default buffer.
CALL BDOS
XRA A ;clear search 'fcb'..
STA FCBEXT ;extent byte..
STA FCBRNO ;..and record number.
LXI D,FCB ;default FCB for search
CMA
STA CANFLG ;make cancel flag true
MVI C,SRCHF ;..of first occurrence.
CALL BDOS
INR A ; 0ffh --> 00h if no file found
BRNZ SETRING ;if found, branch and build ring.
STA CANFLG ;make log-cancel toggle false (0)
CALL ERMSG ;else say none found, fall thru to log.
DB 'No File Found',0
XRA A ;Set Error Code
RET
; establish ring (circular list) of filenames
SETRING:
LHLD RING ;initialize ring pointer
SHLD RINGPOS ;start --> current position of ring
; put each found name in ring. a-reg --> offset into 'tbuf' name storage
TO$RING:
DCR A ;un-do 'inr' from above and below
ADD A ;times 32 --> position index
ADD A
ADD A
ADD A
ADD A
ADI TBUF ;add page offset and..
MOV L,A ;..put address into..
MVI H,0 ;..hl-pair.
LDA FCB ;get drive/user designator and..
MOV M,A ;..put into 'fcb' buffer.
XCHG
LHLD RINGPOS ;pointer to current load point in ring
XCHG
MVI B,12 ;move drive designator and name to ring
CALL MOVE
XCHG ;de-pair contains next load point address
MVI M,' ' ;space for potential..
INX H ;..tagging of files for mass copy.
SHLD RINGPOS ;store and search..
MVI C,SRCHN ;..for next occurrence.
LXI D,FCB ;filename address field
CALL BDOS
INR A ;if all done, 0ffh --> 00h.
BRNZ TO$RING ;if not, put next name into ring.
;
; All filenames in ring -- setup ring size and copy-buffer start point
;
LHLD RINGPOS ;next load point of ring is start of buffer
SHLD RINGEND ;set ring end..
SHLD BUFSTART ;..and copy-buffer start.
PUSH H
LHLD RING
LXI D,13 ;compare 'ringend' (tab base+13)
DAD D
XCHG
POP H
CALL CMPDEHL
BRNZ SORT ;sort if more than one file in ring
XRA A ;set NZ for Return
DCR A
RET
;
; Sort ring of filenames
;
SORT:
LHLD RING ;initialize 'i' sort variable and..
SHLD RINGI
LXI D,13 ;..also 'j' variable.
DAD D
SHLD RINGJ
SORTLP:
LHLD RINGJ ;compare names 'i & j'
XCHG
LHLD RINGI
PUSH H ;save position pointers..
PUSH D ;..for potential swap.
LDA ALPHA ;check for type of alphabetization
ORA A ;if Zero, alpha by type and name
JZ SORTTN
; sort by file name and type
MVI B,12 ; # of characters to compare
CALL CMPSTR ;do comparison
BR NOCMP ;final test
; sort by file type and name
SORTTN:
PUSH H ;save ptrs
PUSH D
LXI B,9 ;pt to type
DAD B
XCHG
DAD B
XCHG
MVI B,3 ;3 chars in file type
CALL CMPSTR ;compare type
POP D ;get ptrs
POP H
BRNZ NOCMP ;final test
PUSH H
PUSH D
MVI B,8 ;8 chars in file name
INX H ;pt to first
INX D
CALL CMPSTR ;compare name
POP D ;get ptrs
POP H
BRNZ NOCMP ;final test
LDAX D ;final compare and fall thru
CMP M
; final test for swapping purposes
NOCMP:
POP D
POP H
MVI B,13
BRNC NOSWAP
;
; Swap if 'j' string larger than 'i'
;
SWAP:
MOV C,M ;get character from one string..
LDAX D ;..and one from other string.
MOV M,A ;second into first
MOV A,C ;first into second
STAX D
INX H ;bump swap pointers
INX D
BJNZ SWAP
NOSWAP:
LHLD RINGJ ;increment 'j' pointer
LXI D,13
DAD D
SHLD RINGJ
XCHG ;see if end of 'j' loop
LHLD RINGEND
CALL CMPDEHL
JNZ SORTLP ;no, so more 'j' looping.
LHLD RINGI ;bump 'i' pointer
LXI D,13
DAD D
SHLD RINGI
DAD D ;set start over 'j' pointer
SHLD RINGJ
XCHG ;see if end of 'i' loop
LHLD RINGEND
CALL CMPDEHL
JNZ SORTLP ;must be more 'i' loop to do
;
; Sort done -- initialize tables for fast crc calculations
;
CALL INITCRC
;
; Calculate buffer maximum available record capacity
;
B$SIZE:
LXI B,0 ;count records
LHLD BDOS+1 ;get 'bdos' entry (fbase)
IF NOT WARMBOOT
LXI D,-(CCPLEN)
DAD D
ENDIF ;not warmboot
DCX H
XCHG ;de-pair --> highest address of buffer
LHLD BUFSTART ;start address of buffer (end of ring list)
B$SIZE2:
INX B ;increase record count by one
PUSH D
LXI D,128 ; 128-byte record
DAD D ;buffer address + record size
POP D
CALL CMPDEHL ;compare for all done
BRNC B$SIZE2 ;more will fit?
DCX B ;set maximum record count less one
MOV A,B ;memory available for copy?
ORA C
BRNZ B$SIZE3 ;yes, buffer memory space available.
CALL ERMSG
DB 'No Room',0
XRA A ;Error code
RET
B$SIZE3:
MOV L,C ;store..
MOV H,B ;..maximum..
SHLD REC$MAX ;..record count.
XRA A ;return NZ for OK
DCR A
RET
;
; left to right compare of two strings (de-pair points to 'a' string;
; hl-pair, to 'b'; b-reg contains string length.)
;
CMPSTR:
LDAX D ;get an 'a' string character and..
CMP M ;..check against 'b' string character.
RNZ ;if not equal, set flag.
INX H ;bump compare..
INX D ;..pointers and..
DCR B ; (if compare, set as equal.)
BRNZ CMPSTR ;..do next character.
RET
;
; COMMAND: MACRO (0-9)
; Process macro command
;
CMACRO:
PUSH PSW ;save digit
LXI H,MACFCB ;set up name of macro file
LXI D,S$FCB
PUSH D
MVI B,12 ;12 chars
CALL MOVE
XCHG
CALL INITFCB ;init FCB
POP D ;pt to FCB
CALL FFIND ;search along path for file
BRNZ CMFOUND ;file found
POP PSW ;clear stack
POP D ;clear ret address
CALL ERMSG
DB 'File ',0
LXI H,MACFCB+1
CALL PRFN ;print file name
CALL VPRINT
DB ' NOT Found',0
JMP LOOP
; found macro file
CMFOUND:
CALL SLOGIN ;log in
CALL FI0$CLOSE ; CLOSE FILE IF ALREADY OPEN
LXI D,S$FCB ;pt to FCB
CALL FI0$OPEN ;open for byte-oriented input
POP PSW ;get command
MOV C,A ;... in C
; new line
CMFL1:
CALL F0$GET ;get first char of line
JNZ CMFLERR ;EOF encountered
CMP C ;match?
BRZ CMFL3
; skip out line
CMFL2:
CALL F0$GET ;skip out line
JNZ CMFLERR
CPI LF ;EOL?
BRNZ CMFL2
BR CMFL1
; found command
CMFL3:
MVI A,MNOTE ;macro note?
CMP C
JZ CMFLNOTE
PUSH D
LHLD CRCTBL ;buffer for command line
LXI D,256 ;+256
DAD D
POP D
; skip leading blanks in command line
CMFL4:
CALL F0$GET ;get next char
BRNZ CMFL6 ;mark end of buffer and go
CPI ' ' ;skip leading blanks
BRZ CMFL4
; load command line into buffer
CMFL5:
ANI 7FH ;mask char
CPI CR ;EOL?
BRZ CMFL6
CPI CTRLZ ;EOF?
BRZ CMFL6
CPI FPESC ;file pted to?
JZ CMFLIF
CPI UIN1 ;user input?
BRZ CMFL5A
CPI UIN2
BRZ CMFL5A
CMFL50:
MOV M,A ;store char
INX H ;pt to next
CMFL51:
CALL F0$GET ;get next char
BRZ CMFL5
BR CMFL6
; print prompt to user and get input
CMFL5A:
PUSH H ;save buffer ptr
CALL CPRMPT ;at command prompt line
DB 0
CMFL5B:
CALL F0$GET ;get next char
BRNZ CMFL5B1
ANI 7FH ;mask
CPI UIN1 ;end of prompt?
BRZ CMFL5C
CPI UIN2
BRZ CMFL5C
CPI CR ;end of prompt?
BRZ CMFL5C
CPI CTRLZ ;eof?
BRZ CMFL5C
CALL COUT ;send char
BR CMFL5B
CMFL5B1:
MVI A,CTRLZ ;eof
CMFL5C:
PUSH PSW ;save offending char
LHLD BUFSTART ;pt to buffer
MVI M,128 ;128 char in line
INX H ;set no chars
MVI M,0
DCX H ;pt to count
XCHG
MVI C,RDBUF ;get line from user
CALL BDOS
LHLD BUFSTART
INX H ;pt to count
MOV A,M ;get count
INX H ;pt to first char
PUSH H ;save ptr
ADD L
MOV L,A
MOV A,H
ACI 0
MOV H,A ;HL pts to after last char
MVI M,0 ;store ending zero
POP H ;HL pts to first char of line
POP PSW ;get char
POP D ;DE pts to next char in buffer
MOV B,A ;char in B
CMFL5D:
MOV A,M ;copy chars
ORA A ;zero=done
BRZ CMFL5E
STAX D ;put char
INX H ;pt to next
INX D
BR CMFL5D
CMFL5E:
XCHG ;HL pts to next char in buffer
MOV A,B ;check offending char
CPI UIN1 ;user input?
BRZ CMFL51
CPI UIN2
BRNZ CMFL5
BR CMFL51
; complete buffer and test for content
CMFL6:
MVI M,0 ;store ending 0
PUSH D
LHLD CRCTBL ;pt to first char in line
LXI D,256
DAD D
POP D
MOV A,M ;get first char
ORA A ;empty?
BRNZ CMFL7
; error return
CMFLERR:
PUSH B
CALL DLOGIN ;return home
POP B
MOV A,C ;invalid command
RET
; try to chain
CMFL7:
PUSH H ;save ptr
CALL DLOGIN ;return home
POP H
CALL CHAIN ;chain to command line pted to by HL
JMP LOOP
; print documentation built into the macro file
CMFLNOTE:
CALL VCLS ;new screen
MVI C,0 ;set tab counter
CMFLN1:
CALL F0$GET ;get next char
BRNZ CMFLN4 ;done
ANI 7FH ;mask
CPI CTRLZ ;eof=done
BRZ CMFLN4
CPI TAB ;tab process
BRZ CMFLN2
CALL COUT ;print char
CPI CR ;new line?
BRZ CMFLN3
INR C ;new pos
CPI LF
BRNZ CMFLN1
DCR C ;back up position count
BR CMFLN1
CMFLN2:
MVI A,' ' ;space over for tab
CALL COUT
INR C ;incr position
MOV A,C ;done?
ANI 7 ;every 8
BRNZ CMFLN2
BR CMFLN1
CMFLN3:
MVI C,0 ;bol for CR
BR CMFLN1
CMFLN4:
CALL DLOGIN ; RETURN HOME
LHLD RINGPOS ;print current file
INX H
CALL PRFN
CALL VPRINT
DB ' Enter Digit or RETURN - ',0
CALL DKEYIN
POP D ;get ret address
CPI '0' ;in range?
JC RUNSH4
CPI '9'+1 ;in range?
JNC RUNSH4
PUSH D ;replace ret address
JMP CMACRO
; insert file pted to (% prefix command)
CMFLIF:
CALL F0$GET ;get next char
JNZ CMFL6
CPI FPESC ;doubled?
JZ CMFL50
LXI D,CMFL51 ;return address
PUSH D ;... on stack
ANI 5FH ;capitalize
CPI FPFILE ;file only?
BRZ CMFLIF1
CPI FPDISK ;disk only?
BRZ CMFLIF2
CPI FPUSER ;user only?
BRZ CMFLIF3
CALL CMFLIF2 ;Disk
CALL CMFLIF3 ;User
MVI M,':' ;separator
INX H ;fall thru to file name
CMFLIF1:
XCHG ;save ptr to next
LHLD RINGPOS ;pt to current file
INX H
MVI B,8 ;8 chars in filename
CALL CMFL5X
MVI A,'.' ;put dot
STAX D
INX D
MVI B,3 ;3 chars max
CALL CMFL5X
XCHG ;HL pts to next
RET
CMFLIF2:
LDA C$DR ;store disk
ADI 'A'
MOV M,A
INX H ;pt to next
RET
CMFLIF3:
LDA C$U$A ;user
CPI 10 ;less than 10?
BRC CMFLIF32
MVI B,'0' ;compute 10's
CMFLIF30:
SUI 10 ;subtract 10's
BRC CMFLIF31
INR B
BR CMFLIF30
CMFLIF31:
ADI 10
MOV M,B ;store 10's
INX H
CMFLIF32:
ADI '0' ;store 1's
MOV M,A
INX H
RET
CMFL5X:
MOV A,M ;get char
CPI ' '
BRZ CMFL5X1
STAX D ;put char
INX H ;pt to next
INX D
BJNZ CMFL5X
RET
CMFL5X1:
INX H ;advance
BJNZ CMFL5X1
RET
;
; Process command from table
;
CTPROC:
MOV B,A ;command in B
LXI H,CTABLE ;pt to table
MOV A,M ;any cursor commands?
ORA A
JNZ CTPR1
LXI H,CTAB1
;
; Command table scanner
; HL = Table
; B = Command Letter
;
CTPR1:
MOV A,M ;get table command char
ORA A ;end of table?
RZ ;done if so
CMP B ;match?
BRZ CTPR2
INX H ;skip to next entry
INX H
INX H
BR CTPR1
CTPR2:
INX H ;pt to address
MOV A,M ;get low
INX H
MOV H,M ;get high
MOV L,A
XTHL ;address on stack
RET ;"jump" to routine
; Command Table
CTABLE:
DB 0 ;user cursor positioning
DW UP
DB 0
DW DOWN
DB 0
DW FORWARD
DB 0
DW REVERSE
CTAB1:
DB CTRLC ;if exit, then to opsys
DW OS$CCP
DB 'X' ;alternate exit <JPS>
DW OS$CCP
DB CTRLR ;screen refresh?
DW RUNSH4
DB CTRLE ;system cursor positioning
DW UP
DB CTRLX
DW DOWN
DB CTRLD
DW FORWARD
DB CTRLS
DW REVERSE
DB '.' ;alternate commands <JPS>
DW FORWARD
DB '>'
DW FORWARD
DB ','
DW REVERSE
DB '<'
DW REVERSE
DB CR ;nop
DW LOOP
DB '+' ;jump forward
DW JUMPF
DB CTRLF ;jump forward <JPS>
DW JUMPF
DB '-' ;jump backward
DW JUMPB
DB CTRLA ;jump backward <JPS>
DW JUMPB
DB ' ' ;go forward
DW FORWARD
DB BS ;back up?
DW REVERSE
DB 'A' ;alphabetize?
DW ALPHASW
DB 'C' ;copy a file?
DW FCOPY
DB 'D' ;delete a file?
DW FDEL
DB 'F' ;show file size?
DW FSIZE
DB 'G' ;group operation?
DW GROUP$OP
DB 'H' ;external help?
DW EXTHELP
DB 'J' ;jump to a file?
DW GOTO
DB DIRCMD ;log-in another drive?
DW RUNSH3
DB 'P' ;output file to 'list' device?
; DW LSTFILE ;<RID>
DW SPRINT ;<RID>
DB 'Q' ;screen refresh?
DW RUNSH4
DB 'R' ;rename?
DW RENAME
DB 'S' ;free bytes on..
DW DSTAT ;..requested drive?
DB 'T' ;if tag, put TAGCH in..
DW TAG ;..front of cursor.
DB 'U' ;remove TAGCH from..
DW UNTAG ;..in front of cursor?
DB 'V' ; 'view' file at console?
DW VIEW
DB 'Z' ;run ZCPR3 command
DW RUNZCPR3
;
IF BIHELP ;built-in help?
DB '?' ;help
DW HELP
DB '/' ;help also
DW HELP
ELSE
DB '?' ;help
DW EXTHELP
DB '/' ;help also
DW EXTHELP
ENDIF ;BIHELP
;
DB 0 ;end of table
; h e l p (menu)
IF BIHELP ;built-in Help?
HELPMSG:
CALL VPRINT
DB CR,LF,CR,LF
DB ' '
DB '-- Tagging Commands -- --------- File Operat'
DB 'ions ----------',CR,LF
DB ' '
DB ' T - ',DIM,'Tag File',BRIGHT
DB ' C - ',DIM,'Copy File',BRIGHT,' '
DB 'D - ',DIM,'Delete File',BRIGHT,CR,LF
DB ' '
DB ' U - ',DIM,'Untag File',BRIGHT
DB ' F - ',DIM,'File Size',BRIGHT,' '
DB 'R - ',DIM,'Rename File',BRIGHT,CR,LF
DB ' '
DB ' G - ',DIM,'Group '
DB 'Copy/Delete/FSize/Tag/Untag',BRIGHT,CR,LF ;<RID>
DB ' '
DB ' ',DIM,'Group ' ;<RID>
DB 'Print/View',BRIGHT,CR,LF,CR,LF ;<RID>
DB ' '
DB '-- File Print & View -- --- User Functions ---',CR,LF
DB ' -- Cursor -- '
DB 'P - ',DIM,'Print',BRIGHT
DB ' V - ',DIM,'View',BRIGHT
DB ' 0-9 - ',DIM,'Execute',BRIGHT,' ',MNOTE,' - ',DIM,'Help'
DB BRIGHT,CR,LF
DB ' ^E '
DB CR,LF
DB ' ^ '
DB '-- Movement Commands -- ---- Miscellaneous ----',CR,LF
DB ' ^S <-+-> ^D '
DB ' <SP> - ',DIM,'File Forward'
DB BRIGHT,' A - ',DIM,'Toggle Alpha Sort',BRIGHT,CR,LF
DB ' v '
DB ' <BS> - ',DIM,'File Backward'
DB BRIGHT,' H - ',DIM,'Help File',BRIGHT,CR,LF
DB ' ^X '
DB ' + - ',DIM,'Screen Forward',BRIGHT
DB ' '
DB DIRCMD ;changes to reflect command choice <JPS>
DB ' - ',DIM,'Log DIR and/or Mask',BRIGHT,CR,LF
DB ' '
DB ' - - ',DIM,'Screen Backward',BRIGHT
DB ' S - ',DIM,'Disk Status',BRIGHT,CR,LF
DB ' -- Screen -- '
DB ' J - ',DIM,'Jump to a File',BRIGHT
DB ' Z - ',DIM,'ZCPR3 Command',BRIGHT,CR,LF
DB ' ^A ',DIM,'Backward',BRIGHT,' ' ;<JPS>
DB ' Q - ',DIM,'Refresh Screen',BRIGHT
DB ' ^C - ',DIM,'Exit',BRIGHT,CR,LF
DB ' ^F ',DIM,'Forward',BRIGHT,' ' ;<JPS>
IF BIHELP ;<JPS>
DB ' ' ;<JPS>
DB '? or / - ',DIM,'Toggle Help Screen',BRIGHT ;<JPS>
ENDIF ;<JPS>
DB 0
RET
HELP:
LDA HELPDISP ;toggle flag
CMA
STA HELPDISP
JMP RUNSH4 ;refresh screen and restart
ENDIF ;BIHELP
;
; COMMAND: H
;
EXTHELP:
CALL CPRMPT
DB 'Read Help File (Y/N)? ',0
CALL CIN
CALL CAPS
CPI 'Y'
JNZ LOOPFN
CALL ERMSG
DB DIM,'Chaining to Help File ...',BRIGHT,0
LXI H,MOREHELP ;run HELP Command
CALL CHAIN ;chain to it
JMP LOOPFN
;
; COMMAND: A
;
; Toggle alphabetize switch and reload files
;
ALPHASW:
LDA ALPHA ;toggle flag
CMA
STA ALPHA
CALL CPRMPT ;tell user what is happening
DB 'Sorting by File ',0
LDA ALPHA ;get flag
ORA A ;check it
BRZ ASWTN
CALL VPRINT
DB 'Name and Type',0
JMP RUNSH2
ASWTN:
CALL VPRINT
DB 'Type and Name',0
JMP RUNSH2 ;reload files
;
; COMMAND: Z
;
; Execute ZCPR3 command line
;
RUNZCPR3:
CALL ERMSG ;position at error message line
DB 0
LXI H,H$DR ;pt to Home Drive (followed by Home User)
CALL PRDU ;print DU
CALL VPRINT ;print prompt
DB '> ',0
PUSH D
LHLD CRCTBL ;use last half of CRC Table
LXI D,256
DAD D
POP D
MVI M,126 ;store length of line
INX H
MVI M,0 ;store count
DCX H ;pt to beginning
XCHG ;DE pts to buffer
PUSH D
MVI C,RDBUF ;Read Line from User
CALL BDOS
POP H
INX H ;pt to char count
MOV E,M
INX H ;pt to first char
MVI D,0 ;set no high-order offset
PUSH H ;save current ptr for later
DAD D
MVI M,0 ;store ending zero
POP H ;pt to first char of command line
MOV A,M ;abort if no first char
ORA A
JZ LOOP
CALL CHAIN ;chain to it
JMP LOOPFN ;continue
; chain to command pted to by HL ending in zero
CHAIN:
CALL PUTCL ;store command line
BRNZ CHAIN1
CALL ERMSG
DB 'CL Err',0
RET
CHAIN1:
MVI B,0 ;set shell message 0
MVI A,80H ;enable wait
CALL PUTSHM
CALL CHAIN2 ;<JPS>
JMP OS$CCP1 ;run command line - moved <JPS>
;made a subroutine <JPS>
CHAIN2:
LDA C$DR ;get current disk
ADI 'A' ;convert to ASCII
STA FILE$D ;store in proper place
LDA C$U$A ;get current user
LXI H,FILE$U ;store user number
MVI C,'0' ;set char
CHAIN3:
SUI 10 ;convert to ASCII
BRC CHAIN4
INR C ;increment 10's char
BR CHAIN3
CHAIN4:
MOV M,C ;store 10's digit char
INX H ;pt to 1's digit
ADI 10+'0' ;add back for 1's digit
MOV M,A ;store 1's digit char
CALL GETSH2 ;pt to shell buffer
LXI D,8 ;skip 8 chars (VFILER Name)
DAD D
LXI D,FILE$D ;place DU
XCHG
MVI B,5 ;store 5 chars (duu:0)
CALL MOVEB
RET ;<JPS>
;
; COMMAND: G
;
; Group operation
;
GROUP$OP:
CALL CPRMPT
DB 'Group Cmd (Copy/View/Print/Delete/File Sizes/' ;<RID>
DB 'Tag/Untag)? ',0 ;<RID>
CALL KEYIN ;get response
MOV B,A ;command in B
LXI H,GTABLE ;pt to table
CALL CTPR1 ;process command
JMP LOOP ;resume if not found
;
; Group Command Table
;
GTABLE:
DB 'C'
DW MASS$COPY
DB 'D'
DW MASS$DEL
DB 'P' ;<RID>
DW MASS$PRINT ;<RID>
DB 'V' ;<RID>
DW MASS$VIEW ;<RID>
DB 'F'
DW MASS$FSIZE
DB 'T'
DW MASS$TAG
DB 'U'
DW MASS$UNTAG
DB 0 ;end of table
;
; COMMAND: GU
;
MASS$UNTAG:
MVI B,' ' ;untag char
;
; Common Entry Point for Mass Untag/Tag - B = Untag/Tag Char
;
MUTLOOP:
LHLD RINGPOS ;move to tag
LXI D,12
DAD D
MOV M,B ;set tag byte
INX H ;pt to next
SHLD RINGPOS
XCHG ;done?
LHLD LOCEND
CALL CMPDEHL
BRNZ MUTLOOP
LXI H,CURHOME ;reset cursor
SHLD CURAT
LHLD LOCBEG ;set ring position
JMP JFW0 ;reset screen from LOCBEG
;
; COMMAND: GT
;
MASS$TAG:
MVI B,TAGCH ;tag char
BR MUTLOOP ;do work
;
; COMMAND: U
;
UNTAG:
MVI B,' ' ;set tag byte
;
; Common Entry Point for Untag/Tag - B = Untag/Tag Char
;
UT:
LHLD RINGPOS ;move back one..
LXI D,12 ;..character position..
DAD D ;..and check tagging status.
MOV M,B ;if file previously tagged, remove..
CALL REFFN ;refresh file name
JMP FORWARD
;
; COMMAND: T
;
TAG:
MVI B,TAGCH ;tag char
BR UT ;do tag
;
; Refresh file name with new tag
;
REFFN:
CALL CLRCUR ;clear cursor
MVI A,' ' ;one more space
CALL COUT
LHLD RINGPOS ;reprint file name
;<RID> INX H
;<RID> CALL PRFN
;<RID> MOV A,M ;print tag
;<RID> JMP COUT
CALL HILITFN ;<RID> brighten
RET ;<RID>
;
; COMMAND: GF
;
MASS$FSIZE:
CALL WORKMSG ;print 'Working' msg
LXI H,0 ;zero total
SHLD TAG$TOT
LHLD RINGPOS ;save ring position
SHLD SRINGPOS
LHLD RING ;set new ring position
SHLD RINGPOS
;
; Main Loop to Compute File Sizes
;
MASS$FS:
LHLD RINGEND ;at end of ring?
XCHG
LHLD RINGPOS
CALL CMPDEHL ;same if so
BRZ MASS$FS2
LXI D,12 ;pt to tag
DAD D
MOV A,M ;get tag
INX H ;pt to next file
CPI TAGCH ;tagged?
BRNZ MASS$FS1 ;skip if not tagged
;
; Compute Size of Tagged File
;
PUSH H ;save ptr to next file
CALL SIZER ;compute file size
XCHG ;size in DE
LHLD TAG$TOT ;get total
DAD D
SHLD TAG$TOT ;new total
POP H ;get ptr to next file
MASS$FS1:
SHLD RINGPOS ;set ptr to next file
BR MASS$FS
;
; File Size Accumulation Done - Print Result
;
MASS$FS2:
LHLD SRINGPOS ;restore ring position
SHLD RINGPOS
CALL FSNOTE ;print file size message
CALL VPRINT ;print specific
DB 'Tagged Files is ',0
LHLD TAG$TOT ;get total
BR FSIZE1 ;print size in HL and return
;
; COMMAND: F
;
; determine and display file size in kilobytes -- round up to next disk
; allocation block -- accumulate tagged file summation
;
FSIZE:
CALL SIZER ;compute file size of current file
PUSH H ;save value
CALL FSNOTE ;print file size message
LHLD RINGPOS ;print file name
INX H
CALL PRFN
CALL VPRINT ;print trailer
DB ' is ',0
POP H ;get size
;
; Print file size in HL and exit to screen
;
FSIZE1:
CALL PHLFDC ;print value in HL as floating
MVI A,'K' ;print suffix
CALL COUT
JMP LOOPFN ;resume
;
; Compute File Size at RINGPOS
; Return Size in HL
;
SIZER:
CALL RINGFCB ;move name to 's$fcb'
;
; Determine file record count and save in RCNT
;
MVI C,COMPSZ
LXI D,S$FCB
CALL BDOS
LHLD S$FCB+33
SHLD RCNT ;save record count and..
LXI H,0
SHLD S$FCB+33 ;..reset opsys
;
; Round up to next disk allocation block
;
LDA B$MASK ;sectors/block - 1
PUSH PSW ;save 'blm'
MOV L,A
XCHG
LHLD RCNT ;..use here.
DAD D ;round up to next block
MVI B,3+1 ;convert from..
CALL SHIFTLP ;..records to kilobytes.
POP PSW ;retrieve 'blm'
RRC ;convert..
RRC ;..to..
RRC ;..kilobytes/block.
ANI 1FH
CMA ;finish rounding
ANA L
MOV L,A ;hl-pair contains # of kilobytes
RET
;
; COMMAND: - (Previous Screen)
;
JUMPB:
LXI H,CURHOME ;set cursor home
SHLD CURAT
LHLD RING ;at front?
XCHG
LHLD LOCBEG
CALL CMPDEHL
BRZ JUMPBW ;back up and wrap around
SHLD LOCEND ;set new end
LXI D,-EPS*13 ;back up
DAD D
SHLD LOCBEG ;new beginning
SHLD RINGPOS ;new position
JMP RUNSH4
JUMPBW:
LHLD LOCBEG ;at first screen?
XCHG
LHLD RING ;pt to first element of ring
CALL CMPDEHL
BRZ JBW0 ;advance to end
LXI H,-EPS*13 ;back up
DAD D ;first element of new local ring
BR JFW0
JBW0:
LXI D,EPS*13 ;pt to next screen
DAD D
XCHG
LHLD RINGEND
CALL CMPDEHL
XCHG
BRZ JBW1
BRC JBW0
JBW1:
LXI D,-EPS*13
DAD D ;pt to first element of new local ring
BR JFW0
;
; COMMAND: + (Next Screen)
;
JUMPF:
LXI H,CURHOME ;set cursor to home
SHLD CURAT
LHLD LOCEND ;see if Local End <= Ring End
XCHG
LHLD RINGEND
CALL CMPDEHL
BRZ CMDLOOP
LHLD LOCEND ;new screen starting at LOCEND
BR JFW0
;
; Reset to Beginning of RING and Resume Command Looping
;
CMDLOOP:
CALL SETSCR ;reset all screen pointers
CMDLRET:
JMP RUNSH4
;
; Reset RING Position to HL
;
JFW0:
CALL SETSCR1 ;reset RINGPOS on ...
BR CMDLRET
;
; Reset Local Ring to HL
;
JFW0A:
CALL SETSCR2 ;reset LOCBEG on ...
BR CMDLRET
;
; COMMAND: ' ', Left-Arrow
;
FORWARD:
CALL CLRCUR ;clear cursor
CALL FOR0 ;position on screen and in ring
CALL SETCUR ;set cursor
JMP LOOPFN
; advance routine
FOR0:
LHLD RINGPOS ;at end of loop yet?
LXI D,13 ;i.e., will we be at end of loop?
DAD D
XCHG
LHLD LOCEND
CALL CMPDEHL ;compare 'present' to 'end'
BRNZ FORW ;to next print position
CALL CUR$FIRST ;position cursor
LHLD LOCBEG ;set position pointer to beginning and..
SHLD RINGPOS
RET
FORW:
LHLD RINGPOS ;advance in ring
LXI D,13
DAD D
SHLD RINGPOS ;new position
CALL CUR$NEXT ;position cursor
RET
;
; COMMAND: BS, Right-Arrow
;
REVERSE:
CALL CLRCUR ;clear cursor
CALL REV0 ;position on screen and in ring
CALL SETCUR ;set cursor
JMP LOOPFN
; Back Up Routine
REV0:
LHLD LOCBEG
XCHG
LHLD RINGPOS ;see if at beginning of ring
CALL CMPDEHL
BRNZ REV1 ;skip position pointer reset if not..
CALL CUR$LAST ;end of local ring
LHLD LOCEND ;set to end +1 to backup to end
LXI D,-13
DAD D
SHLD RINGPOS
RET
REV1:
CALL CUR$BACK ;back up 1
REV2:
LHLD RINGPOS
LXI D,-13 ;one ring position..
DAD D ;..backwards.
SHLD RINGPOS
RET
;
; COMMAND: Up-Arrow
;
UP:
CALL CLRCUR ;clear cursor
LHLD RINGPOS ;see if wrap around
LXI D,-13*4 ;4 entries
DAD D
XCHG
LHLD LOCBEG ;beginning of local screen
CALL CMPDEHL
BRC UP2 ;wrap around
MVI B,4 ;back up 4 entries
UP1:
PUSH B ;save count
CALL REV0 ;back up in ring and on screen (no print)
POP B ;get count
BJNZ UP1
BR DOWN1A
UP2:
LHLD RINGPOS ;advance to beyond end
LXI D,13*4
DAD D
XCHG
LHLD LOCEND ;compare to local end
XCHG
CALL CMPDEHL
BRZ DOWN1A ;at end, so too far
BRC DOWN1A ;beyond end, so back up
SHLD RINGPOS ;new ring position
LHLD CURAT ;advance cursor
INR H ;next line
SHLD CURAT
BR UP2
;
; COMMAND: Down-Arrow
;
DOWN:
CALL CLRCUR ;clear cursor
LHLD RINGPOS ;see if wrap around
LXI D,13*4 ;4 entries
DAD D
XCHG
LHLD LOCEND ;end of local screen
XCHG
CALL CMPDEHL
BRZ DOWN2 ;wrap around
BRC DOWN2 ;wrap around
MVI B,4 ;forward 4 entries
DOWN1:
PUSH B ;save count
CALL FOR0 ;advance in ring and on screen (no print)
POP B ;get count
BJNZ DOWN1
DOWN1A:
CALL SETCUR ;set cursor
JMP LOOPFN
DOWN2:
LHLD CURAT ;preserve column
MOV B,L ;column number in B
LXI H,CURHOME ;home position
SHLD CURAT ;set new position
LHLD LOCBEG ;beginning of local ring
SHLD RINGPOS ;new ring position
DOWN3:
LHLD CURAT ;check for at top of column
MOV A,L ;get col
CMP B ;there?
BRZ DOWN1A
LHLD RINGPOS ;advance in ring
LXI D,13 ;13 bytes/entry
DAD D
SHLD RINGPOS
LHLD CURAT ;get cursor position
LXI D,19 ;advance 19 bytes/screen entry
DAD D
SHLD CURAT
BR DOWN3
;
; COMMAND: S
;
; Determine remaining storage on requested disk
;
DSTAT:
CALL CPRMPT
DB 'Status of Disk (Letter): ',0
CALL KEYIN ;get char
PUSH PSW
CALL CRLF
POP PSW
SUI 'A' ;convert to number
JC LOOP
MOV B,A ;... in B
LDA MAXDR ;compare to max
SUI 'A'
CMP B
JC LOOPFN
MOV A,B ;get disk
STA R$DR ;requested drive
CALL RESET ;..login as current.
CALL FRESTOR ;determine free space remaining
CALL PRINT$FRE ;print value
LDA C$DR ;login original as..
CALL SET$DR ;..current drive.
JMP LOOPFN
;
; COMMAND: GD
;
MASS$DEL:
MOV A,B ;<RID> recover the opcode
STA MASSOP ;<RID> need it later
CALL CPRMPT
DB 'Mass Delete (Y/N/V=Verify)? ',0
CALL KEYIN ;get response
CPI 'Y'
BRZ MD1
CPI 'V'
JNZ LOOP ;return to position
MD1:
STA MDFLG ;set flag
;<RID> STA MASSOP
JMP MASS$RUN
;
; COMMAND: D
;
FDEL:
XRA A ;set no mass operation
STA MFLAG
CALL DELETE ;delete file
;
; Was Deletion Done? Abort if Not
;
LDA DELCODE ;0=not done
ORA A
JZ LOOPFN ;abort if not
;
; Reset Local Display
;
LHLD LOCEND ;move in end
LXI D,-13
DAD D
SHLD LOCEND
XCHG
LHLD RINGPOS ;position beyond end of ring?
CALL CMPDEHL
BRNZ FDEL1
;
; Cursor Beyond End of Display
;
CALL CUR$BACK ;back up cursor
LHLD LOCEND ;reset position
LXI D,-13
DAD D
SHLD RINGPOS
FDEL1:
LHLD LOCEND ;get local end
XCHG ;... in DE
LHLD LOCBEG ;erased all local files?
CALL CMPDEHL
JZ CMDLOOP ;reset
JMP JFW0A ;rescreen from LOCBEG
;
; Delete filename at RINGPOS
;
DELETE:
XRA A
STA DELCODE ;set deletion not done
CALL RINGFCB ;get file name
LDA MFLAG ;mass operation?
ORA A ;0=no
BRZ DEL1A ;do delete with message <JPS>
;
; Test for Verify on Mass Delete
;
LDA MDFLG ;verify?
CPI 'V'
BRNZ DEL1 ;delete without verify
;
; Verify and Delete only if Approved
;
CALL CPRMPT
DB 'Delete ',0
CALL PRFNS ;print file name in S$FCB
CALL VPRINT
DB ' (Y/N)? ',0
CALL KEYIN
CPI 'Y'
RNZ ;abort if not approved
;
; Delete File (Mass Operation)
;
DEL1:
LDA MDFLG ;mass operation - verify on?
CPI 'V'
BRZ DEL2
DEL1A: CALL ERMSG ;print information for mass del w/o verify
DB 'Deleting File ',0
CALL PRFNS
;
; Delete File in S$FCB
;
DEL2:
LXI H,S$FCB ;set file to R/W
CALL ATTRIB
RZ ;abort
LXI D,S$FCB ;point at delete 'fcb'
MVI C,ERASE ;erase function
CALL BDOS
INR A
BRNZ DELCL ;close up erased position
FNF$MSG:
CALL FNF1 ;show error message
JMP LOOPFN
;
; Close up erased position
;
DELCL:
MVI A,0FFH
STA DELCODE ;set deletion done
LHLD RINGPOS ;prepare move up pointers
PUSH H
LXI D,13 ;13 bytes/entry
DAD D ;de-pair = 'to' location
POP D ;hl-pair = 'from' location
;
; Move 13-byte ring entries from HL to DE
;
MOVUP:
XCHG ;HL=dest
PUSH H ;check if at end
LHLD RINGEND ;get old end pointer
CALL CMPDEHL ;check against current end location
POP H
XCHG ;DE=dest
BRZ MOVDONE ;must be at end of ring
MVI B,13 ;one name size
CALL MOVE ;move one name up
BR MOVUP ;go check end parameters
;
; Move Complete
;
MOVDONE:
LHLD RING ;see if ring is empty
XCHG
SHLD RINGEND ;set new ring end if all moved
CALL CMPDEHL ;..(listend --> listpos --> ring)
RNZ
CALL ERMSG
DB 'List Empty',0
JMP RUNSH3 ;go to drive/user area with files
;
; COMMAND: R
;
; Set-up to rename file at cursor position -- scan keyboard buffer and
; move filename to destination FCB (DFCB)
;
RENAME:
LHLD RINGPOS ;move name from ring to rename 'fcb'
LXI D,D$FCB ;place to move name
MVI B,12 ;amount to move
CALL MOVE
CALL CPRMPT ;new name prompt
DB 'Rename File to: ',0
LXI D,D$FCB+16 ;pt to FCB to fill
CALL FILENAME ;get file name
LXI H,D$FCB+1 ;check for any wild cards -- none permitted
MVI B,11 ;11 bytes
WILDCHK:
MOV A,M ;get char
INX H ;pt to next
CPI '?' ;wild?
BRZ WILDFND
BJNZ WILDCHK
; copy old file status bit ($r/o or $sys) to new filename
CPYBITS:
LXI D,D$FCB+1 ;first character of old name..
LXI H,D$FCB+17 ;..and of new name.
MVI B,11 ; # of bytes with tag bits
CBITS1:
LDAX D ;fetch bit of old name character
ANI 80H ;strip upper bit and..
MOV C,A ;..save in c-reg.
MVI A,7FH ;mask for character only
ANA M ;put masked character into a-reg
ORA C ;add old bit
MOV M,A ;copy new byte back
INX H ;bump copy pointers
INX D
BJNZ CBITS1 ;DJNZ
; check if new filename already exists. if so, say so. then go
; to command loop without moving ring position
LDA D$FCB ;copy new name to source 'fcb'
STA S$FCB
MVI B,11
LXI H,D$FCB+17 ;copy new name to..
LXI D,S$FCB+1 ;..source 'fcb' for existence check.
CALL MOVE
LXI H,S$FCB+12 ;clear 'fcb' system..
CALL INITFCB ;..fields.
LXI D,S$FCB ;search to see if this file exists
MVI C,SRCHF ;search first function
CALL BDOS
INR A ; 0ffh --> 00h if file not found
BRZ RENFILE ;to rename, if duplicate doesn't exists.
CALL ERMSG ;announce the situation
DB 'File Already Exists',0
JMP COMCAN ;try again?
; wild char found in file name -- error
WILDFND:
CALL ERMSG
DB 'AFN NOT Allowed',0
JMP COMCAN
; copy new name into ring position
RENFILE:
;following not needed with full screen refresh
;<JPS> LHLD RINGPOS ;get ring position pointer
;<JPS> INX H ;pt to name
;<JPS> PUSH H ;save ptr
;<JPS> XCHG
;<JPS> LXI H,D$FCB+17 ;point at new name and..
;<JPS> MVI B,11
;<JPS> CALL MOVE ;..move.
;<JPS> LHLD CURAT ;get current position on screen
;<JPS> LXI D,4 ;advance 4 chars
;<JPS> DAD D
;<JPS> CALL GOTOXY
;<JPS> POP H ;get ptr
;<JPS> CALL PRFN ;print file name
;<JPS> MOV A,M ;print tag
;<JPS> CALL COUT
LXI D,D$FCB ;rename 'fcb' location
MVI C,REN ;rename function
CALL BDOS
INR A ; 0ffh --> 00h if rename error
;<JPS> JNZ LOOP ;if okay, proceed, else..
;<JPS> JMP FNF$MSG ;..show no-file msg.
JZ FNF$MSG ;if error, report it <JPS>
JMP RUNSH2 ;start over <JPS>
; get file name from user and process into FCB pted to by DE
FILENAME:
PUSH D ;save ptr
LHLD CMDBUF ;command line location
XCHG
MVI C,RDBUF ;console read-buffer function
CALL BDOS
CALL CONVERT ;capitalize alpha
POP H ;set to null drive
MVI M,0 ;..required by 'bdos'.
INX H
; initialize new filename field with spaces
PUSH H ;save start pointer
MVI B,11 ; # of spaces to 'blank'
CALL FILL
POP H
XCHG
LHLD CMDBUF ;put length..
INX H
MOV C,M ;..in c-reg.
INX H
XCHG ;de-pair --> buffer pointer and hl-pair..
CALL UNSPACE ;..--> 'fcb' pointer. remove leading spaces.
; extend buffer to spaces beyond command length
EXTEND:
PUSH H
MOV L,C ;double-byte remaining length
MVI H,0
DAD D ;to buffer end +1
MVI M,' ' ;force illegal character end
POP H
; start filename scan
SCAN:
MVI B,8 ; 8 characters in filename
SCAN1:
CALL CKLEGAL ;get and see if legal character
JC COMCAN ;all of command line?
CPI ' ' ;see if end of parameter field
RZ ;rename file
CPI '.' ;at end of filename
BRZ SCAN2 ;process filetype field
CPI '*' ;rest wild?
BRZ SCAN1B
MOV M,A ;put character into destination 'fcb'
INX H
BJNZ SCAN1
; entry if eight characters without a 'period'
SCAN1A:
CALL CKLEGAL ;scan buffer up to period or end
RC ;no extent if not legal
CPI ' ' ;end of parameter field?
RZ
CPI '.'
BRNZ SCAN1A ;do till end or period
BR SCAN2A ;continue at correct place
; make rest of entry wild
SCAN1B:
MVI M,'?' ;fill with ?'s
INX H
BJNZ SCAN1B
LDAX D ;get next char
INX D ;pt to after dot
CPI '.' ;must be dot
JNZ COMCAN ;cancel if not
BR SCAN2A
; build filetype field
SCAN2:
INX H ;advance ptr to file type field
BJNZ SCAN2
SCAN2A:
MVI B,3 ;length of filetype field
SCAN3:
CALL CKLEGAL ;get and check character
BRC SCAN4 ;name done if illegal
CPI ' ' ;end of parameter field?
BRZ SCAN4
CPI '.' ;check if another period
BRZ SCAN4
CPI '*' ;rest wild?
BRZ SCAN4B
MOV M,A
INX H
BJNZ SCAN3 ;get next character
BR SCAN4A
SCAN4:
INX H ;advance to end of type field
BJNZ SCAN4
SCAN4A:
CALL INITFCB ;..and zero counter fields.
RET
SCAN4B:
MVI M,'?' ;make wild
INX H
BJNZ SCAN4B
BR SCAN4A ;complete rest
;
; COMMAND: J
;
GOTO:
CALL CPRMPT
DB 'Jump to Filename: ',0
LXI D,D$FCB ;pt to FCB
CALL FILENAME ;get file name
LHLD RING ;pt to first element of ring
SHLD RINGPOS ;set position
SHLD LOCBEG ;set local beginning
PUSH H
LHLD CRCTBL ;pt to CRC Table
MVI M,0 ;set local counter
POP H
GOTOL:
CALL GOTOCOMP ;compare
BRZ GOTOF ;we are there
PUSH H
LHLD CRCTBL ;pt to table
INR M
MOV A,M
POP H
CPI EPS
BRNZ GOTOL1
LHLD CRCTBL ;zero first entry
MVI M,0
LHLD LOCBEG ;reset local beginning
LXI D,EPS*13
DAD D
SHLD LOCBEG
GOTOL1:
LHLD RINGPOS ;advance to next entry
LXI D,13
DAD D
SHLD RINGPOS ;new position
XCHG ;position in DE
LHLD RINGEND ;check for completion
CALL CMPDEHL ;compare current position with end of ring
BRNZ GOTOL
LHLD RING ;pt to first element
SHLD RINGPOS ;set position
CALL FNF1 ;print message
JMP CMDLOOP
GOTOF:
LHLD LOCBEG ;we have local beginning
PUSH H
XCHG ;ring location in DE
LXI H,CURHOME ;set cursor ptr
SHLD CURAT
GOTOF0:
LHLD RINGPOS ;at position?
CALL CMPDEHL
BRZ GOTOF1
LXI H,13 ;advance location
DAD D
PUSH H
CALL CUR$NEXT ;advance cursor
POP D ;pt to next ring position
BR GOTOF0
GOTOF1:
POP H ;pt to local ring
JMP JFW0A ;process
GOTOCOMP:
LHLD RINGPOS ;pt to current entry
INX H ;pt to first char of file name
LXI D,D$FCB+1 ;pt to first char of new file
MVI B,11 ;11 bytes
GOTOC1:
LDAX D ;get char
CPI '?' ;match?
BRZ GOTOC2
CMP M ;match?
RNZ ;no match
GOTOC2:
INX D ;pt to next
INX H
BJNZ GOTOC1
RET
;
; COMMAND: V
;
; Type file to console with pagination set to 'lps' -- single-line scroll
; using <space> bar , <ctrl-x> to cancel, any other key to page screen.
;
VIEW:
CALL VIEWFL ;<RID>
JMP RUNSH4 ;<RID>
VIEWFL: ;<RID>
CALL VCLS
CALL VPRINT
DB CR,LF,DIM,'<CTRL-C> Cancels, <SP> Turns Up One Line, '
DB 'Other Keys Page Screen',BRIGHT,CR,LF,LF,0
MVI A,1 ;initialize..
STA LPSCNT ;..lines-per-screen counter.
STA VIEWFLG ; 'view' paginate if not zero
MVI A,WRCON ;write console out function
BR CURRENT ;to common i/o processing
;
; COMMAND: P
;
; Send file to logical list device -- any keypress cancels
;
SPRINT: ;<RID>
;
;<RID> Set Flags for First Time Thru and No Mass Print
;
XRA A ;<RID> A=0
STA FIRST$M ;<RID> set for prompt for destination
;
;<RID> Do Print
;
CALL LSTFILE ;<RID> print file at RINGPOS
;
;<RID> Advance to Next File
;
JMP RUNSH4 ;<RID> refresh screen and reset stack
;
;
LSTFILE:
LDA FIRST$M ;<RID> by-pass prompt.
ORA A ;<RID>
BRNZ SKPPRMT ;<RID>..1st time thru in mass-print mode.
DCR A ;<RID> A=0FFH
STA FIRST$M ;<RID> set not first time any more
CALL CPRMPT
DB 'Print on LST Device (Y/N)? ',0
CALL KEYIN ;get response
CPI 'Y'
JNZ LOOP
SKPPRMT: ;<RID>
CALL ERMSG
DB 'Printing ',0
LHLD RINGPOS ;pt to file name
INX H
CALL PRFN ;print it
MVI A,1 ;one for..
STA VIEWFLG ;..output to printer.
DCR A ;zero for..
STA LPSCNT ;..lines-per-page counter
STA EOFLAG ;<RID> used to provide formfeed at end of file
MVI A,LIST ;out to 'list' device function and fall thru
; output character for console/list/punch processing
CURRENT:
STA CON$LST ;save bdos function
; output file to console/printer/punch
CALL RINGFCB ;position name to 'fcb'
XCHG ;HL pts to S$FCB
CALL INITFCB ;set 'fcb' for use
LXI D,TBUF ;set to use default dma buffer
MVI C,SETDMA ;address set function
CALL BDOS
LXI D,S$FCB ;open file for reading
MVI C,OPEN ;file open function code
CALL BDOS
INR A ; 0ffh --> 00h if open not okay
BRNZ ZEROCR ;if not okay, show error message.
;
; File Not Found Error
;
FNF:
CALL FNF1 ;print file not found message
JMP LOOP
;
; Print File Not Found Message
;
FNF1:
CALL ERMSG
DB 'File NOT Found',0
RET
;
; Continue
;
ZEROCR:
XRA A
STA S$FCB+32 ;zero file 'current record' field
STA CHARCNT ;zero char count for tabbing
CALL PHEAD ;print heading if output to LST device
READMR:
LXI D,S$FCB ;point at file 'fcb' for reading
MVI C,READ ;record read function
CALL BDOS
ORA A ;check if read okay
BRNZ CURDONE ;eof?
LXI H,TBUF ;point at record just read
MVI B,128 ;set record character counter to output
READLP:
MOV A,M ;get a character
ANI 7FH ;force to 'ascii'
CPI EOFCHAR ;see if end-of-file
BRZ CURDONE ;back to ring loop if 'eof'
MOV E,A ;put character for 'bdos' call
PUSH B
PUSH H
PUSH D ; (character in e-reg)
LDA CON$LST ;get function for punch/list/console output
MOV C,A
MOV A,E ;check char
CPI TAB ;tabulate?
BRNZ NOTAB
MVI E,' ' ;space over
TABL:
PUSH B ;save key regs
PUSH D
CALL BDOS
POP D ;get key regs
POP B
CALL INCCCNT ;increment char count
ANI 7 ;check for done at every 8
BRNZ TABL
BR TABDN
NOTAB:
CALL BDOS ;send character
CALL INCCCNT ;increment char count
TABDN:
LDA VIEWFLG ;if 'view'..
ORA A
POP D ;get char in E in case PAGER is called
CNZ PAGER ;..check for 'lf'.
MVI E,GET ;get status or char
MVI C,DIRCON ;console status function
CALL BDOS ;status?
POP H
POP B
ANI 7FH ;if character there, then abort..
CNZ CANVIEW ;already got char
INX H ;if not, bump buffer pointer.
BJNZ READLP ;no, more in present record.
BR READMR ;yes, get next record.
CURDONE:
MVI A,TRUE ;<RID> set eoflag for formfeed at end of file
STA EOFLAG ;<RID>
LDA CON$LST ;console?
CPI WRCON
JZ BOTTOM ;<RID> prompt for user
JMP FORMFD ;<RID>
;<RID> JMP RUNSH4 ;refresh screen and continue user input
PAGER:
MOV A,E ; (character in e-reg)
CPI LF
RNZ
XRA A ;zero char count
STA CHARCNT
LDA CON$LST ;printer or console?
CPI LIST ;check for printer
BRZ PAGEP
LDA CTPP ;get number of lines of text per screen
MOV B,A ;... in B
LDA LPSCNT ;is counter..
INR A ;..at..
STA LPSCNT ;..limit..
CMP B ;..of lines-per-screen?
RC ;no, return.
XRA A ;yes, initialize..
STA LPSCNT ;..for next screen full.
CALL VPRINT
DB ' ',DIM,'[View More...]',BRIGHT,CR,0 ;show msg line
CALL DKEYIN ;wait for keyboard input
CPI ' ' ;see if <space> bar..
PUSH PSW
CALL VPRINT
DB ' ',CR,0 ;clear above msg line
POP PSW
BRNZ CANVIEW ;..if not, see if cancel.
LDA CTPP ;set for single line
DCR A
STA LPSCNT ;..scroll and..
RET ;..return for one more line.
PAGEP:
LDA LTPP ;get number of lines of text per page
MOV B,A ;... in B
LDA LPSCNT ;is counter..
INR A ;..at..
STA LPSCNT ;..limit..
CMP B ;..of lines-per-screen?
RC ;no, return.
FORMFD: XRA A ;<RID> zero for..
STA LPSCNT ;..lines-per-page counter
LDA LFFEED ;form feed available?
ORA A ;0=no
JZ PRFEED
CALL LCRLF ;new line
MVI A,FF ;send form feed char
CALL LOUT
LDA EOFLAG ;<RID> if true then output final formfeed
ORA A ;<RID>
RNZ ;<RID> don't do heading if final formfeed
JMP PHEAD ;print header and done
PRFEED:
LDA LSPP ;number of lines to skip
MOV B,A ;number of lines to skip
MVI C,LIST ;LST output
PAGELST:
CALL LCRLF ;new line on LST
BJNZ PAGELST
JMP PHEAD ;print heading and done
CANVIEW:
CPI CTRLC ;^C?
JZ COMCAN
RET ;return for another page
INCCCNT:
LDA CHARCNT ;increment char count
INR A
STA CHARCNT
RET
PHEAD:
LDA CON$LST ;printing to printer?
CPI LIST
RNZ
LXI H,HEADMSG ;print heading
PHEAD1:
MOV A,M ;get char
ORA A ;done?
BRZ PHEAD2
CALL LOUT ;send to printer
INX H ;pt to next
BR PHEAD1
PHEAD2:
LXI H,S$FCB+1 ;pt to file name
MVI B,8 ;8 chars
CALL PHEAD3
MVI A,'.' ;dot
CALL LOUT
MVI B,3 ;3 more chars
CALL PHEAD3
CALL LCRLF ;new line
CALL LCRLF ;blank line
RET
PHEAD3:
MOV A,M ;get char
CALL LOUT ;LST it
INX H ;pt to next
BJNZ PHEAD3
RET
;
; COMMAND: GC
;
; Copy files tagged using the 't' command. auto-erase if file exists
; on requested destination drive or in user area.
;
MASS$COPY:
MOV A,B ;<RID> recover opcode
STA MASSOP ;<RID>
CALL ERMSG
DB 'Mass Copy',0
;<RID> XRA A ;A=0
;<RID> STA MASSOP ;set operation to mass copy
;
; Main Entry Point for Mass Operation of Copy or Delete
; On entry, MASSOP = 0 if copy, 0FFH if delete
;
MASS$RUN:
LHLD RINGPOS ;save position
SHLD SRINGPOS
LHLD RING
LXI D,-13 ;back up to before first ring element
DAD D
SHLD RINGPOS ;set position
;
; Set Flags for First Time Thru and Mass Operation
;
XRA A ;A=0
STA FIRST$M ;set for prompt for dest with first file
DCR A ;A=0FFH
STA MFLAG ;this is a mass operation
;
; Main Mass Operation Loop
;
MASS$OLP:
LHLD RINGPOS ;re-entry point for next file
LXI D,13 ;advance to next
DAD D
SHLD RINGPOS
XCHG ;at ring..
;
; Check for Loop Completion -- DE = Current RINGPOS
;
MASS$OLP1:
LHLD RINGEND ;..end yet?
CALL CMPDEHL ;compare present position with end
; BRZ MASS$OLX ;done
JZ MASS$OLX ;<JPS>
;
; Check for Tagged File at RINGPOS
;
LHLD RINGPOS ;get position
LXI D,12 ;get 1st possible tag location
DAD D
MOV A,M ;get tag
CPI TAGCH
BRNZ MASS$OLP ;not tagged, so skip
;
; Select Mass Operation
;
LDA MASSOP ;get type of mass operation
;<RID> ORA A ;0=COPY
;<RID> BRZ MASS$OC ;do copy
CPI 'C' ;<RID> check if copy
BRZ MASS$OC ;<RID> yes its copy
CPI 'P' ;<RID> check if print
BRZ MASS$LST ;<RID> yes its print
CPI 'D' ;<RID> check if delete
BRZ MDELETE ;<RID> its delete
CPI 'V' ;<RID> check if view
BRZ MASS$FVIEW ;<RID> its view
CALL ERMSG ;<RID> should be one of above
DB 'Illegal character',0 ;<RID>
JMP LOOP ;<RID> get new comand
;<RID> COMMAND: GP
;
;<RID> Print tagged files using the 't' command
;
MASS$PRINT: ;<RID>
MOV A,B ;<RID> recover opcode
STA MASSOP ;<RID>
CALL ERMSG ;<RID>
DB 'Mass Print',0 ;<RID>
BR MASS$RUN ;<RID>
MASS$LST: ;<RID>
CALL LSTFILE ;<RID>
BR MASS$OLP ;<RID> skip to next
;<RID> COMMAND: GV
;
;<RID> View tagged files using the 't' command
;
MASS$VIEW: ;<RID>
MOV A,B ;<RID> recover opcode
STA MASSOP ;<RID>
CALL ERMSG ;<RID>
DB 'Mass View',0 ;<RID>
; BR MASS$RUN ;<RID>
JMP MASS$RUN ;<JPS>
MASS$FVIEW:
CALL VIEWFL ;<RID>
BR MASS$OLP ;<RID>
; Do Mass Delete - Current File Delete
;
MDELETE: ;<RID>
CALL DELETE ;delete filename at RINGPOS
;
; Advance to Next File if Delete Aborted
;
LDA DELCODE ;deletion done?
ORA A ;0=no
; BRZ MASS$OLP ;skip to next if not
JZ MASS$OLP ;<JPS>
;
; Stay at Current File if Delete Done - Ring was Compressed by Delete
;
LHLD RINGPOS ;get current ring position
XCHG ;... in DE (don't advance)
; BR MASS$OLP1 ;loop until thru ring list
JMP MASS$OLP1 ;<JPS>
;
; Do Mass Copy - Current File Copy
;
MASS$OC:
CALL COPY ;do copy
; BR MASS$OLP ;loop until thru ring list
JMP MASS$OLP ;<JPS>
;
; Exit Mass Operation Loop
;
MASS$OLX:
LHLD SRINGPOS ;reset ring position
SHLD RINGPOS
LDA MASSOP ;<RID> (if delete, restart)
;<RID> ORA A ;NZ=delete
;<RID> JNZ RUNSH2
CPI 'D' ;<RID> check if delete
JZ RUNSH2 ;<RID> else either print or copy
LHLD LOCBEG ;copy, so reset local ring
JMP JFW0A ;rescreen
;
; COMMAND: C
;
; Copy source file at current 'ring' position to another drive. set-up
; fcb's and buffer area and check for correct keyboard inputs. contains
; auto-crc file copy verification.
;
FCOPY:
;
; Set Flags for First Time Thru and No Mass Copy
;
XRA A ;A=0
STA FIRST$M ;set for prompt for destination
STA MFLAG ;not a mass copy
;
; Do Copy
;
CALL COPY ;do copy of file at RINGPOS
;
; Advance to Next File
;
JMP FORWARD ;advance to next file
;
; Copy File at RINGPOS
;
COPY:
LXI H,0 ;initialize storage for..
SHLD CRCVAL ;..'crc' working value.
CALL RINGFCB ;move from 'ring' to 'sfcb'
LXI H,S$FCB+12 ;set pointer to source extent field
CALL INITFCB
MVI B,32 ;copy source 'fcb' to destination 'fcb'
LXI H,S$FCB+1 ;from point..
LXI D,D$FCB+1 ;..to point..
CALL MOVE ;..move across.
LXI D,S$FCB ;open file for reading
MVI C,OPEN ;open function
CALL BDOS
INR A ; 0ffh --> 00h if bad open
JZ FNF ;file not found
;
; Source File is Open -- If first time thru, get dest dir
;
COPY2:
LDA FIRST$M ;by-pass prompt, drive/user compatibility..
ORA A ;..test, and disk reset after..
BRNZ COPY3M ;..1st time thru in mass-copy mode.
DCR A ;A=0FFH
STA FIRST$M ;set not first time any more
CALL CPRMPT ;prompt for drive selection
DB 'Copy to DIR: ',0
CALL DEF$D$U
;
; Check to ensure that either drives or user areas are different
;
LDA FCB ;get requested drive from 'fcb' and..
MOV B,A ;..put into b-reg for..
LDA S$FCB ;..comparison
CMP B
BRNZ COPY3 ;branch if different
LDA R$U$A ;requested user area --> rua
MOV B,A
LDA C$U$A ;current user area --> cua
CMP B
BRNZ COPY3
CALL ERMSG ;if not, show error condition:
DB 'Src DIR = Dest DIR',0
JMP LOOP ;try again?
;
; First File Copy - Reset System
;
COPY3:
CALL RESET ;make sure disk is read/write
CALL DLOGIN ;return home
;
; Nth File Copy - Copy without Resetting System
;
COPY3M:
LDA FCB ;put requested drive into..
STA D$FCB ;..place in destination fcb (used to log in)
LDA R$U$A ;toggle to..
CALL SET$USR ;..requested user area.
LXI D,D$FCB ;search for duplicate
MVI C,SRCHF ; 'search first' function
CALL BDOS
INR A ;if not found, 0ffh --> 00h. then..
BRZ COPY5 ;go to 'make' function for new file.
LDA MFLAG ;auto-erase..
ORA A ;..if..
BRZ COPY4M ;..in mass-copy mode.
CALL ERMSG ;If found, ask to replace:
DB 0
LXI H,D$FCB+1
CALL PRFN
CALL VPRINT
DB ' Exists on Dest -- Erase (Y/N)? ',0
CALL KEYIN ;get answer
CPI 'Y' ;if yes, then delete and copy ...
BRZ COPY4M ;... else fall thru to CUA$LOG and exit
;
; Log into Current User Area
;
CUA$LOG:
LDA C$U$A ;reset to current user area
JMP SET$USR ;set user and return to caller
;
; Erase destination file and proceed
;
COPY4M:
;
; Set File Attributes
;
LXI H,D$FCB ;pt to FCB
CALL ATTRIB ;clear bytes in FCB and set attr of file
BRZ CUA$LOG ;return to caller if R/W not permitted
;
; Delete old file at dest
;
LXI D,D$FCB ;delete file already existing
MVI C,ERASE ;erase function
CALL BDOS
;
; Create new file at dest
;
COPY5:
LXI D,D$FCB ;create new file and open for writing
MVI C,MAKE ;make function
CALL BDOS
INR A ;if directory full, 0ffh --> 00h.
BRNZ COPY6 ;if not, branch.
CALL ERMSG
DB 'Dest Dir Full',0
JMP LOOPFN ;if error, back to ring processor.
;
; Perform Copy
;
COPY6:
CALL CPRMPT
DB 'Copying File ',0
LXI H,D$FCB+1 ;print file name
CALL PRFNSX
CALL VPRINT
DB ' to ',0
LDA D$FCB ;print dest DU
ADI '@'
CALL COUT ;print disk
LDA R$U$A ;get user
CALL PAFDC ;print user
MVI A,':'
CALL COUT
XRA A ;clear 'eof'..
STA EOFLAG ;..flag.
COPY6A:
CALL CUA$LOG ;current user area
LXI H,0 ;clear current-record..
SHLD REC$CNT ;..counter.
LHLD BUFSTART ;set buffer start pointer..
SHLD BUF$PT ;..to begin pointer.
;
; read source file -- fill buffer memory or stop on 'eof' -- update 'crc'
; on-the-fly
;
COPY7:
LHLD BUF$PT ;set dma address to buffer pointer
XCHG ; de-pair --> dma address
MVI C,SETDMA
CALL BDOS
LXI D,S$FCB ;source 'fcb' for reading
MVI C,READ ;record read function
CALL BDOS
ORA A ; 00h --> read okay
BRZ S$RD$OK
DCR A ;eof?
BRZ COPY8 ;yes, end-of-file, set 'eof' flag.
CALL ERMSG
DB 'Read Error',0
JMP LOOPFN
;
; Read OK - Update CRC
;
S$RD$OK:
LHLD BUF$PT
MVI B,128
COPY7A:
MOV A,M ;get character and..
CALL UPDCRC ;..add to 'crc' value.
INX H
DCR B
BRNZ COPY7A ;loop 'till record read finished
;
; Update Buffer Ptr and Record Count
;
LHLD BUF$PT ;bump buffer pointer..
LXI D,128 ;..by..
DAD D ;..one..
SHLD BUF$PT ;..record.
LHLD REC$CNT ;bump buffer..
INX H ;..record count and..
SHLD REC$CNT ;..store.
XCHG ;ready to compare to..
;
; Check for Full Buffer
;
LHLD REC$MAX ;..maximum record count (full-buffer).
CALL CMPDEHL ;compare
BRNZ COPY7 ;if not full, get next record.
BR COPY9 ;full, start first write session.
;
; Indicate end-of-file read
;
COPY8:
MVI A,TRUE ;set 'eof' flag
STA EOFLAG
;
; Write source file from memory buffer to destination
;
COPY9:
LDA R$U$A ;set user to requested..
CALL SET$USR ;..area.
LHLD BUFSTART ;adjust buffer pointer..
SHLD BUF$PT ;..to start address.
COPY10:
LHLD REC$CNT ;buffer empty?
MOV A,H
ORA L
BRZ COPY11 ;buffer empty, check 'eof' flag.
DCX H ;dec buffer record count for each write
SHLD REC$CNT
LHLD BUF$PT ;set up dma address
PUSH H ;save for size bump
XCHG ;pointer in de-pair
MVI C,SETDMA
CALL BDOS
POP H
LXI D,128 ;bump pointer one record length
DAD D
SHLD BUF$PT
LXI D,D$FCB ;destination file 'fcb'
MVI C,WRITE ;write record function
CALL BDOS
ORA A ; 00h --> write okay
BRZ COPY10 ;okay, do next record. else..
CALL ERMSG ;..say disk write error.
DB 'Copy Disk Full',0
;
; Error in Write -- Delete Destination File and Abort
;
C$ERA:
LXI D,D$FCB ;delete..
MVI C,ERASE ;..partial..
CALL BDOS ;..from directory.
JMP LOOPFN ;back to ring
;
; Destination Buffer Written - Check for End
;
COPY11:
LDA EOFLAG ;buffer all written, check for 'eof'.
ORA A
JZ COPY6A ;branch to read next buffer full
LXI D,D$FCB ;point at 'fcb' for file closure
MVI C,CLOSE
CALL BDOS
INR A ;if no-close-error then..
BRNZ CRC$CMP ;..compare file crc's.
CALL ERMSG
DB 'Copy Close Error',0
JMP C$ERA
;
; Read Destination File and Compare CRCs
;
CRC$CMP:
LHLD CRCVAL ;transfer 'crc' value to..
SHLD CRCVAL2 ;..new storage area.
LXI H,0 ;clear working storage..
SHLD CRCVAL ;..to continue.
LXI D,TBUF
MVI C,SETDMA
CALL BDOS
LXI H,D$FCB+12
CALL INITFCB
LXI D,D$FCB
MVI C,OPEN
CALL BDOS
INR A ; 0ffh --> 00h if bad open
JZ BADCRC ;if bad open, just say 'bad-crc'.
XRA A ;zero 'fcb'..
STA D$FCB+32 ;..'cr' field.
CRCWF1:
LXI D,D$FCB
MVI C,READ
CALL BDOS
ORA A ;read okay?
BRZ D$RD$OK ;yes, read more.
DCR A ;eof?
BRZ FINCRC ;yes, finish up and make 'crc' comparison.
CALL ERMSG
DB 'Copy Read Error',0
JMP LOOP
;
; Block Read OK - Update CRC
;
D$RD$OK:
LXI H,TBUF
MVI B,128
CRCWF2:
MOV A,M ;get character to..
CALL UPDCRC ;..add to 'crc' value.
INX H
BJNZ CRCWF2
BR CRCWF1
;
; Read Complete - Check CRCs
;
FINCRC:
LHLD CRCVAL ;put written-file 'crc' into..
XCHG ;..de-pair.
LHLD CRCVAL2 ;put read-file 'crc' and..
CALL CMPDEHL ;..compare 'de/hl' for equality.
BRNZ BADCRC ;if not zero, show copy-error message.
CALL VPRINT ;if zero, show 'verified' message.
DB ' -- Verified',0
JMP CUA$LOG ;return to current user and return to caller
;
; Error on Copy
;
BADCRC:
CALL CUA$LOG ;return to current user
CALL ERMSG
DB ' -- CRC Error',0
JMP LOOP ;abort
;
; clear attributes of file (HL) and set attributes on disk
; return code of 0FFH (NZ) indicates OK to proceed, 0 (Z) indicates abort
;
ATTRIB:
PUSH H ;save regs
PUSH H
PUSH D
LHLD DUM$FCB ;init FCB
LXI D,12 ;12 bytes in
DAD D
POP D
CALL INITFCB
LHLD DUM$FCB ;pt to dummy FCB
XCHG ;... in DE
POP H
MVI B,12 ;copy
PUSH D
CALL MOVE
POP D ;pt to FCB
MVI C,SRCHF ;look for file
CALL BDOS
INR A ;file not found = 0
POP H
RZ ;abort if no file
PUSH H ;save ptr
DCR A ;adjust
RRC ;right 3 bits to indicate offset into BUFF
RRC
RRC
LXI H,TBUF ;pt to buffer
ADD L ;pt to FCB of file
ADI 9 ;pt to R/O Byte
MOV L,A
MOV A,M ;get byte
ANI 80H ;extract R/O Bit
BRZ ATTRIB0
CALL ERMSG
DB 0
POP H
PUSH H
INX H ;pt to file name
CALL PRFN ;print file name
CALL VPRINT
DB ' is R/O -- Erase (Y/N)? ',0
CALL KEYIN
CPI 'Y'
JZ ATTRIB0
POP H
XRA A ;error return
RET
ATTRIB0:
POP H ;get ptr
PUSH H ;save ptr
INX H ;pt to first char
MVI B,11 ;11 Bytes
ATTRIB1:
MOV A,M ;get byte
ANI 7FH ;mask it
MOV M,A ;put byte
INX H ;pt to next
DCR B ;count down
JNZ ATTRIB1
POP D ;pt to FCB
MVI C,ATTR
CALL BDOS
XRA A
DCR A ;no error return
RET
;
;**************************************************
;
; CRC subroutines
;
; initialize tables for fast crc calculations
INITCRC:
LHLD CRCTBL
MVI C,0 ;table index
GLOOP:
XCHG
LXI H,0 ;initialize crc register pair
MOV A,C
PUSH B ;save index in c-reg
MVI B,8
XRA H
MOV H,A
LLOOP:
DAD H
BRNC LSKIP
MVI A,10H ;generator is x^16 + x^12 + x^5 + x^0 as..
XRA H ;..recommended by ccitt for asynchronous..
MOV H,A ;..communications. produces the same..
MVI A,21H ;..results as public domain programs..
XRA L ;..chek, comm7, mdm7, and modem7.
MOV L,A
LSKIP:
BJNZ LLOOP
POP B
XCHG ;de-pair now has crc, hl pointing into table.
MOV M,D ;store high byte of crc..
INR H
MOV M,E ;..and store low byte.
DCR H
INX H ;move to next table entry
INR C ;next index
BRNZ GLOOP
RET
UPDCRC:
PUSH B ;update 'crc'..
PUSH H ;..accumulator..
LHLD CRCVAL ;pick up partial remainder
XCHG ;de-pair now has partial
MVI B,0
XRA D
MOV C,A
LHLD CRCTBL
DAD B
MOV A,M
XRA E
MOV D,A
INR H
MOV E,M
XCHG
SHLD CRCVAL
POP H
POP B
RET
;
;**************************************************
;
; WORKHORSE Routines
;
; conin routine (waits for response)
;
KEYIN:
CALL CIN ;get input
CALL CAPS ;capitalize
JMP COUT ;echo
; direct console input w/o echo (waits for input)
DKEYIN:
CALL CIN ;get char from BIOS
JMP CAPS ;capitalize
; convert keyboard input to upper case
CONVERT:
LHLD CMDBUF ; 'current keyboard buffer length'..
INX H
MOV B,M ;..to b-reg.
MOV A,B
ORA A ;if zero length, skip conversion.
JZ COMCAN
CONVLP:
INX H ;point at character to capitalize
MOV A,M
CALL CAPS
MOV M,A ;put back into buffer
BJNZ CONVLP
RET
;
; Fill buffer with 'spaces' with count in b-reg
;
FILL:
MVI M,' ' ;put in space character
INX H
BJNZ FILL ;no, branch.
RET
;
; Ignore leading spaces (ls) in buffer, length in c-reg.
;
UNSPACE:
LDAX D ;get character
CPI ' '
RNZ ;not blank, a file is entered.
INX D ;to next character
DCR C
JZ COMCAN ;all spaces --> command recovery error
BR UNSPACE
;
; Check for legal filename character -- return with carry set if illegal
;
CKLEGAL:
LDAX D ;get character from de-pair
INX D ;point at next character
CPI ' ' ;less than space?
RC ;return carry if unpermitted character
PUSH H
PUSH B
CPI '[' ;if greater than 'z', exit with..
BRNC CKERR ;..carry set.
MVI B,CHR$TEND-CHR$TBL
LXI H,CHR$TBL
CHR$LP:
CMP M
BRZ CKERR
INX H
BJNZ CHR$LP
ORA A ;clear carry for good character
POP B
POP H
RET
CKERR:
POP B
POP H
STC ;error exit with carry set
RET
CHR$TBL:
DB ',',':',';','<','=','>' ;invalid character table
CHR$TEND:
DS 0
;
; Print file name in S$FCB
;
PRFNSX:
PUSH H ;save regs
PUSH B
BR PRFNS0
PRFNS:
PUSH H ;affect only PSW
PUSH B
LXI H,S$FCB+1
PRFNS0:
CALL PRFN ;print file name
POP B ;restore
POP H
RET
;
; Print file name pted to by HL
;
PRFN:
MVI B,8 ;8 chars
CALL PRFNS1
MVI A,'.'
CALL COUT
MVI B,3 ;file type and fall thru
PRFNS1:
MOV A,M ;get char
CALL COUT
INX H ;pt to next
BJNZ PRFNS1
RET
;
; Copy filename from RINGPOS to SFCB
;
RINGFCB:
LHLD RINGPOS ;move name from ring to source 'fcb'
LXI D,S$FCB ;place to move filename and..
MVI B,12 ;..amount to move (fall thru to MOVE)
;
; move subroutine -- move b-reg # of bytes from hl-pair to de-pair
;
MOVE:
MOV A,M ;get hl-pair referenced source byte
ANI 7FH ;strip attributes
STAX D ;put to de-pair referenced destination
INX H ;fix pointers for next search
INX D
BJNZ MOVE
RET
MOVEB:
PUSH H ;SAVE HL, DE
PUSH D
CALL MOVE
POP D ;RESTORE DE, HL
POP H
RET
;
; Initialize FCB system fields (entry with hl-pair pointing to FCB)
;
INITFCB:
MVI B,21 ;fill ex, s1, s2, rc, cr counters with zeros.
INITLP:
MVI M,0 ;put zero (null) in memory
INX H
BJNZ INITLP
RET
;
; Disk system reset -- login requested drive
;
RESET:
MVI C,RESETDK ;reset system
CALL BDOS
LDA R$DR ;make requested drive..
SET$DR:
MOV E,A ;..current
MVI C,LOGIN
JMP BDOS ;return to caller
;
; Set/reset (or get) user area (call with binary user area in a-reg)
;
SET$USR:
MOV E,A ;user number in E
GET$USR:
MVI C,SGUSER
JMP BDOS ;return to caller
;
; Compare de-pair to hl-pair and set flags accordingly
;
CMPDEHL:
MOV A,D ;see if high bytes set flags
CMP H
RNZ ;return if not equal
MOV A,E
CMP L ;low bytes set flags instead
RET
;
; Shift hl-pair b-reg bits (-1) to right (divider routine)
;
SHIFTLP:
DCR B
RZ
MOV A,H
ORA A
RAR
MOV H,A
MOV A,L
RAR
MOV L,A
BR SHIFTLP
;
; Determine free storage remaining on selected drive
;
FRESTOR:
MVI C,INQDISK ;determine current drive
CALL BDOS ;returns 0 as a:, 1 as b:, etc.
INR A ;make 1 --> a:, 2 --> b:, etc.
STA FCB
MVI C,GETPARM ;current disk parameter block
CALL BDOS
INX H ;bump to..
INX H
MOV A,M ;..block shift factor.
STA BSHIFTF ; 'bsh'
INX H ;bump to..
MOV A,M ;..block mask.
STA B$MASK ; 'blm'
INX H ;bump to..
INX H ;..get..
MOV E,M ;..maximum block number..
INX H ;..double..
MOV D,M ;..byte.
XCHG
SHLD B$MAX ; 'dsm'
MVI C,INQALC ;address of allocation vector
CALL BDOS
XCHG ;get its length
LHLD B$MAX
INX H
LXI B,0 ;initialize block count to zero
GSPBYT:
PUSH D ;save allocation address
LDAX D
MVI E,8 ;set to process 8 bits (blocks)
GSPLUP:
RAL ;test bit
BRC NOT$FRE
INX B
NOT$FRE:
MOV D,A ;save bits
DCX H
MOV A,L
ORA H
BRZ END$ALC ;quit if out of blocks
MOV A,D ;restore bits
DCR E ;count down 8 bits
BRNZ GSPLUP ;branch to do another bit
POP D ;bump to next count..
INX D ;..of allocation vector.
BR GSPBYT ;process it
END$ALC:
POP D ;clear alloc vector pointer from stack
MOV L,C ;copy # blocks to hl-pair
MOV H,B
LDA BSHIFTF ;get block shift factor
SUI 3 ;convert from sectors to thousands (k)
BRZ PRT$FRE ;skip shifts if 1k blocks
FREK$LP:
DAD H ;multiply blocks by k-bytes per block
DCR A ;multiply by 2, 4, 8, or 16.
BRNZ FREK$LP
PRT$FRE:
SHLD DISKSP ;save disk space
RET
;
; Print free space on disk
;
PRINT$FRE:
CALL ERMSG ;position and set flags
DB 0
LHLD DISKSP
CALL PHLFDC ; # of free k-bytes in hl-pair
CALL VPRINT
DB 'K Bytes on Disk',0
RET
;
;**************************************************
;
; MESSAGE Routines
;
; Print VFILER Banner
;
BANNER:
CALL VCLS ;clear screen
LXI H,BANADR
CALL GOTOXY
CALL VPRINT ;print banner
DB 'VFILER, Version '
DB VERS/10+'0','.',(VERS MOD 10)+'0'
IF Z80
DB ' '
; DB DIM ;<JPS>
DB '[Z80 Code]'
; DB BRIGHT ;<JPS>
ELSE
DB ' '
; DB DIM ;<JPS>
DB '[8080 Code]'
; DB BRIGHT ;<JPS>
ENDIF
DB 0
RET
;
; Home the Cursor
;
CUR$FIRST:
LXI H,CURHOME ; HOME ADDRESS
SHLD CURAT ; SET CURSOR POSITION
JMP GOTOXY
;
; Last File Position
;
CUR$LAST:
LHLD RINGPOS ; ADVANCE
SHLD LOCPOS ; SET LOCAL POSITION
CL0:
LXI D,13
DAD D
XCHG
LHLD LOCEND ; END OF LOCAL RING?
CALL CMPDEHL
RZ
XCHG ; NEW POSITION
SHLD LOCPOS
PUSH H ; SAVE POSITION
CALL CUR$NEXT ; ADVANCE CURSOR
POP H ; GET POSITION
BR CL0
;
; Advance the Cursor
;
CUR$NEXT:
LHLD CURAT ; COMPUTE NEW POSITION
MOV A,L ; CHECK FOR NEW LINE
ADI 19 ; SIZE OF EACH ENTRY
CPI 70
BRNC CN1 ; ADVANCE TO NEXT LINE
MOV L,A ; NEW POSITION
SHLD CURAT
JMP GOTOXY
CN1:
MOV A,H ; GET LINE
LXI H,CURHOME ; GET COL
MOV H,A ; SET LINE AND FALL GO TO CUR$DOWN
SHLD CURAT
BR CUR$DOWN
;
; Back Up the Cursor
;
CUR$BACK:
LXI H,CURHOME ; GET HOME
XCHG ; ... IN DE
LHLD CURAT
CALL CMPDEHL ; COMPARE
BRZ CUR$LAST ; GOTO END IF LAST
MOV A,L ; CHECK FOR FIRST COL
CMP E
BRZ CB1
SUI 19 ; BACK UP ONE COL
MOV L,A
SHLD CURAT ; NEW POS
JMP GOTOXY
CB1:
MOV A,E ; GET HOME COL
ADI 19*3 ; GET LAST COL
MOV L,A
DCR H ; PREV LINE
SHLD CURAT
JMP GOTOXY
;
; Move Cursor Down One Line
;
CUR$DOWN:
LXI H,CURHOME ; GET HOME ADDRESS
MOV B,H ; LINE IN B
LHLD CURAT ; GET CURRENT ADDRESS
INR H ; MOVE DOWN
MOV A,H ; CHECK FOR TOO FAR
SUB B
CPI EPS/4
BRNC CD1
SHLD CURAT ; OK, SO SET POSITION
JMP GOTOXY
CD1:
MOV A,L ; GET COL
LXI H,CURHOME
MOV L,A
SHLD CURAT
JMP GOTOXY
;
; Refresh Screen
;
REFRESH:
LHLD CURAT ; SAVE CURSOR AND RING POSITIONS
SHLD SCURAT
LHLD RINGPOS
SHLD SRINGPOS
CALL BANNER ; PRINT BANNER
;
IF BIHELP ;built-in help?
LDA HELPDISP ;DISPLAY HELP?
ORA A ;0=NO
BRZ REF1
CALL HELPMSG ;PRINT HELP MESSAGE
BR REF2
REF1:
ENDIF ;BIHELP
;
CALL DISPFILES ; DISPLAY FILES
REF2:
LXI H,DUADR ; DU ADDRESS
CALL GOTOXY
LXI H,C$DR ; PT TO CURRENT DRIVE (FOLLOWED BY CUR USER)
CALL STNDOUT ;<RID> TURNON HIGHLIGHTING
CALL PRDU ; PRINT DU:DIR>
CALL STNDEND ;<RID> TURN OFF HIGHLIGHTING
LXI H,CPMADR ; COMMAND PROMPT MESSAGE
CALL GOTOXY
CALL VPRINT ; PROMPT WITH DRIVE PREFIX
DB DIM
DB 'Command (? = ',0
LDA HELPDISP ; IN HELP NOW?
ORA A ; 0=NO
BRZ REF3
CALL VPRINT
DB 'Files',0
BR REF4
REF3:
CALL VPRINT
DB 'Help',0
REF4:
CALL VPRINT
DB ')?',BRIGHT,0
LHLD SCURAT ; RESTORE CURSOR AND RING POSITIONS
SHLD CURAT
LHLD SRINGPOS
SHLD RINGPOS
CALL SETCUR ; RESTORE CURSOR ON SCREEN
RET
;
; Print DU pted to by HL
;
PRDU:
PUSH H ; SAVE REGS
PUSH B
MOV A,M ; GET DRIVE
MOV B,A
ADI 'A' ; CONVERT TO LETTER
CALL COUT
INX H ; PT TO USER
MOV A,M ; GET USER
MOV C,A
CALL PAFDC ; PRINT USER AS FLOATING
MVI A,':' ; PRINT COLON
CALL COUT
CALL DUTDIR ; SCAN NAMED DIRECTORY TABLE
BRZ PRDU2 ; NO NAME?
MVI B,8 ; PRINT NAME
PRDU1:
MOV A,M ; GET CHAR
CPI ' ' ; DONE IF SPACE ENCOUNTERED
BRZ PRDU3
CALL COUT
INX H
BJNZ PRDU1
BR PRDU3
PRDU2:
CALL VPRINT
DB 'Noname',0
PRDU3:
POP B ; RESTORE REGS
POP H
RET
;
; Refresh File Display
;
DISPFILES:
CALL CUR$FIRST ; POSITION CURSOR AT FIRST POSITION
LHLD LOCBEG ; PT TO FIRST FILE NAME
SHLD LOCPOS ; SAVE LOCAL POSITION
DSPF1:
LHLD LOCEND ; AT END?
XCHG
LHLD LOCPOS
CALL CMPDEHL
JZ CUR$FIRST ; POSITION AT FIRST ENTRY AND RETURN
MVI B,4 ; 4 SPACES
MVI A,' '
DSPF2:
CALL COUT
BJNZ DSPF2
PUSH H ; SAVE CURRENT LOCAL POSITION IN RING
;<RID> INX H ; PT TO FILE NAME
;<RID> CALL PRFN ; PRINT FILE NAME
;<RID> MOV A,M ; PRINT TAG
;<RID> CALL COUT
CALL HILITFN ;<RID> brigten filename
POP H ; GET CURRENT LOCAL POSITION
LXI D,13
DAD D
SHLD LOCPOS
CALL CUR$NEXT ; ADVANCE CURSOR
BR DSPF1
HILITFN: ;<RID>
PUSH H ;<RID> save for later
LXI D,12 ;<RID> locate the tag byte
DAD D ;<RID>
MOV A,M ;<RID> put tag byte in a for store
STA TAGFLG ;<RID>
POP H ;<RID> back to beginning of filename
INX H ;<RID> point to filename
LDA TAGFLG ;<RID>
CPI ' ' ;<RID> if space don't highlight
CNZ STNDOUT ;<RID> set highlight on
CALL PRFN ;<RID> put out filename
MOV A,M ;<RID> get tag byte
CALL COUT ;<RID> and output it
LDA TAGFLG ;<RID>
CPI ' ' ;<RID>
CNZ STNDEND ;<RID> turn off highlighting
RET ;<RID>
; Position Cursor at CURAT
;
SETCUR:
LDA HELPDISP ; NOGO IF IN HELP DISPLAY
ORA A
RNZ
LHLD CURAT
CALL GOTOXY
CALL VPRINT
DB DIM,'-->',BRIGHT,0
RET
;
; Clear Cursor
;
CLRCUR:
LDA HELPDISP ; NOGO IF IN HELP DISPLAY
ORA A
RNZ
LHLD CURAT
CALL GOTOXY
CALL VPRINT
DB ' ',0
RET
;
; Command Prompt
;
CPRMPT:
LXI H,CPADR ; GET ADDRESS
MPRINT:
PUSH H ; SAVE ADDRESS
CALL GOTOXY
PUSH B
;<RID> MVI B,76-(CPADR MOD 255)
LDA CWIDTH ;<RID> find screen length in chars
SUI (CPADR MOD 256)-1 ;<RID> determine number of char. to blank
MOV B,A ;<RID> put number in b
CALL VEREOL ; ERASE TO EOL
POP B
POP H ; GET ADDRESS
CALL GOTOXY ; POSITION CURSOR
JMP VPRINT ; PRINT MESSAGE AND RETURN
;
; Working Message
;
WORKMSG:
CALL ERMSG
DB DIM,'Working ...',BRIGHT,0
RET
;
; Error Message
;
ERMSG:
MVI A,0FFH ; SET ERROR MESSAGE FLAG
STA ERMFLG
LXI H,ERADR ; GET ADDRESS
BR MPRINT
;
; Print File Size Info
;
FSNOTE:
CALL ERMSG ; USE THIS ROUTINE
DB 'Size of ',0
RET
;
; Position for File Size Print
;
ATFS:
LXI H,FSADR+13 ; POSITION FOR PRINT OF FILE SIZE
JMP GOTOXY
;
; Clear Error Message
;
ERCLR:
XRA A ; CLEAR FLAG
STA ERMFLG
LXI H,ERADR ; POSITION
CALL GOTOXY
PUSH B
;<RID> MVI B,76-(ERADR MOD 255)
LDA CWIDTH ;<RID> find screen length in chars
SUI (ERADR MOD 256)-1 ;<RID> determine number of char. to blank
MOV B,A ;<RID> put number in b
CALL VEREOL ; ERASE TO EOL
POP B
RET
;
; Position at Command Prompt and Clear It
;
ATCMD:
LXI H,CPADR ; POSITION
CALL GOTOXY
PUSH B
;<RID> MVI B,76-(CPADR MOD 255)
LDA CWIDTH ;<RID> find screen length in chars
SUI (CPADR MOD 256)-1 ;<RID> determine number of char. to blank
MOV B,A ;<RID> put number in b
CALL VEREOL ; CLEAR MESSAGE
POP B
LXI H,CPADR ; REPOSITION
JMP GOTOXY
;
; Position at Bottom of Screen and Prompt for Continuation
;
BOTTOM:
LXI H,BOTADR ; POSITION
CALL GOTOXY
;
; Prompt for Continuation
;
SAK:
CALL VPRINT
DB DIM,'Strike Any Key -- ',BRIGHT,0
JMP KEYIN
;
; S T O R A G E
;
; Initialized
;
HEADMSG:
DB 'File: ',0
MOREHELP:
DB 'HELP ' ;HELP Command for further info
VFNAME ;VFILER Name
DB 0
MACFCB:
DB 0
VFNAME ;VFILER Name
VFNFILL ;Filler
DB 'CMD'
FILERCMD:
VFNAME ;VFILER Name
VFNFILL ;Filler
DB ' ' ;one space
FILE$D:
DB 'x'
FILE$U:
DB 'xx'
DB ':' ;colon
DB 0
JOKER:
DB '???????????' ;*.* equivalent
FIRST$M:
DB FALSE ;1st time thru in mass-copy mode
MFLAG:
DB TRUE ;multiple file copy flag-->0 for mass copy
TAG$TOT:
DW 0 ;summation of tagged file sizes
CMDBUF:
DS 2 ;command buffer maximum length, usage, and..
;
; Uninitialized
;
STACK:
DS 2
LWIDTH:
DS 1 ;WIDTH OF LINE
LTPP:
DS 1 ;LINES OF TEXT PER PAGE
LSPP:
DS 1 ;LINES TO SKIP PER PAGE
LFFEED:
DS 1 ;PRINTER CAN FORMFEED? (0=NO)
CWIDTH:
DS 1 ;WIDTH OF SCREEN
CTPP:
DS 1 ;LINES OF TEXT PER SCREEN
CSPP:
DS 1 ;LINES TO SKIP PER SCREEN
ALPHA:
DS 1 ;alphabetization flag (0=type and name, 0FFH=
;...name and type)
B$MAX:
DS 2 ;highest block number on drive
B$MASK:
DS 1 ;sec/blk-1
BSHIFTF:
DS 1 ;# of shifts to multiply by sec/blk
BUFENTRY:
DS 2 ;buffer start
BUF$PT:
DS 2 ;copy buffer current pointer..
BUFSTART:
DS 2 ;..and begin pointer.
CANFLG:
DS 1 ;no-file-found cancel flag
C$DR:
DS 1 ;'current drive'
C$U$A:
DS 1 ;'current user area' (must follow C$DR)
CHARCNT:
DS 1 ;character count for tab expansion
CON$LST:
DS 1 ;bdos function storage
CRCTBL:
DS 2 ;tables for 'crc' calculations
CRCVAL:
DS 2 ;2-byte 'crc' value of working file and..
CRCVAL2:
DS 2 ;..of finished source read-file.
CURAT:
DS 2 ;current cursor position
DELCODE:
DS 1 ;deletion code (0=delete not done)
D$FCB:
DS 33 ;fcb for destination file/new name if rename
DISKSP:
DS 2 ;space remaining on disk
DUM$FCB:
DS 2 ;dummy FCB for file attributes
DRLET:
DS 1 ;scratch for drive letter
EOFLAG:
DS 1 ;file copy loop 'eof' flag
ERMFLG:
DS 1 ;error message present flag
H$DR:
DS 1 ;home drive
H$U$A:
DS 1 ;home user area (must follow H$DR)
HELPDISP:
DS 1 ;display help screen (0=no)
LPSCNT:
DS 1 ;lines-per-screen for 'view'
LOCBEG:
DS 2 ;local beginning of ring
LOCEND:
DS 2 ;local end of ring
LOCPOS:
DS 2 ;local ring position (temp)
MASSOP:
DS 1 ;mass file operation code (0=no)
MAXDR:
DS 1 ;max driver letter
MDFLG:
DS 1 ;mass delete verify flag
O$USR:
DS 1 ;store initial user area for exit
R$DR:
DS 1 ;'requested drive'
RCNT:
DS 2 ;# of records in file and..
REC$CNT:
DS 2 ;..currently in ram buffer.
REC$MAX:
DS 2 ;maximum 128-byte record capacity of buffer
RING:
DS 2 ;ptr to beginning of ring
RINGI:
DS 2 ;ring sort pointer
RINGJ:
DS 2 ;another ring sort pointer
RINGEND:
DS 2 ;current ring end pointer
RINGPOS:
DS 2 ;current ring position in scan
R$U$A:
DS 1 ;'requested user area'
SCURAT:
DS 2 ;save cursor position
S$FCB:
DS 36 ;fcb for source (random record) file
SRINGPOS:
DS 2 ;save ring position
TAGFLG: ;<RID> temp for tag
DS 1 ;<RID>
T$DR:
DS 1 ;temp disk
TEST$RT:
DS 1 ;intermediate right-justify data
T$U$A:
DS 1 ;temp user
T$UN$FG:
DS 1 ;tag/untag file summation switch
USER:
DS 1 ;temp user buffer
VIEWFLG:
DS 1 ;<RID> (00h) 1-->to list/punch else to crt 'view'
END