forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2044 lines
50 KiB
2044 lines
50 KiB
TITLE 'ZCPR Version 1.0'
|
|
;
|
|
; CP/M Z80 Command Processor Replacement (CPR) Version 1.0
|
|
; CCPZ CREATED AND CUSTOMIZED FOR ARIES-II BY RLC
|
|
; FURTHER MODIFIED BY RGF AS V2.0
|
|
; FURTHER MODIFIED BY RLC AS V2.1
|
|
; FURTHER MODIFIED BY KBP AS V2.2
|
|
; FURTHER MODIFIED BY RLC AS V2.4 (V2.3 skipped)
|
|
; FURTHER MODIFIED BY RLC AS V2.5
|
|
; FURTHER MODIFIED BY RLC AS V2.6
|
|
; FURTHUR MODIFIED BY SBB AS V2.7
|
|
; FURTHER MODIFIED BY RLC AS V2.8
|
|
; FURTHER MODIFIED BY RLC AS V2.9
|
|
; FURTHER MODIFIED BY RLC AS V3.0
|
|
; FURTHER MODIFIED BY RLC AS V3.1
|
|
; FURTHER MODIFIED BY RLC AS V4.0
|
|
; ZCPR VERSION 1.0 CREATED FROM CCPZ VERSION 4.0 BY RLC IN
|
|
; A COORDINATED EFFORT WITH CCP-GROUP
|
|
;
|
|
; ZCPR is a group effort by CCP-GROUP, whose active membership involved
|
|
; in this project consists of the following:
|
|
; RLC - Richard Conn
|
|
; RGF - Ron Fowler
|
|
; KBP - Keith Peterson
|
|
; FJW - Frank Wancho
|
|
; The following individual also provided a contribution:
|
|
; SBB - Steve Bogolub
|
|
;
|
|
;
|
|
;******** Structure Notes ********
|
|
;
|
|
; This CPR is divided into a number of major sections. The following
|
|
; is an outline of these sections and the names of the major routines
|
|
; located therein.
|
|
;
|
|
; Section Function/Routines
|
|
; ------- -----------------
|
|
;
|
|
; -- Opening Comments, Equates, and Macro Definitions
|
|
;
|
|
; 0 JMP Table into CPR
|
|
;
|
|
; 1 Buffers
|
|
;
|
|
; 2 CPR Starting Modules
|
|
; CPR1 CPR RESTRT RSTCPR RCPRNL
|
|
; PRNNF
|
|
;
|
|
; 3 Utilities
|
|
; CRLF CONOUT CONIN LCOUT LSTOUT
|
|
; READF READ BDOSB PRINTC PRINT
|
|
; GETDRV DEFDMA DMASET RESET BDOSJP
|
|
; LOGIN OPENF OPEN GRBDOS CLOSE
|
|
; SEARF SEAR1 SEARN SUBKIL DELETE
|
|
; RESETUSR GETUSR SETUSR
|
|
;
|
|
; 4 CPR Utilities
|
|
; SETUD SETU0D UCASE REDBUF CNVBUF
|
|
; BREAK USRNUM ERROR SDELM ADVAN
|
|
; SBLANK ADDAH NUMBER NUMERR HEXNUM
|
|
; DIRPTR SLOGIN DLOGIN COMLOG SCANER
|
|
; CMDSER
|
|
;
|
|
; 5 CPR-Resident Commands and Functions
|
|
; 5A DIR DIRPR FILLQ
|
|
; 5B ERA
|
|
; 5C LIST
|
|
; 5D TYPE PAGER
|
|
; 5E SAVE
|
|
; 5F REN
|
|
; 5G USER
|
|
; 5H DFU
|
|
; 5I JUMP
|
|
; 5J GO
|
|
; 5K COM CALLPROG ERRLOG ERRJMP
|
|
; 5L GET MEMLOAD PRNLE
|
|
;
|
|
;
|
|
FALSE EQU 0
|
|
TRUE EQU NOT FALSE
|
|
;
|
|
; CUSTOMIZATION EQUATES
|
|
;
|
|
; The following equates may be used to customize this CPR for the user's
|
|
; system and integration technique. The following constants are provided:
|
|
;
|
|
; REL - TRUE if integration is to be done via MOVCPM
|
|
; - FALSE if integration is to be done via DDT and SYSGEN
|
|
;
|
|
; BASE - Base Address of user's CP/M system (normally 0 for DR version)
|
|
; This equate allows easy modification by non-standard CP/M (eg,H89)
|
|
;
|
|
; CPRLOC - Base Page Address of CPR; this value can be obtained by running
|
|
; the BDOSLOC program on your system, or by setting the
|
|
; MSIZE and BIOSEX equates to the system memory size in
|
|
; K-bytes and the "extra" memory required by your BIOS
|
|
; in K-bytes. BIOSEX is zero if your BIOS is normal size,
|
|
; and can be negative if your BIOS is in PROM or in
|
|
; non-contiguous memory.
|
|
;
|
|
; RAS - Remote-Access System; setting this equate to TRUE disables
|
|
; certain CPR commands that are considered harmful in a Remote-
|
|
; Access environment; use under Remote-Access Systems (RBBS) for
|
|
; security purposes
|
|
;
|
|
REL EQU FALSE ;SET TO TRUE FOR MOVCPM INTEGRATION
|
|
;
|
|
BASE EQU 0 ;BASE OF CP/M SYSTEM (SET FOR STANDARD CP/M)
|
|
;
|
|
IF REL
|
|
CPRLOC EQU 0 ;MOVCPM IMAGE
|
|
ELSE
|
|
;
|
|
; If REL is FALSE, the value of CPRLOC may be set in one
|
|
; of two ways. The first way is to set MSIZE and BIOSEX
|
|
; as described above using the following three lines:
|
|
;
|
|
;MSIZE EQU 56 ;SIZE OF MEM IN K-BYTES
|
|
;BIOSEX EQU 0 ;EXTRA # K-BYTES IN BIOS
|
|
;CPRLOC EQU 3400H+(MSIZE-20-BIOSEX)*1024 ;CPR ORIGIN
|
|
;
|
|
; The second way is to obtain the origin of your current
|
|
; CPR using BDSLOC or its equivalent, then merely set CPRLOC
|
|
; to that value as as in the following line:
|
|
;
|
|
;CPRLOC EQU 0BD00H ;FILL IN WITH BDOSLOC SUPPLIED VALUE
|
|
CPRLOC EQU 0D000H ;WW - CUSTOMIZED FOR ROMWBW
|
|
;
|
|
; Note that you should only use one method or the other.
|
|
; Do NOT define CPRLOC twice!
|
|
;
|
|
; The following gives the required offset to load the CPR into the
|
|
; CP/M SYSGEN Image through DDT (the Roffset command); Note that this
|
|
; value conforms with the standard value presented in the CP/M reference
|
|
; manuals, but it may not necessarily conform with the location of the
|
|
; CPR in YOUR CP/M system; several systems (Morrow Designs, P&T, Heath
|
|
; Org-0 to name a few) have the CPR located at a non-standard address in
|
|
; the SYSGEN Image
|
|
;
|
|
;CPRR EQU 0980H-CPRLOC ;DDT LOAD OFFSET
|
|
CPRR EQU 1100H-CPRLOC ;DDT LOAD OFFSET FOR MORROW DESIGNS
|
|
ENDIF
|
|
;
|
|
RAS EQU FALSE ;SET TO TRUE IF CPR IS FOR A REMOTE-ACCESS SYSTEM
|
|
;
|
|
; The following is presented as an option, but is not generally user-customiz-
|
|
; able. A basic design choice had to be made in the design of ZCPR concerning
|
|
; the execution of SUBMIT files. The original CCP had a problem in this sense
|
|
; in that it ALWAYS looked for the SUBMIT file from drive A: and the SUBMIT
|
|
; program itself (SUBMIT.COM) would place the $$$.SUB file on the currently
|
|
; logged-in drive, so when the user was logged into B: and he issued a SUBMIT
|
|
; command, the $$$.SUB was placed on B: and did not execute because the CCP
|
|
; looked for it on A: and never found it.
|
|
; After much debate it was decided to have ZCPR perform the same type of
|
|
; function as CCP (look for the $$$.SUB file on A:), but the problem with
|
|
; SUBMIT.COM still exists. Hence, RGF designed SuperSUB and RLC took his
|
|
; SuperSUB and designed SUB from it; both programs are set up to allow the
|
|
; selection at assembly time of creating the $$$.SUB on the logged-in drive
|
|
; or on drive A:.
|
|
; A final definition of the Indirect Command File ($$$.SUB or SUBMIT
|
|
; File) is presented as follows:
|
|
; "An Indirect Command File is one which contains
|
|
; a series of commands exactly as they would be
|
|
; entered from a CP/M Console. The SUBMIT Command
|
|
; (or SUB Command) reads this files and transforms
|
|
; it for processing by the ZCPR (the $$$.SUB File).
|
|
; ZCPR will then execute the commands indicated
|
|
; EXACTLY as if they were typed at the Console."
|
|
; Hence, to permit this to happen, the $$$.SUB file must always
|
|
; be present on a specific drive, and A: is the choice for said drive.
|
|
; With this facility engaged as such, Indirect Command Files like:
|
|
; DIR
|
|
; A:
|
|
; DIR
|
|
; can be executed, even though the currently logged-in drive is changed
|
|
; during execution. If the $$$.SUB file was present on the currently
|
|
; logged-in drive, the above series of commands would not work since the
|
|
; ZCPR would be looking for $$$.SUB on the logged-in drive, and switching
|
|
; logged-in drives without moving the $$$.SUB file as well would cause
|
|
; processing to abort.
|
|
;
|
|
SUBA equ TRUE ; Set to TRUE to have $$$.SUB always on A:
|
|
; Set to FALSE to have $$$.SUB on the logged-in drive
|
|
;
|
|
; The following flag enables extended processing for user-program supplied
|
|
; command lines. This is for Command Level 3 of ZCPR. Under the CCPZ Version
|
|
; 4.0 philosophy, three command levels exist:
|
|
; (1) that command issued by the user from his console at the '>' prompt
|
|
; (2) that command issued by a $$$.SUB file at the '$' prompt
|
|
; (3) that command issued by a user program by placing the command into
|
|
; CIBUFF and setting the character count in CBUFF
|
|
; Setting CLEVEL3 to TRUE enables extended processing of the third level of
|
|
; ZCPR command. All the user program need do is to store the command line and
|
|
; set the character count; ZCPR will initialize the pointers properly, store
|
|
; the ending zero properly, and capitalize the command line for processing.
|
|
; Once the command line is properly stored, the user executes the command line
|
|
; by reentering the ZCPR through CPRLOC [NOTE: The C register MUST contain
|
|
; a valid User/Disk Flag (see location 4) at this time.]
|
|
;
|
|
CLEVEL3 equ TRUE ;ENABLE COMMAND LEVEL 3 PROCESSING
|
|
;
|
|
;
|
|
;*** TERMINAL AND 'TYPE' CUSTOMIZATION EQUATES
|
|
;
|
|
NLINES EQU 24 ;NUMBER OF LINES ON CRT SCREEN
|
|
WIDE EQU TRUE ;TRUE IF WIDE DIR DISPLAY
|
|
FENCE EQU '|' ;SEP CHAR BETWEEN DIR FILES
|
|
;
|
|
PGDFLT EQU TRUE ;SET TO FALSE TO DISABLE PAGING BY DEFAULT
|
|
PGDFLG EQU 'P' ;FOR TYPE COMMAND: PAGE OR NOT (DEP ON PGDFLT)
|
|
; THIS FLAG REVERSES THE DEFAULT EFFECT
|
|
;
|
|
MAXUSR EQU 15 ;MAXIMUM USER NUMBER ACCESSABLE
|
|
;
|
|
SYSFLG EQU 'A' ;FOR DIR COMMAND: LIST $SYS AND $DIR
|
|
;
|
|
SOFLG EQU 'S' ;FOR DIR COMMAND: LIST $SYS FILES ONLY
|
|
;
|
|
SUPRES EQU TRUE ;SUPRESSES USER # REPORT FOR USER 0
|
|
;
|
|
DEFUSR EQU 0 ;DEFAULT USER NUMBER FOR COM FILES
|
|
;
|
|
SPRMPT EQU '$' ;CPR PROMPT INDICATING SUBMIT COMMAND
|
|
CPRMPT EQU '>' ;CPR PROMPT INDICATING USER COMMAND
|
|
;
|
|
NUMBASE EQU 'H' ;CHARACTER USED TO SWITCH FROM DEFAULT
|
|
; NUMBER BASE
|
|
;
|
|
SECTFLG EQU 'S' ;OPTION CHAR FOR SAVE COMMAND TO SAVE SECTORS
|
|
;
|
|
; END OF CUSTOMIZATION SECTION
|
|
;
|
|
CR EQU 0DH
|
|
LF EQU 0AH
|
|
TAB EQU 09H
|
|
;
|
|
WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS
|
|
UDFLAG EQU BASE+0004H ;USER NUM IN HIGH NYBBLE, DISK IN LOW
|
|
BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY PT
|
|
TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER
|
|
TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER
|
|
TPA EQU BASE+0100H ;BASE OF TPA
|
|
;
|
|
;
|
|
; MACROS TO PROVIDE Z80 EXTENSIONS
|
|
; MACROS INCLUDE:
|
|
;
|
|
$-MACRO ;FIRST TURN OFF THE EXPANSIONS
|
|
;
|
|
; JR - JUMP RELATIVE
|
|
; JRC - JUMP RELATIVE IF CARRY
|
|
; JRNC - JUMP RELATIVE IF NO CARRY
|
|
; JRZ - JUMP RELATIVE IF ZERO
|
|
; JRNZ - JUMP RELATIVE IF NO ZERO
|
|
; DJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO
|
|
; LDIR - MOV @HL TO @DE FOR COUNT IN BC
|
|
; LXXD - LOAD DOUBLE REG DIRECT
|
|
; SXXD - STORE DOUBLE REG DIRECT
|
|
;
|
|
;
|
|
;
|
|
; @GENDD MACRO USED FOR CHECKING AND GENERATING
|
|
; 8-BIT JUMP RELATIVE DISPLACEMENTS
|
|
;
|
|
@GENDD MACRO ?DD ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
|
|
IF (?DD GT 7FH) AND (?DD LT 0FF80H)
|
|
DB 100H ;Displacement Range Error on Jump Relative
|
|
ELSE
|
|
DB ?DD
|
|
ENDIF
|
|
ENDM
|
|
;
|
|
;
|
|
; Z80 MACRO EXTENSIONS
|
|
;
|
|
JR MACRO ?N ;;JUMP RELATIVE
|
|
DB 18H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
JRC MACRO ?N ;;JUMP RELATIVE ON CARRY
|
|
DB 38H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
JRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
|
|
DB 30H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
JRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
|
|
DB 28H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
JRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
|
|
DB 20H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
DJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
|
|
DB 10H
|
|
@GENDD ?N-$-1
|
|
ENDM
|
|
;
|
|
LDIR MACRO ;;LDIR
|
|
DB 0EDH,0B0H
|
|
ENDM
|
|
;
|
|
LDED MACRO ?N ;;LOAD DE DIRECT
|
|
DB 0EDH,05BH
|
|
DW ?N
|
|
ENDM
|
|
;
|
|
LBCD MACRO ?N ;;LOAD BC DIRECT
|
|
DB 0EDH,4BH
|
|
DW ?N
|
|
ENDM
|
|
;
|
|
SDED MACRO ?N ;;STORE DE DIRECT
|
|
DB 0EDH,53H
|
|
DW ?N
|
|
ENDM
|
|
;
|
|
SBCD MACRO ?N ;;STORE BC DIRECT
|
|
DB 0EDH,43H
|
|
DW ?N
|
|
ENDM
|
|
;
|
|
; END OF Z80 MACRO EXTENSIONS
|
|
;
|
|
;
|
|
;**** Section 0 ****
|
|
;
|
|
ORG CPRLOC
|
|
;
|
|
; ENTRY POINTS INTO ZCPR
|
|
; If the ZCPR is entered at location CPRLOC (at the JMP to CPR), then
|
|
; the default command in CIBUFF will be processed. If the ZCPR is entered
|
|
; at location CPRLOC+3 (at the JMP to CPR1), then the default command in
|
|
; CIBUFF will NOT be processed.
|
|
; NOTE: Entry into ZCPR in this way is permitted under ZCPR Version 4.0,
|
|
; but in order for this to work, CIBUFF and CBUFF MUST be initialized properly
|
|
; AND the C register MUST contain a valid User/Disk Flag (see Location 4: the
|
|
; most significant nybble contains the User Number and the least significant
|
|
; nybble contains the Disk Number).
|
|
; Some user programs (such as SYNONYM3) attempt to use the default
|
|
; command facility. Under the original CPR, it was necessary to initialize
|
|
; the pointer after the reserved space for the command buffer to point to
|
|
; the first byte of the command buffer. Under Version 4.x of ZCPR, this is
|
|
; no longer the case. The CIBPTR (Command Input Buffer PoinTeR) is located
|
|
; to be compatable with such programs (provided they determine the buffer
|
|
; length from the byte at MBUFF [CPRLOC + 6]), but under Version 4.x of ZCPR
|
|
; this is no longer necessary. ZCPR Version 4.x automatically initializes
|
|
; this buffer pointer in all cases.
|
|
;
|
|
ENTRY:
|
|
JMP CPR ; Process potential default command
|
|
JMP CPR1 ; Do NOT process potential default command
|
|
;
|
|
;**** Section 1 ****
|
|
; BUFFERS ET AL
|
|
;
|
|
; INPUT COMMAND LINE AND DEFAULT COMMAND
|
|
; The command line to be executed is stored here. This command line
|
|
; is generated in one of three ways:
|
|
; (1) by the user entering it through the BDOS READLN function at
|
|
; the du> prompt [user input from keyboard]
|
|
; (2) by the SUBMIT File Facility placing it there from a $$$.SUB
|
|
; file
|
|
; (3) by an external program or user placing the required command
|
|
; into this buffer
|
|
; In all cases, the command line is placed into the buffer starting at
|
|
; CIBUFF. This command line is terminated by the last character (NOT Carriage
|
|
; Return), and a character count of all characters in the command line
|
|
; up to and including the last character is placed into location CBUFF
|
|
; (immediately before the command line at CIBUFF). The placed command line
|
|
; is then parsed, interpreted, and the indicated command is executed.
|
|
; If CLEVEL3 is permitted, a terminating zero is placed after the command
|
|
; (otherwise the user program has to place this zero) and the CIBPTR is
|
|
; properly initialized (otherwise the user program has to init this ptr).
|
|
; If the command is placed by a user program, entering at CPRLOC is enough
|
|
; to have the command processed. Again, under CCPZ Version 4.0, it is not
|
|
; necessary to store the pointer to CIBUFF in CIBPTR; ZCPR will do this for
|
|
; the calling program if CLEVEL3 is made TRUE.
|
|
; WARNING: The command line must NOT exceed BUFLEN characters in length.
|
|
; For user programs which load this command, the value of BUFLEN can be
|
|
; obtained by examining the byte at MBUFF (CPRLOC + 6).
|
|
;
|
|
BUFLEN EQU 80 ;MAXIMUM BUFFER LENGTH
|
|
MBUFF:
|
|
DB BUFLEN ;MAXIMUM BUFFER LENGTH
|
|
CBUFF:
|
|
DB 0 ;NUMBER OF VALID CHARS IN COMMAND LINE
|
|
CIBUFF:
|
|
DB ' ' ;DEFAULT (COLD BOOT) COMMAND
|
|
CIBUF:
|
|
DB 0 ;COMMAND STRING TERMINATOR
|
|
DS BUFLEN-($-CIBUFF)+1 ;TOTAL IS 'BUFLEN' BYTES
|
|
;
|
|
CIBPTR:
|
|
DW CIBUFF ;POINTER TO COMMAND INPUT BUFFER
|
|
CIPTR:
|
|
DW CIBUF ;CURRENT POINTER
|
|
;
|
|
DS 26 ;STACK AREA
|
|
STACK EQU $ ;TOP OF STACK
|
|
;
|
|
; FILE TYPE FOR COMMAND
|
|
;
|
|
COMMSG:
|
|
DB 'COM'
|
|
;
|
|
; SUBMIT FILE CONTROL BLOCK
|
|
;
|
|
SUBFCB:
|
|
IF SUBA ;IF $$$.SUB ON A:
|
|
DB 1 ;DISK NAME SET TO DEFAULT TO DRIVE A:
|
|
ENDIF
|
|
;
|
|
IF NOT SUBA ;IF $$$.SUB ON CURRENT DRIVE
|
|
DB 0 ;DISK NAME SET TO DEFAULT TO CURRENT DRIVE
|
|
ENDIF
|
|
;
|
|
DB '$$$' ;FILE NAME
|
|
DB ' '
|
|
DB 'SUB' ;FILE TYPE
|
|
DB 0 ;EXTENT NUMBER
|
|
DB 0 ;S1
|
|
SUBFS2:
|
|
DS 1 ;S2
|
|
SUBFRC:
|
|
DS 1 ;RECORD COUNT
|
|
DS 16 ;DISK GROUP MAP
|
|
SUBFCR:
|
|
DS 1 ;CURRENT RECORD NUMBER
|
|
;
|
|
; COMMAND FILE CONTROL BLOCK
|
|
;
|
|
FCBDN:
|
|
DS 1 ;DISK NAME
|
|
FCBFN:
|
|
DS 8 ;FILE NAME
|
|
FCBFT:
|
|
DS 3 ;FILE TYPE
|
|
DS 1 ;EXTENT NUMBER
|
|
DS 2 ;S1 AND S2
|
|
DS 1 ;RECORD COUNT
|
|
FCBDM:
|
|
DS 16 ;DISK GROUP MAP
|
|
FCBCR:
|
|
DS 1 ;CURRENT RECORD NUMBER
|
|
;
|
|
; OTHER BUFFERS
|
|
;
|
|
PAGCNT:
|
|
DB NLINES-2 ;LINES LEFT ON PAGE
|
|
CHRCNT:
|
|
DB 0 ;CHAR COUNT FOR TYPE
|
|
QMCNT:
|
|
DB 0 ;QUESTION MARK COUNT FOR FCB TOKEN SCANNER
|
|
;
|
|
; CPR BUILT-IN COMMAND TABLE
|
|
;
|
|
NCHARS EQU 4 ;NUMBER OF CHARS/COMMAND
|
|
;
|
|
; CPR COMMAND NAME TABLE
|
|
; EACH TABLE ENTRY IS COMPOSED OF THE 4-BYTE COMMAND AND 2-BYTE ADDRESS
|
|
;
|
|
CMDTBL:
|
|
DB 'DIR '
|
|
DW DIR
|
|
DB 'LIST'
|
|
DW LIST
|
|
DB 'TYPE'
|
|
DW TYPE
|
|
DB 'USER'
|
|
DW USER
|
|
DB 'DFU '
|
|
DW DFU
|
|
;
|
|
IF NOT RAS ;FOR NON-RAS
|
|
DB 'GO '
|
|
DW GO
|
|
DB 'ERA '
|
|
DW ERA
|
|
DB 'SAVE'
|
|
DW SAVE
|
|
DB 'REN '
|
|
DW REN
|
|
DB 'GET '
|
|
DW GET
|
|
DB 'JUMP'
|
|
DW JUMP
|
|
ENDIF
|
|
;
|
|
NCMNDS EQU ($-CMDTBL)/(NCHARS+2)
|
|
;
|
|
;
|
|
;**** Section 2 ****
|
|
; CPR STARTING POINTS
|
|
;
|
|
; START CPR AND DON'T PROCESS DEFAULT COMMAND STORED
|
|
;
|
|
CPR1:
|
|
XRA A ;SET NO DEFAULT COMMAND
|
|
STA CBUFF
|
|
;
|
|
; START CPR AND POSSIBLY PROCESS DEFAULT COMMAND
|
|
;
|
|
; NOTE ON MODIFICATION BY RGF: BDOS RETURNS 0FFH IN
|
|
; ACCUMULATOR WHENEVER IT LOGS IN A DIRECTORY, IF ANY
|
|
; FILE NAME CONTAINS A '$' IN IT. THIS IS NOW USED AS
|
|
; A CLUE TO DETERMINE WHETHER OR NOT TO DO A SEARCH
|
|
; FOR SUBMIT FILE, IN ORDER TO ELIMINATE WASTEFUL SEARCHES.
|
|
;
|
|
CPR:
|
|
LXI SP,STACK ;RESET STACK
|
|
PUSH B
|
|
MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4)
|
|
RAR ;EXTRACT USER NUMBER
|
|
RAR
|
|
RAR
|
|
RAR
|
|
ANI 0FH
|
|
MOV E,A ;SET USER NUMBER
|
|
CALL SETUSR
|
|
CALL RESET ;RESET DISK SYSTEM
|
|
STA RNGSUB ;SAVE SUBMIT CLUE FROM DRIVE A:
|
|
POP B
|
|
MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4)
|
|
ANI 0FH ;EXTRACT DEFAULT DISK DRIVE
|
|
STA TDRIVE ;SET IT
|
|
JRZ NOLOG ;SKIP IF 0...ALREADY LOGGED
|
|
CALL LOGIN ;LOG IN DEFAULT DISK
|
|
;
|
|
IF NOT SUBA ;IF $$$.SUB IS ON CURRENT DRIVE
|
|
STA RNGSUB ;BDOS '$' CLUE
|
|
ENDIF
|
|
;
|
|
NOLOG:
|
|
LXI D,SUBFCB ;CHECK FOR $$$.SUB ON CURRENT DISK
|
|
RNGSUB EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE RNGSUB FLAG
|
|
ORA A ;SET FLAGS ON CLUE
|
|
CMA ;PREPARE FOR COMING 'CMA'
|
|
CNZ SEAR1
|
|
CMA ;0FFH IS RETURNED IF NO $$$.SUB, SO COMPLEMENT
|
|
STA RNGSUB ;SET FLAG (0=NO $$$.SUB)
|
|
LDA CBUFF ;EXECUTE DEFAULT COMMAND?
|
|
ORA A ;0=NO
|
|
JRNZ RS1
|
|
;
|
|
; PROMPT USER AND INPUT COMMAND LINE FROM HIM
|
|
;
|
|
RESTRT:
|
|
LXI SP,STACK ;RESET STACK
|
|
;
|
|
; PRINT PROMPT (DU>)
|
|
;
|
|
CALL CRLF ;PRINT PROMPT
|
|
CALL GETDRV ;CURRENT DRIVE IS PART OF PROMPT
|
|
ADI 'A' ;CONVERT TO ASCII A-P
|
|
CALL CONOUT
|
|
CALL GETUSR ;GET USER NUMBER
|
|
;
|
|
IF SUPRES ;IF SUPPRESSING USR # REPORT FOR USR 0
|
|
ORA A
|
|
JRZ RS000
|
|
ENDIF
|
|
;
|
|
CPI 10 ;USER < 10?
|
|
JRC RS00
|
|
SUI 10 ;SUBTRACT 10 FROM IT
|
|
PUSH PSW ;SAVE IT
|
|
MVI A,'1' ;OUTPUT 10'S DIGIT
|
|
CALL CONOUT
|
|
POP PSW
|
|
RS00:
|
|
ADI '0' ;OUTPUT 1'S DIGIT (CONVERT TO ASCII)
|
|
CALL CONOUT
|
|
;
|
|
; READ INPUT LINE FROM USER OR $$$.SUB
|
|
;
|
|
RS000:
|
|
CALL REDBUF ;INPUT COMMAND LINE FROM USER (OR $$$.SUB)
|
|
;
|
|
; PROCESS INPUT LINE
|
|
;
|
|
RS1:
|
|
;
|
|
IF CLEVEL3 ;IF THIRD COMMAND LEVEL IS PERMITTED
|
|
CALL CNVBUF ;CAPITALIZE COMMAND LINE, PLACE ENDING 0,
|
|
; AND SET CIBPTR VALUE
|
|
ENDIF
|
|
;
|
|
CALL DEFDMA ;SET TBUFF TO DMA ADDRESS
|
|
CALL GETDRV ;GET DEFAULT DRIVE NUMBER
|
|
STA TDRIVE ;SET IT
|
|
CALL SCANER ;PARSE COMMAND NAME FROM COMMAND LINE
|
|
CNZ ERROR ;ERROR IF COMMAND NAME CONTAINS A '?'
|
|
LXI D,RSTCPR ;PUT RETURN ADDRESS OF COMMAND
|
|
PUSH D ;ON THE STACK
|
|
LDA TEMPDR ;IS COMMAND OF FORM 'D:COMMAND'?
|
|
ORA A ;NZ=YES
|
|
JNZ COM ; IMMEDIATELY
|
|
CALL CMDSER ;SCAN FOR CPR-RESIDENT COMMAND
|
|
JNZ COM ;NOT CPR-RESIDENT
|
|
MOV A,M ;FOUND IT: GET LOW-ORDER PART
|
|
INX H ;GET HIGH-ORDER PART
|
|
MOV H,M ;STORE HIGH
|
|
MOV L,A ;STORE LOW
|
|
PCHL ;EXECUTE CPR ROUTINE
|
|
;
|
|
; ENTRY POINT FOR RESTARTING CPR AND LOGGING IN DEFAULT DRIVE
|
|
;
|
|
RSTCPR:
|
|
CALL DLOGIN ;LOG IN DEFAULT DRIVE
|
|
;
|
|
; ENTRY POINT FOR RESTARTING CPR WITHOUT LOGGING IN DEFAULT DRIVE
|
|
;
|
|
RCPRNL:
|
|
CALL SCANER ;EXTRACT NEXT TOKEN FROM COMMAND LINE
|
|
LDA FCBFN ;GET FIRST CHAR OF TOKEN
|
|
SUI ' ' ;ANY CHAR?
|
|
LXI H,TEMPDR
|
|
ORA M
|
|
JNZ ERROR
|
|
JR RESTRT
|
|
;
|
|
; No File Error Message
|
|
;
|
|
PRNNF:
|
|
CALL PRINTC ;NO FILE MESSAGE
|
|
DB 'No Fil','e'+80H
|
|
RET
|
|
;
|
|
;**** Section 3 ****
|
|
; I/O UTILITIES
|
|
;
|
|
; OUTPUT CHAR IN REG A TO CONSOLE AND DON'T CHANGE BC
|
|
;
|
|
;
|
|
; OUTPUT <CRLF>
|
|
;
|
|
CRLF:
|
|
MVI A,CR
|
|
CALL CONOUT
|
|
MVI A,LF ;FALL THRU TO CONOUT
|
|
;
|
|
CONOUT:
|
|
PUSH B
|
|
MVI C,02H
|
|
OUTPUT:
|
|
MOV E,A
|
|
PUSH H
|
|
CALL BDOS
|
|
POP H
|
|
POP B
|
|
RET
|
|
;
|
|
CONIN:
|
|
MVI C,01H ;GET CHAR FROM CON: WITH ECHO
|
|
CALL BDOSB
|
|
JMP UCASE ;CAPITALIZE
|
|
;
|
|
LCOUT:
|
|
PUSH PSW ;OUTPUT CHAR TO CON: OR LST: DEP ON PRFLG
|
|
PRFLG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE PRINT FLAG
|
|
ORA A ;0=TYPE
|
|
JRZ LC1
|
|
POP PSW ;GET CHAR
|
|
;
|
|
; OUTPUT CHAR IN REG A TO LIST DEVICE
|
|
;
|
|
LSTOUT:
|
|
PUSH B
|
|
MVI C,05H
|
|
JR OUTPUT
|
|
LC1:
|
|
POP PSW ;GET CHAR
|
|
PUSH PSW
|
|
CALL CONOUT ;OUTPUT TO CON:
|
|
POP PSW
|
|
CPI LF ;CHECK FOR PAGING
|
|
JZ PAGER
|
|
RET
|
|
;
|
|
READF:
|
|
LXI D,FCBDN ;FALL THRU TO READ
|
|
READ:
|
|
MVI C,14H ;FALL THRU TO BDOSB
|
|
;
|
|
; CALL BDOS AND SAVE BC
|
|
;
|
|
BDOSB:
|
|
PUSH B
|
|
CALL BDOS
|
|
POP B
|
|
ORA A
|
|
RET
|
|
;
|
|
; PRINT STRING (ENDING IN 0) PTED TO BY RET ADR;START WITH <CRLF>
|
|
;
|
|
PRINTC:
|
|
PUSH PSW ;SAVE FLAGS
|
|
CALL CRLF ;NEW LINE
|
|
POP PSW
|
|
;
|
|
PRINT:
|
|
XTHL ;GET PTR TO STRING
|
|
PUSH PSW ;SAVE FLAGS
|
|
CALL PRIN1 ;PRINT STRING
|
|
POP PSW ;GET FLAGS
|
|
XTHL ;RESTORE HL AND RET ADR
|
|
RET
|
|
;
|
|
; PRINT STRING (ENDING IN 0) PTED TO BY HL
|
|
;
|
|
PRIN1:
|
|
MOV A,M ;GET NEXT BYTE
|
|
ORA A ;WW - SET FLAGS
|
|
RZ ;WW - DONE IF ZERO
|
|
ANI 7FH ;WW - CLEAR HIGH BIT
|
|
CALL CONOUT ;PRINT CHAR
|
|
MOV A,M ;GET NEXT BYTE AGAIN FOR TEST
|
|
INX H ;PT TO NEXT BYTE
|
|
ORA A ;SET FLAGS
|
|
RM ;DONE IF MSB SET
|
|
JR PRIN1
|
|
;
|
|
; BDOS FUNCTION ROUTINES
|
|
;
|
|
;
|
|
; RETURN NUMBER OF CURRENT DISK IN A
|
|
;
|
|
GETDRV:
|
|
MVI C,19H
|
|
JR BDOSJP
|
|
;
|
|
; SET 80H AS DMA ADDRESS
|
|
;
|
|
DEFDMA:
|
|
LXI D,TBUFF ;80H=TBUFF
|
|
DMASET:
|
|
MVI C,1AH
|
|
JR BDOSJP
|
|
;
|
|
RESET:
|
|
MVI C,0DH
|
|
BDOSJP:
|
|
JMP BDOS
|
|
;
|
|
LOGIN:
|
|
MOV E,A
|
|
MVI C,0EH
|
|
JR BDOSJP ;SAVE SOME CODE SPACE
|
|
;
|
|
OPENF:
|
|
XRA A
|
|
STA FCBCR
|
|
LXI D,FCBDN ;FALL THRU TO OPEN
|
|
;
|
|
OPEN:
|
|
MVI C,0FH ;FALL THRU TO GRBDOS
|
|
;
|
|
GRBDOS:
|
|
CALL BDOS
|
|
INR A ;SET ZERO FLAG FOR ERROR RETURN
|
|
RET
|
|
;
|
|
CLOSE:
|
|
MVI C,10H
|
|
JR GRBDOS
|
|
;
|
|
SEARF:
|
|
LXI D,FCBDN ;SPECIFY FCB
|
|
SEAR1:
|
|
MVI C,11H
|
|
JR GRBDOS
|
|
;
|
|
SEARN:
|
|
MVI C,12H
|
|
JR GRBDOS
|
|
;
|
|
; CHECK FOR SUBMIT FILE IN EXECUTION AND ABORT IT IF SO
|
|
;
|
|
SUBKIL:
|
|
LXI H,RNGSUB ;CHECK FOR SUBMIT FILE IN EXECUTION
|
|
MOV A,M
|
|
ORA A ;0=NO
|
|
RZ
|
|
MVI M,0 ;ABORT SUBMIT FILE
|
|
LXI D,SUBFCB ;DELETE $$$.SUB
|
|
;
|
|
DELETE:
|
|
MVI C,13H
|
|
JR BDOSJP ;SAVE MORE SPACE
|
|
;
|
|
; RESET USER NUMBER IF CHANGED
|
|
;
|
|
RESETUSR:
|
|
TMPUSR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TMPUSR
|
|
MOV E,A ;PLACE IN E
|
|
JR SETUSR ;THEN GO SET USER
|
|
GETUSR:
|
|
MVI E,0FFH ;GET CURRENT USER NUMBER
|
|
SETUSR:
|
|
MVI C,20H ;SET USER NUMBER TO VALUE IN E (GET IF E=FFH)
|
|
JR BDOSJP ;MORE SPACE SAVING
|
|
;
|
|
; END OF BDOS FUNCTIONS
|
|
;
|
|
;
|
|
;**** Section 4 ****
|
|
; CPR UTILITIES
|
|
;
|
|
; SET USER/DISK FLAG TO CURRENT USER AND DEFAULT DISK
|
|
;
|
|
SETUD:
|
|
CALL GETUSR ;GET NUMBER OF CURRENT USER
|
|
ADD A ;PLACE IT IN HIGH NYBBLE
|
|
ADD A
|
|
ADD A
|
|
ADD A
|
|
LXI H,TDRIVE ;MASK IN DEFAULT DRIVE NUMBER (LOW NYBBLE)
|
|
ORA M ;MASK IN
|
|
STA UDFLAG ;SET USER/DISK NUMBER
|
|
RET
|
|
;
|
|
; SET USER/DISK FLAG TO USER 0 AND DEFAULT DISK
|
|
;
|
|
SETU0D:
|
|
TDRIVE EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TDRIVE
|
|
STA UDFLAG ;SET USER/DISK NUMBER
|
|
RET
|
|
;
|
|
; CONVERT CHAR IN A TO UPPER CASE
|
|
;
|
|
UCASE:
|
|
CPI 61H ;LOWER-CASE A
|
|
RC
|
|
CPI 7BH ;GREATER THAN LOWER-CASE Z?
|
|
RNC
|
|
ANI 5FH ;CAPITALIZE
|
|
RET
|
|
;
|
|
; INPUT NEXT COMMAND TO CPR
|
|
; This routine determines if a SUBMIT file is being processed
|
|
; and extracts the command line from it if so or from the user's console
|
|
;
|
|
REDBUF:
|
|
LDA RNGSUB ;SUBMIT FILE CURRENTLY IN EXECUTION?
|
|
ORA A ;0=NO
|
|
JRZ RB1 ;GET LINE FROM CONSOLE IF NOT
|
|
LXI D,SUBFCB ;OPEN $$$.SUB
|
|
PUSH D ;SAVE DE
|
|
CALL OPEN
|
|
POP D ;RESTORE DE
|
|
JRZ RB1 ;ERASE $$$.SUB IF END OF FILE AND GET CMND
|
|
LDA SUBFRC ;GET VALUE OF LAST RECORD IN FILE
|
|
DCR A ;PT TO NEXT TO LAST RECORD
|
|
STA SUBFCR ;SAVE NEW VALUE OF LAST RECORD IN $$$.SUB
|
|
CALL READ ;DE=SUBFCB
|
|
JRNZ RB1 ;ABORT $$$.SUB IF ERROR IN READING LAST REC
|
|
LXI D,CBUFF ;COPY LAST RECORD (NEXT SUBMIT CMND) TO CBUFF
|
|
LXI H,TBUFF ; FROM TBUFF
|
|
LXI B,BUFLEN ;NUMBER OF BYTES
|
|
LDIR
|
|
LXI H,SUBFS2 ;PT TO S2 OF $$$.SUB FCB
|
|
MVI M,0 ;SET S2 TO ZERO
|
|
INX H ;PT TO RECORD COUNT
|
|
DCR M ;DECREMENT RECORD COUNT OF $$$.SUB
|
|
LXI D,SUBFCB ;CLOSE $$$.SUB
|
|
CALL CLOSE
|
|
JRZ RB1 ;ABORT $$$.SUB IF ERROR
|
|
MVI A,SPRMPT ;PRINT SUBMIT PROMPT
|
|
CALL CONOUT
|
|
LXI H,CIBUFF ;PRINT COMMAND LINE FROM $$$.SUB
|
|
CALL PRIN1
|
|
CALL BREAK ;CHECK FOR ABORT (ANY CHAR)
|
|
;
|
|
IF CLEVEL3 ;IF THIRD COMMAND LEVEL IS PERMITTED
|
|
RZ ;IF <NULL> (NO ABORT), RETURN TO CALLER AND RUN
|
|
ENDIF
|
|
;
|
|
IF NOT CLEVEL3 ;IF THIRD COMMAND LEVEL IS NOT PERMITTED
|
|
JRZ CNVBUF ;IF <NULL> (NO ABORT), CAPITALIZE COMMAND
|
|
ENDIF
|
|
;
|
|
CALL SUBKIL ;KILL $$$.SUB IF ABORT
|
|
JMP RESTRT ;RESTART CPR
|
|
;
|
|
; INPUT COMMAND LINE FROM USER CONSOLE
|
|
;
|
|
RB1:
|
|
CALL SUBKIL ;ERASE $$$.SUB IF PRESENT
|
|
CALL SETUD ;SET USER AND DISK
|
|
MVI A,CPRMPT ;PRINT PROMPT
|
|
CALL CONOUT
|
|
MVI C,0AH ;READ COMMAND LINE FROM USER
|
|
LXI D,MBUFF
|
|
CALL BDOS
|
|
;
|
|
IF CLEVEL3 ;IF THIRD COMMAND LEVEL IS PERMITTED
|
|
JMP SETU0D ;SET CURRENT DISK NUMBER IN LOWER PARAMS
|
|
ENDIF
|
|
;
|
|
IF NOT CLEVEL3 ;IF THIRD COMMAND LEVEL IS NOT PERMITTED
|
|
CALL SETU0D ;SET CURRENT DISK NUMBER IF LOWER PARAMS
|
|
; AND FALL THRU TO CNVBUF
|
|
ENDIF
|
|
;
|
|
; CAPITALIZE STRING (ENDING IN 0) IN CBUFF AND SET PTR FOR PARSING
|
|
;
|
|
CNVBUF:
|
|
LXI H,CBUFF ;PT TO USER'S COMMAND
|
|
MOV B,M ;CHAR COUNT IN B
|
|
INR B ;ADD 1 IN CASE OF ZERO
|
|
CB1:
|
|
INX H ;PT TO 1ST VALID CHAR
|
|
MOV A,M ;CAPITALIZE COMMAND CHAR
|
|
CALL UCASE
|
|
MOV M,A
|
|
DJNZ CB1 ;CONTINUE TO END OF COMMAND LINE
|
|
CB2:
|
|
MVI M,0 ;STORE ENDING <NULL>
|
|
LXI H,CIBUFF ;SET COMMAND LINE PTR TO 1ST CHAR
|
|
SHLD CIBPTR
|
|
RET
|
|
;
|
|
; CHECK FOR ANY CHAR FROM USER CONSOLE;RET W/ZERO SET IF NONE
|
|
;
|
|
BREAK:
|
|
PUSH D ;SAVE DE
|
|
MVI C,11 ;CSTS CHECK
|
|
CALL BDOSB
|
|
CNZ CONIN ;GET INPUT CHAR
|
|
BRKBK:
|
|
POP D
|
|
RET
|
|
;
|
|
; GET THE REQUESTED USER NUMBER FROM THE COMMAND LINE AND VALIDATE IT.
|
|
;
|
|
USRNUM:
|
|
CALL NUMBER
|
|
CPI MAXUSR+1
|
|
RC
|
|
;
|
|
; INVALID COMMAND -- PRINT IT
|
|
;
|
|
ERROR:
|
|
CALL CRLF ;NEW LINE
|
|
LHLD CIPTR ;PT TO BEGINNING OF COMMAND LINE
|
|
ERR2:
|
|
MOV A,M ;GET CHAR
|
|
CPI ' '+1 ;SIMPLE '?' IF <SP> OR LESS
|
|
JRC ERR1
|
|
PUSH H ;SAVE PTR TO ERROR COMMAND CHAR
|
|
CALL CONOUT ;PRINT COMMAND CHAR
|
|
POP H ;GET PTR
|
|
INX H ;PT TO NEXT
|
|
JR ERR2 ;CONTINUE
|
|
ERR1:
|
|
CALL PRINT ;PRINT '?'
|
|
DB '?'+80H
|
|
CALL SUBKIL ;TERMINATE ACTIVE $$$.SUB IF ANY
|
|
JMP RESTRT ;RESTART CPR
|
|
;
|
|
; CHECK TO SEE IF DE PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET
|
|
;
|
|
SDELM:
|
|
LDAX D
|
|
ORA A ;0=DELIMITER
|
|
RZ
|
|
CPI ' ' ;ERROR IF < <SP>
|
|
JRC ERROR
|
|
RZ ;<SP>=DELIMITER
|
|
CPI '=' ;'='=DELIMITER
|
|
RZ
|
|
CPI 5FH ;UNDERSCORE=DELIMITER
|
|
RZ
|
|
CPI '.' ;'.'=DELIMITER
|
|
RZ
|
|
CPI ':' ;':'=DELIMITER
|
|
RZ
|
|
CPI ';' ;';'=DELIMITER
|
|
RZ
|
|
CPI '<' ;'<'=DELIMITER
|
|
RZ
|
|
CPI '>' ;'>'=DELIMITER
|
|
RET
|
|
;
|
|
; ADVANCE INPUT PTR TO FIRST NON-BLANK AND FALL THROUGH TO SBLANK
|
|
;
|
|
ADVAN:
|
|
LDED CIBPTR
|
|
;
|
|
; SKIP STRING PTED TO BY DE (STRING ENDS IN 0) UNTIL END OF STRING
|
|
; OR NON-BLANK ENCOUNTERED (BEGINNING OF TOKEN)
|
|
;
|
|
SBLANK:
|
|
LDAX D
|
|
ORA A
|
|
RZ
|
|
CPI ' '
|
|
RNZ
|
|
INX D
|
|
JR SBLANK
|
|
;
|
|
; ADD A TO HL (HL=HL+A)
|
|
;
|
|
ADDAH:
|
|
ADD L
|
|
MOV L,A
|
|
RNC
|
|
INR H
|
|
RET
|
|
;
|
|
; EXTRACT DECIMAL NUMBER FROM COMMAND LINE
|
|
; RETURN WITH VALUE IN REG A;ALL REGISTERS MAY BE AFFECTED
|
|
;
|
|
NUMBER:
|
|
CALL SCANER ;PARSE NUMBER AND PLACE IN FCBFN
|
|
LXI H,FCBFN+10 ;PT TO END OF TOKEN FOR CONVERSION
|
|
MVI B,11 ;11 CHARS MAX
|
|
;
|
|
; CHECK FOR SUFFIX FOR HEXADECIMAL NUMBER
|
|
;
|
|
NUMS:
|
|
MOV A,M ;GET CHARS FROM END, SEARCHING FOR SUFFIX
|
|
DCX H ;BACK UP
|
|
CPI ' ' ;SPACE?
|
|
JRNZ NUMS1 ;CHECK FOR SUFFIX
|
|
DJNZ NUMS ;COUNT DOWN
|
|
JR NUM0 ;BY DEFAULT, PROCESS
|
|
NUMS1:
|
|
CPI NUMBASE ;CHECK AGAINST BASE SWITCH FLAG
|
|
JRZ HNUM0
|
|
;
|
|
; PROCESS DECIMAL NUMBER
|
|
;
|
|
NUM0:
|
|
LXI H,FCBFN ;PT TO BEGINNING OF TOKEN
|
|
LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT
|
|
; (C=0, B=11)
|
|
NUM1:
|
|
MOV A,M ;GET CHAR
|
|
CPI ' ' ;DONE IF <SP>
|
|
JRZ NUM2
|
|
INX H ;PT TO NEXT CHAR
|
|
SUI '0' ;CONVERT TO BINARY (ASCII 0-9 TO BINARY)
|
|
CPI 10 ;ERROR IF >= 10
|
|
JRNC NUMERR
|
|
MOV D,A ;DIGIT IN D
|
|
MOV A,C ;NEW VALUE = OLD VALUE * 10
|
|
RLC
|
|
RLC
|
|
RLC
|
|
ADD C ;CHECK FOR RANGE ERROR
|
|
JRC NUMERR
|
|
ADD C ;CHECK FOR RANGE ERROR
|
|
JRC NUMERR
|
|
ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT
|
|
JRC NUMERR ;CHECK FOR RANGE ERROR
|
|
MOV C,A ;SET NEW VALUE
|
|
DJNZ NUM1 ;COUNT DOWN
|
|
;
|
|
; RETURN FROM NUMBER
|
|
;
|
|
NUM2:
|
|
MOV A,C ;GET ACCUMULATED VALUE
|
|
RET
|
|
;
|
|
; NUMBER ERROR ROUTINE FOR SPACE CONSERVATION
|
|
;
|
|
NUMERR:
|
|
JMP ERROR ;USE ERROR ROUTINE - THIS IS RELATIVE PT
|
|
;
|
|
; EXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE
|
|
; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED
|
|
;
|
|
HEXNUM:
|
|
CALL SCANER ;PARSE NUMBER AND PLACE IN FCBFN
|
|
HNUM0:
|
|
LXI H,FCBFN ;PT TO TOKEN FOR CONVERSION
|
|
LXI D,0 ;DE=ACCUMULATED VALUE
|
|
MVI B,11 ;B=CHAR COUNT
|
|
HNUM1:
|
|
MOV A,M ;GET CHAR
|
|
CPI ' ' ;DONE?
|
|
JRZ HNUM3 ;RETURN IF SO
|
|
CPI NUMBASE ;DONE IF NUMBASE SUFFIX
|
|
JRZ HNUM3
|
|
SUI '0' ;CONVERT TO BINARY
|
|
JRC NUMERR ;RETURN AND DONE IF ERROR
|
|
CPI 10 ;0-9?
|
|
JRC HNUM2
|
|
SUI 7 ;A-F?
|
|
CPI 10H ;ERROR?
|
|
JRNC NUMERR
|
|
HNUM2:
|
|
INX H ;PT TO NEXT CHAR
|
|
MOV C,A ;DIGIT IN C
|
|
MOV A,D ;GET ACCUMULATED VALUE
|
|
RLC ;EXCHANGE NYBBLES
|
|
RLC
|
|
RLC
|
|
RLC
|
|
ANI 0F0H ;MASK OUT LOW NYBBLE
|
|
MOV D,A
|
|
MOV A,E ;SWITCH LOW-ORDER NYBBLES
|
|
RLC
|
|
RLC
|
|
RLC
|
|
RLC
|
|
MOV E,A ;HIGH NYBBLE OF E=NEW HIGH OF E,
|
|
; LOW NYBBLE OF E=NEW LOW OF D
|
|
ANI 0FH ;GET NEW LOW OF D
|
|
ORA D ;MASK IN HIGH OF D
|
|
MOV D,A ;NEW HIGH BYTE IN D
|
|
MOV A,E
|
|
ANI 0F0H ;MASK OUT LOW OF E
|
|
ORA C ;MASK IN NEW LOW
|
|
MOV E,A ;NEW LOW BYTE IN E
|
|
DJNZ HNUM1 ;COUNT DOWN
|
|
;
|
|
; RETURN FROM HEXNUM
|
|
;
|
|
HNUM3:
|
|
XCHG ;RETURNED VALUE IN HL
|
|
MOV A,L ;LOW-ORDER BYTE IN A
|
|
RET
|
|
;
|
|
; PT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C
|
|
;
|
|
DIRPTR:
|
|
LXI H,TBUFF ;PT TO TEMP BUFFER
|
|
ADD C ;PT TO 1ST BYTE OF DIR ENTRY
|
|
CALL ADDAH ;PT TO DESIRED BYTE IN DIR ENTRY
|
|
MOV A,M ;GET DESIRED BYTE
|
|
RET
|
|
;
|
|
; CHECK FOR SPECIFIED DRIVE AND LOG IT IN IF NOT DEFAULT
|
|
;
|
|
SLOGIN:
|
|
XRA A ;SET FCBDN FOR DEFAULT DRIVE
|
|
STA FCBDN
|
|
CALL COMLOG ;CHECK DRIVE
|
|
RZ
|
|
JR DLOG5 ;DO LOGIN OTHERWISE
|
|
;
|
|
; CHECK FOR SPECIFIED DRIVE AND LOG IN DEFAULT DRIVE IF SPECIFIED<>DEFAULT
|
|
;
|
|
DLOGIN:
|
|
CALL COMLOG ;CHECK DRIVE
|
|
RZ ;ABORT IF SAME
|
|
LDA TDRIVE ;LOG IN DEFAULT DRIVE
|
|
;
|
|
DLOG5: JMP LOGIN
|
|
;
|
|
; ROUTINE COMMON TO BOTH LOGIN ROUTINES; ON EXIT, Z SET MEANS ABORT
|
|
;
|
|
COMLOG:
|
|
TEMPDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TEMPDR
|
|
ORA A ;0=NO
|
|
RZ
|
|
DCR A ;COMPARE IT AGAINST DEFAULT
|
|
LXI H,TDRIVE
|
|
CMP M
|
|
RET ;ABORT IF SAME
|
|
;
|
|
; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCBDN;
|
|
; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP);
|
|
; ON INPUT, CIBPTR PTS TO CHAR AT WHICH TO START SCAN;
|
|
; ON OUTPUT, CIBPTR PTS TO CHAR AT WHICH TO CONTINUE AND ZERO FLAG IS RESET
|
|
; IF '?' IS IN TOKEN
|
|
;
|
|
; ENTRY POINTS:
|
|
; SCANER - LOAD TOKEN INTO FIRST FCB
|
|
; SCANX - LOAD TOKEN INTO FCB PTED TO BY HL
|
|
;
|
|
SCANER:
|
|
LXI H,FCBDN ;POINT TO FCBDN
|
|
SCANX:
|
|
XRA A ;SET TEMPORARY DRIVE NUMBER TO DEFAULT
|
|
STA TEMPDR
|
|
CALL ADVAN ;SKIP TO NON-BLANK OR END OF LINE
|
|
SDED CIPTR ;SET PTR TO NON-BLANK OR END OF LINE
|
|
LDAX D ;END OF LINE?
|
|
ORA A ;0=YES
|
|
JRZ SCAN2
|
|
SBI 'A'-1 ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER
|
|
MOV B,A ;STORE NUMBER (A:=0, B:=1, ETC) IN B
|
|
INX D ;PT TO NEXT CHAR
|
|
LDAX D ;SEE IF IT IS A COLON (:)
|
|
CPI ':'
|
|
JRZ SCAN3 ;YES, WE HAVE A DRIVE SPEC
|
|
DCX D ;NO, BACK UP PTR TO FIRST NON-BLANK CHAR
|
|
SCAN2:
|
|
LDA TDRIVE ;SET 1ST BYTE OF FCBDN AS DEFAULT DRIVE
|
|
MOV M,A
|
|
JR SCAN4
|
|
SCAN3:
|
|
MOV A,B ;WE HAVE A DRIVE SPEC
|
|
STA TEMPDR ;SET TEMPORARY DRIVE
|
|
MOV M,B ;SET 1ST BYTE OF FCBDN AS SPECIFIED DRIVE
|
|
INX D ;PT TO BYTE AFTER ':'
|
|
;
|
|
; EXTRACT FILENAME FROM POSSIBLE FILENAME.TYP
|
|
;
|
|
SCAN4:
|
|
XRA A ;A=0
|
|
STA QMCNT ;INIT COUNT OF NUMBER OF QUESTION MARKS IN FCB
|
|
MVI B,8 ;MAX OF 8 CHARS IN FILE NAME
|
|
CALL SCANF ;FILL FCB FILE NAME
|
|
;
|
|
; EXTRACT FILE TYPE FROM POSSIBLE FILENAME.TYP
|
|
;
|
|
MVI B,3 ;PREPARE TO EXTRACT TYPE
|
|
CPI '.' ;IF (DE) DELIMITER IS A '.', WE HAVE A TYPE
|
|
JRNZ SCAN15 ;FILL FILE TYPE BYTES WITH <SP>
|
|
INX D ;PT TO CHAR IN COMMAND LINE AFTER '.'
|
|
CALL SCANF ;FILL FCB FILE TYPE
|
|
JR SCAN16 ;SKIP TO NEXT PROCESSING
|
|
SCAN15:
|
|
CALL SCANF4 ;SPACE FILL
|
|
;
|
|
; FILL IN EX, S1, S2, AND RC WITH ZEROES
|
|
;
|
|
SCAN16:
|
|
MVI B,4 ;4 BYTES
|
|
SCAN17:
|
|
INX H ;PT TO NEXT BYTE IN FCBDN
|
|
MVI M,0
|
|
DJNZ SCAN17
|
|
;
|
|
; SCAN COMPLETE -- DE PTS TO DELIMITER BYTE AFTER TOKEN
|
|
;
|
|
SDED CIBPTR
|
|
;
|
|
; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN FILENAME.TYP
|
|
;
|
|
LDA QMCNT ;GET NUMBER OF QUESTION MARKS
|
|
ORA A ;SET ZERO FLAG TO INDICATE ANY '?'
|
|
RET
|
|
;
|
|
; SCANF -- SCAN TOKEN PTED TO BY DE FOR A MAX OF B BYTES; PLACE IT INTO
|
|
; FILE NAME FIELD PTED TO BY HL; EXPAND AND INTERPRET WILD CARDS OF
|
|
; '*' AND '?'; ON EXIT, DE PTS TO TERMINATING DELIMITER
|
|
;
|
|
SCANF:
|
|
CALL SDELM ;DONE IF DELIMITER ENCOUNTERED - <SP> FILL
|
|
JRZ SCANF4
|
|
INX H ;PT TO NEXT BYTE IN FCBDN
|
|
CPI '*' ;IS (DE) A WILD CARD?
|
|
JRNZ SCANF1 ;CONTINUE IF NOT
|
|
MVI M,'?' ;PLACE '?' IN FCBDN AND DON'T ADVANCE DE IF SO
|
|
CALL SCQ ;SCANNER COUNT QUESTION MARKS
|
|
JR SCANF2
|
|
SCANF1:
|
|
MOV M,A ;STORE FILENAME CHAR IN FCBDN
|
|
INX D ;PT TO NEXT CHAR IN COMMAND LINE
|
|
CPI '?' ;CHECK FOR QUESTION MARK (WILD)
|
|
CZ SCQ ;SCANNER COUNT QUESTION MARKS
|
|
SCANF2:
|
|
DJNZ SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED
|
|
SCANF3:
|
|
CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER
|
|
RZ ;ZERO FLAG SET IF DELIMITER FOUND
|
|
INX D ;PT TO NEXT CHAR IN COMMAND LINE
|
|
JR SCANF3
|
|
;
|
|
; FILL MEMORY POINTED TO BY HL WITH SPACES FOR B BYTES
|
|
;
|
|
SCANF4:
|
|
INX H ;PT TO NEXT BYTE IN FCBDN
|
|
MVI M,' ' ;FILL FILENAME PART WITH <SP>
|
|
DJNZ SCANF4
|
|
RET
|
|
;
|
|
; INCREMENT QUESTION MARK COUNT FOR SCANNER
|
|
; THIS ROUTINE INCREMENTS THE COUNT OF THE NUMBER OF QUESTION MARKS IN
|
|
; THE CURRENT FCB ENTRY
|
|
;
|
|
SCQ:
|
|
LDA QMCNT ;GET COUNT
|
|
INR A ;INCREMENT
|
|
STA QMCNT ;PUT COUNT
|
|
RET
|
|
;
|
|
; CMDTBL (COMMAND TABLE) SCANNER
|
|
; ON RETURN, HL PTS TO ADDRESS OF COMMAND IF CPR-RESIDENT
|
|
; ON RETURN, ZERO FLAG SET MEANS CPR-RESIDENT COMMAND
|
|
;
|
|
CMDSER:
|
|
LXI H,CMDTBL ;PT TO COMMAND TABLE
|
|
MVI C,NCMNDS ;SET COMMAND COUNTER
|
|
CMS1:
|
|
LXI D,FCBFN ;PT TO STORED COMMAND NAME
|
|
MVI B,NCHARS ;NUMBER OF CHARS/COMMAND (8 MAX)
|
|
CMS2:
|
|
LDAX D ;COMPARE AGAINST TABLE ENTRY
|
|
CMP M
|
|
JRNZ CMS3 ;NO MATCH
|
|
INX D ;PT TO NEXT CHAR
|
|
INX H
|
|
DJNZ CMS2 ;COUNT DOWN
|
|
LDAX D ;NEXT CHAR IN INPUT COMMAND MUST BE <SP>
|
|
CPI ' '
|
|
JRNZ CMS4
|
|
RET ;COMMAND IS CPR-RESIDENT (ZERO FLAG SET)
|
|
CMS3:
|
|
INX H ;SKIP TO NEXT COMMAND TABLE ENTRY
|
|
DJNZ CMS3
|
|
CMS4:
|
|
INX H ;SKIP ADDRESS
|
|
INX H
|
|
DCR C ;DECREMENT TABLE ENTRY NUMBER
|
|
JRNZ CMS1
|
|
INR C ;CLEAR ZERO FLAG
|
|
RET ;COMMAND IS DISK-RESIDENT (ZERO FLAG CLEAR)
|
|
;
|
|
;**** Section 5 ****
|
|
; CPR-Resident Commands
|
|
;
|
|
;
|
|
;Section 5A
|
|
;Command: DIR
|
|
;Function: To display a directory of the files on disk
|
|
;Forms:
|
|
; DIR <afn> Displays the DIR files
|
|
; DIR <afn> S Displays the SYS files
|
|
; DIR <afn> A Display both DIR and SYS files
|
|
;
|
|
DIR:
|
|
MVI A,80H ;SET SYSTEM BIT EXAMINATION
|
|
PUSH PSW
|
|
CALL SCANER ;EXTRACT POSSIBLE D:FILENAME.TYP TOKEN
|
|
CALL SLOGIN ;LOG IN DRIVE IF NECESSARY
|
|
LXI H,FCBFN ;MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP
|
|
MOV A,M ;GET FIRST CHAR OF FILENAME.TYP
|
|
CPI ' ' ;IF <SP>, ALL WILD
|
|
CZ FILLQ
|
|
CALL ADVAN ;LOOK AT NEXT INPUT CHAR
|
|
MVI B,0 ;SYS TOKEN DEFAULT
|
|
JRZ DIR2 ;JUMP; THERE ISN'T ONE
|
|
CPI SYSFLG ;SYSTEM FLAG SPECIFIER?
|
|
JRZ GOTSYS ;GOT SYSTEM SPECIFIER
|
|
CPI SOFLG ;SYS ONLY?
|
|
JRNZ DIR2
|
|
MVI B,80H ;FLAG SYS ONLY
|
|
GOTSYS:
|
|
INX D
|
|
SDED CIBPTR
|
|
CPI SOFLG ;SYS ONLY SPEC?
|
|
JRZ DIR2 ;THEN LEAVE BIT SPEC UNCHAGNED
|
|
POP PSW ;GET FLAG
|
|
XRA A ;SET NO SYSTEM BIT EXAMINATION
|
|
PUSH PSW
|
|
DIR2:
|
|
POP PSW ;GET FLAG
|
|
DIR2A:
|
|
;DROP INTO DIRPR TO PRINT DIRECTORY
|
|
; THEN RESTART CPR
|
|
;
|
|
; DIRECTORY PRINT ROUTINE; ON ENTRY, MSB OF A IS 1 (80H) IF SYSTEM FILES EXCL
|
|
;
|
|
DIRPR:
|
|
MOV D,A ;STORE SYSTEM FLAG IN D
|
|
MVI E,0 ;SET COLUMN COUNTER TO ZERO
|
|
PUSH D ;SAVE COLUMN COUNTER (E) AND SYSTEM FLAG (D)
|
|
MOV A,B ;SYS ONLY SPECIFIER
|
|
STA SYSTST
|
|
CALL SEARF ;SEARCH FOR SPECIFIED FILE (FIRST OCCURRANCE)
|
|
CZ PRNNF ;PRINT NO FILE MSG;REG A NOT CHANGED
|
|
;
|
|
; ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN
|
|
;
|
|
DIR3:
|
|
JRZ DIR11 ;DONE IF ZERO FLAG SET
|
|
DCR A ;ADJUST TO RETURNED VALUE
|
|
RRC ;CONVERT NUMBER TO OFFSET INTO TBUFF
|
|
RRC
|
|
RRC
|
|
ANI 60H
|
|
MOV C,A ;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY)
|
|
MVI A,10 ;ADD 10 TO PT TO SYSTEM FILE ATTRIBUTE BIT
|
|
CALL DIRPTR
|
|
POP D ;GET SYSTEM BIT MASK FROM D
|
|
PUSH D
|
|
ANA D ;MASK FOR SYSTEM BIT
|
|
SYSTST EQU $+1 ;POINTER TO IN-THE-CODE BUFFER SYSTST
|
|
CPI 0
|
|
JRNZ DIR10
|
|
POP D ;GET ENTRY COUNT (=<CR> COUNTER)
|
|
MOV A,E ;ADD 1 TO IT
|
|
INR E
|
|
PUSH D ;SAVE IT
|
|
ANI 03H ;OUTPUT <CRLF> IF 4 ENTRIES PRINTED IN LINE
|
|
PUSH PSW
|
|
JRNZ DIR4
|
|
CALL CRLF ;NEW LINE
|
|
JR DIR5
|
|
DIR4:
|
|
CALL PRINT
|
|
;
|
|
IF WIDE
|
|
DB ' ' ;2 SPACES
|
|
DB FENCE ;THEN FENCE CHAR
|
|
DB ' ',' '+80H ;THEN 2 MORE SPACES
|
|
ENDIF
|
|
;
|
|
IF NOT WIDE
|
|
DB ' ' ;SPACE
|
|
DB FENCE ;THEN FENCE CHAR
|
|
DB ' '+80H ;THEN SPACE
|
|
ENDIF
|
|
;
|
|
DIR5:
|
|
MVI B,01H ;PT TO 1ST BYTE OF FILE NAME
|
|
DIR6:
|
|
MOV A,B ;A=OFFSET
|
|
CALL DIRPTR ;HL NOW PTS TO 1ST BYTE OF FILE NAME
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI ' ' ;NO FILE NAME?
|
|
JRNZ DIR8 ;PRINT FILE NAME IF PRESENT
|
|
POP PSW
|
|
PUSH PSW
|
|
CPI 03H
|
|
JRNZ DIR7
|
|
MVI A,09H ;PT TO 1ST BYTE OF FILE TYPE
|
|
CALL DIRPTR ;HL NOW PTS TO 1ST BYTE OF FILE TYPE
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI ' ' ;NO FILE TYPE?
|
|
JRZ DIR9 ;CONTINUE IF SO
|
|
DIR7:
|
|
MVI A,' ' ;OUTPUT <SP>
|
|
DIR8:
|
|
CALL CONOUT ;PRINT CHAR
|
|
INR B ;INCR CHAR COUNT
|
|
MOV A,B
|
|
CPI 12 ;END OF FILENAME.TYP?
|
|
JRNC DIR9 ;CONTINUE IF SO
|
|
CPI 09H ;END IF FILENAME ONLY?
|
|
JRNZ DIR6 ;PRINT TYP IF SO
|
|
MVI A,'.' ;PRINT DOT BETWEEN FILE NAME AND TYPE
|
|
CALL CONOUT
|
|
JR DIR6
|
|
DIR9:
|
|
POP PSW
|
|
DIR10:
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
JRNZ DIR11
|
|
CALL SEARN ;SEARCH FOR NEXT FILE
|
|
JR DIR3 ;CONTINUE
|
|
DIR11:
|
|
POP D ;RESTORE STACK
|
|
RET
|
|
;
|
|
; FILL FCB @HL WITH '?'
|
|
;
|
|
FILLQ:
|
|
MVI B,11 ;NUMBER OF CHARS IN FN & FT
|
|
FQLP:
|
|
MVI M,'?' ;STORE '?'
|
|
INX H
|
|
DJNZ FQLP
|
|
RET
|
|
;
|
|
;Section 5B
|
|
;Command: ERA
|
|
;Function: Erase files
|
|
;Forms:
|
|
; ERA <afn> Erase Specified files and print their names
|
|
;
|
|
IF NOT RAS ;NOT FOR REMOTE-ACCESS SYSTEM
|
|
;
|
|
ERA:
|
|
CALL SCANER ;PARSE FILE SPECIFICATION
|
|
CPI 11 ;ALL WILD (ALL FILES = 11 '?')?
|
|
JRNZ ERA1 ;IF NOT, THEN DO ERASES
|
|
CALL PRINTC
|
|
DB 'All','?'+80H
|
|
CALL CONIN ;GET REPLY
|
|
CPI 'Y' ;YES?
|
|
JNZ RESTRT ;RESTART CPR IF NOT
|
|
CALL CRLF ;NEW LINE
|
|
ERA1:
|
|
CALL SLOGIN ;LOG IN SELECTED DISK IF ANY
|
|
XRA A ;PRINT ALL FILES (EXAMINE SYSTEM BIT)
|
|
MOV B,A ;NO SYS-ONLY OPT TO DIRPR
|
|
CALL DIRPR ;PRINT DIRECTORY OF ERASED FILES
|
|
LXI D,FCBDN ;DELETE FILE SPECIFIED
|
|
CALL DELETE
|
|
RET ;REENTER CPR
|
|
;
|
|
ENDIF ;RAS
|
|
;
|
|
;Section 5C
|
|
;Command: LIST
|
|
;Function: Print out specified file on the LST: Device
|
|
;Forms:
|
|
; LIST <ufn> Print file (NO Paging)
|
|
;
|
|
LIST:
|
|
MVI A,0FFH ;TURN ON PRINTER FLAG
|
|
JR TYPE0
|
|
;
|
|
;Section 5D
|
|
;Command: TYPE
|
|
;Function: Print out specified file on the CON: Device
|
|
;Forms:
|
|
; TYPE <ufn> Print file
|
|
; TYPE <ufn> P Print file with paging flag
|
|
;
|
|
TYPE:
|
|
XRA A ;TURN OFF PRINTER FLAG
|
|
;
|
|
; ENTRY POINT FOR CPR LIST FUNCTION (LIST)
|
|
;
|
|
TYPE0:
|
|
STA PRFLG ;SET FLAG
|
|
CALL SCANER ;EXTRACT FILENAME.TYP TOKEN
|
|
JNZ ERROR ;ERROR IF ANY QUESTION MARKS
|
|
CALL ADVAN ;GET PGDFLG IF IT'S THERE
|
|
STA PGFLG ;SAVE IT AS A FLAG
|
|
JRZ NOSLAS ;JUMP IF INPUT ENDED
|
|
INX D ;PUT NEW BUF POINTER
|
|
XCHG
|
|
SHLD CIBPTR
|
|
NOSLAS:
|
|
CALL SLOGIN ;LOG IN SELECTED DISK IF ANY
|
|
CALL OPENF ;OPEN SELECTED FILE
|
|
JZ TYPE4 ;ABORT IF ERROR
|
|
CALL CRLF ;NEW LINE
|
|
MVI A,NLINES-1 ;SET LINE COUNT
|
|
STA PAGCNT
|
|
LXI H,CHRCNT ;SET CHAR POSITION/COUNT
|
|
MVI M,0FFH ;EMPTY LINE
|
|
MVI B,0 ;SET TAB CHAR COUNTER
|
|
TYPE1:
|
|
LXI H,CHRCNT ;PT TO CHAR POSITION/COUNT
|
|
MOV A,M ;END OF BUFFER?
|
|
CPI 80H
|
|
JRC TYPE2
|
|
PUSH H ;READ NEXT BLOCK
|
|
CALL READF
|
|
POP H
|
|
JRNZ TYPE3 ;ERROR?
|
|
XRA A ;RESET COUNT
|
|
MOV M,A
|
|
TYPE2:
|
|
INR M ;INCREMENT CHAR COUNT
|
|
LXI H,TBUFF ;PT TO BUFFER
|
|
CALL ADDAH ;COMPUTE ADDRESS OF NEXT CHAR FROM OFFSET
|
|
MOV A,M ;GET NEXT CHAR
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI 1AH ;END OF FILE (^Z)?
|
|
RZ ;RESTART CPR IF SO
|
|
;
|
|
; OUTPUT CHAR TO CON: OR LST: DEVICE WITH TABULATION
|
|
;
|
|
CPI CR ;RESET TAB COUNT?
|
|
JRZ TABRST
|
|
CPI LF ;RESET TAB COUNT?
|
|
JRZ TABRST
|
|
CPI TAB ;TAB?
|
|
JRZ LTAB
|
|
CALL LCOUT ;OUTPUT CHAR
|
|
INR B ;INCREMENT CHAR COUNT
|
|
JR TYPE2L
|
|
TABRST:
|
|
CALL LCOUT ;OUTPUT <CR> OR <LF>
|
|
MVI B,0 ;RESET TAB COUNTER
|
|
JR TYPE2L
|
|
LTAB:
|
|
MVI A,' ' ;<SP>
|
|
CALL LCOUT
|
|
INR B ;INCR POS COUNT
|
|
MOV A,B
|
|
ANI 7
|
|
JRNZ LTAB
|
|
;
|
|
; CONTINUE PROCESSING
|
|
;
|
|
TYPE2L:
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
JRZ TYPE1 ;CONTINUE IF NO CHAR
|
|
CPI 'C'-'@' ;^C?
|
|
RZ ;RESTART IF SO
|
|
JR TYPE1
|
|
TYPE3:
|
|
DCR A ;NO ERROR?
|
|
RZ ;RESTART CPR
|
|
TYPE4:
|
|
JMP ERRLOG
|
|
;
|
|
; PAGING ROUTINES
|
|
; PAGER COUNTS DOWN LINES AND PAUSES FOR INPUT (DIRECT) IF COUNT EXPIRES
|
|
; PAGSET SETS LINES/PAGE COUNT
|
|
;
|
|
PAGER:
|
|
PUSH H
|
|
LXI H,PAGCNT ;COUNT DOWN
|
|
DCR M
|
|
JRNZ PGBAK ;JUMP IF NOT END OF PAGE
|
|
MVI M,NLINES-2 ;REFILL COUNTER
|
|
;
|
|
PGFLG EQU $+1 ;POINTER TO IN-THE-CODE BUFFER PGFLG
|
|
MVI A,0 ;0 MAY BE CHANGED BY PGFLG EQUATE
|
|
CPI PGDFLG ;PAGE DEFAULT OVERRIDE OPTION WANTED?
|
|
;
|
|
IF PGDFLT ;IF PAGING IS DEFAULT
|
|
JRZ PGBAK ; PGDFLG MEANS NO PAGING, PLEASE
|
|
ELSE ;IF PAGING NOT DEFAULT
|
|
JRNZ PGBAK ; PGDFLG MEANS PLEASE PAGINATE
|
|
ENDIF
|
|
;
|
|
CALL CONIN ;GET CHAR TO CONTINUE
|
|
CPI 'C'-'@' ;^C
|
|
JZ RSTCPR ;RESTART CPR
|
|
PGBAK:
|
|
POP H ;RESTORE HL
|
|
RET
|
|
;
|
|
;Section 5E
|
|
;Command: SAVE
|
|
;Function: To save the contents of the TPA onto disk as a file
|
|
;Forms:
|
|
; SAVE <Number of Pages> <ufn>
|
|
; Save specified number of pages (start at 100H)
|
|
; from TPA into specified file; <Number of
|
|
; Pages> is in DEC
|
|
; SAVE <Number of Sectors> <ufn> S
|
|
; Like SAVE above, but numeric argument specifies
|
|
; number of sectors rather than pages
|
|
;
|
|
IF NOT RAS ;NOT FOR REMOTE-ACCESS SYSTEM
|
|
;
|
|
SAVE:
|
|
CALL NUMBER ;EXTRACT NUMBER FROM COMMAND LINE
|
|
MOV L,A ;HL=PAGE COUNT
|
|
MVI H,0
|
|
PUSH H ;SAVE PAGE COUNT
|
|
CALL EXTEST ;TEST FOR EXISTENCE OF FILE AND ABORT IF SO
|
|
MVI C,16H ;BDOS MAKE FILE
|
|
CALL GRBDOS
|
|
POP H ;GET PAGE COUNT
|
|
JRZ SAVE3 ;ERROR?
|
|
XRA A ;SET RECORD COUNT FIELD OF NEW FILE'S FCB
|
|
STA FCBCR
|
|
CALL ADVAN ;LOOK FOR 'S' FOR SECTOR OPTION
|
|
INX D ;PT TO AFTER 'S' TOKEN
|
|
CPI SECTFLG
|
|
JRZ SAVE0
|
|
DCX D ;NO 'S' TOKEN, SO BACK UP
|
|
DAD H ;DOUBLE IT FOR HL=SECTOR (128 BYTES) COUNT
|
|
SAVE0:
|
|
SDED CIBPTR ;SET PTR TO BAD TOKEN OR AFTER GOOD TOKEN
|
|
LXI D,TPA ;PT TO START OF SAVE AREA (TPA)
|
|
SAVE1:
|
|
MOV A,H ;DONE WITH SAVE?
|
|
ORA L ;HL=0 IF SO
|
|
JRZ SAVE2
|
|
DCX H ;COUNT DOWN ON SECTORS
|
|
PUSH H ;SAVE PTR TO BLOCK TO SAVE
|
|
LXI H,128 ;128 BYTES PER SECTOR
|
|
DAD D ;PT TO NEXT SECTOR
|
|
PUSH H ;SAVE ON STACK
|
|
CALL DMASET ;SET DMA ADDRESS FOR WRITE (ADDRESS IN DE)
|
|
LXI D,FCBDN ;WRITE SECTOR
|
|
MVI C,15H ;BDOS WRITE SECTOR
|
|
CALL BDOSB ;SAVE BC
|
|
POP D ;GET PTR TO NEXT SECTOR IN DE
|
|
POP H ;GET SECTOR COUNT
|
|
JRNZ SAVE3 ;WRITE ERROR?
|
|
JR SAVE1 ;CONTINUE
|
|
SAVE2:
|
|
LXI D,FCBDN ;CLOSE SAVED FILE
|
|
CALL CLOSE
|
|
INR A ;ERROR?
|
|
JRNZ SAVE4
|
|
SAVE3:
|
|
CALL PRNLE ;PRINT 'NO SPACE' ERROR
|
|
SAVE4:
|
|
CALL DEFDMA ;SET DMA TO 0080
|
|
RET ;RESTART CPR
|
|
;
|
|
; Test File in FCB for existence, ask user to delete if so, and abort if he
|
|
; choses not to
|
|
;
|
|
EXTEST:
|
|
CALL SCANER ;EXTRACT FILE NAME
|
|
JNZ ERROR ;'?' IS NOT PERMITTED
|
|
CALL SLOGIN ;LOG IN SELECTED DISK
|
|
CALL SEARF ;LOOK FOR SPECIFIED FILE
|
|
LXI D,FCBDN ;PT TO FILE FCB
|
|
RZ ;OK IF NOT FOUND
|
|
PUSH D ;SAVE PTR TO FCB
|
|
CALL PRINTC
|
|
DB 'Delete File','?'+80H
|
|
CALL CONIN ;GET RESPONSE
|
|
POP D ;GET PTR TO FCB
|
|
CPI 'Y' ;KEY ON YES
|
|
JNZ RSTCPR ;RESTART IF NO
|
|
PUSH D ;SAVE PTR TO FCB
|
|
CALL DELETE ;DELETE FILE
|
|
POP D ;GET PTR TO FCB
|
|
RET
|
|
;
|
|
ENDIF ;RAS
|
|
;
|
|
;Section 5F
|
|
;Command: REN
|
|
;Function: To change the name of an existing file
|
|
;Forms:
|
|
; REN <New ufn>=<Old ufn> Perform function
|
|
;
|
|
IF NOT RAS ;NOT FOR REMOTE-ACCESS SYSTEM
|
|
;
|
|
REN:
|
|
CALL EXTEST ;TEST FOR FILE EXISTENCE AND RETURN
|
|
; IF FILE DOESN'T EXIST; ABORT IF IT DOES
|
|
LDA TEMPDR ;SAVE CURRENT DEFAULT DISK
|
|
PUSH PSW ;SAVE ON STACK
|
|
REN0:
|
|
LXI H,FCBDN ;SAVE NEW FILE NAME
|
|
LXI D,FCBDM
|
|
LXI B,16 ;16 BYTES
|
|
LDIR
|
|
CALL ADVAN ;ADVANCE CIBPTR
|
|
CPI '=' ;'=' OK
|
|
JRNZ REN4
|
|
REN1:
|
|
XCHG ;PT TO CHAR AFTER '=' IN HL
|
|
INX H
|
|
SHLD CIBPTR ;SAVE PTR TO OLD FILE NAME
|
|
CALL SCANER ;EXTRACT FILENAME.TYP TOKEN
|
|
JRNZ REN4 ;ERROR IF ANY '?'
|
|
POP PSW ;GET OLD DEFAULT DRIVE
|
|
MOV B,A ;SAVE IT
|
|
LXI H,TEMPDR ;COMPARE IT AGAINST CURRENT DEFAULT DRIVE
|
|
MOV A,M ;MATCH?
|
|
ORA A
|
|
JRZ REN2
|
|
CMP B ;CHECK FOR DRIVE ERROR
|
|
MOV M,B
|
|
JRNZ REN4
|
|
REN2:
|
|
MOV M,B
|
|
XRA A
|
|
STA FCBDN ;SET DEFAULT DRIVE
|
|
LXI D,FCBDN ;RENAME FILE
|
|
MVI C,17H ;BDOS RENAME FCT
|
|
CALL GRBDOS
|
|
RNZ
|
|
REN3:
|
|
CALL PRNNF ;PRINT NO FILE MSG
|
|
REN4:
|
|
JMP ERRLOG
|
|
;
|
|
ENDIF ;RAS
|
|
;
|
|
;Section 5G
|
|
;Command: USER
|
|
;Function: Change current USER number
|
|
;Forms:
|
|
; USER <unum> Select specified user number;<unum> is in DEC
|
|
;
|
|
USER:
|
|
CALL USRNUM ;EXTRACT USER NUMBER FROM COMMAND LINE
|
|
MOV E,A ;PLACE USER NUMBER IN E
|
|
CALL SETUSR ;SET SPECIFIED USER
|
|
RSTJMP:
|
|
JMP RCPRNL ;RESTART CPR
|
|
;
|
|
;Section 5H
|
|
;Command: DFU
|
|
;Function: Set the Default User Number for the command/file scanner
|
|
; (MEMLOAD)
|
|
;Forms:
|
|
; DFU <unum> Select Default User Number;<unum> is in DEC
|
|
;
|
|
DFU:
|
|
CALL USRNUM ;GET USER NUMBER
|
|
STA DFUSR ;PUT IT AWAY
|
|
JR RSTJMP ;RESTART CPR (NO DEFAULT LOGIN)
|
|
;
|
|
;Section 5I
|
|
;Command: JUMP
|
|
;Function: To Call the program (subroutine) at the specified address
|
|
; without loading from disk
|
|
;Forms:
|
|
; JUMP <adr> Call at <adr>;<adr> is in HEX
|
|
;
|
|
IF NOT RAS ;NOT FOR REMOTE-ACCESS SYSTEM
|
|
;
|
|
JUMP:
|
|
CALL HEXNUM ;GET LOAD ADDRESS IN HL
|
|
JR CALLPROG ;PERFORM CALL
|
|
;
|
|
ENDIF ;RAS
|
|
;
|
|
;Section 5J
|
|
;Command: GO
|
|
;Function: To Call the program in the TPA without loading
|
|
; loading from disk. Same as JUMP 100H, but much
|
|
; more convenient, especially when used with
|
|
; parameters for programs like STAT. Also can be
|
|
; allowed on remote-access systems with no problems.
|
|
;
|
|
;Form:
|
|
; GO <parameters like for COMMAND>
|
|
;
|
|
IF NOT RAS ;ONLY IF RAS
|
|
;
|
|
GO: LXI H,TPA ;Always to TPA
|
|
JR CALLPROG ;Perform call
|
|
;
|
|
ENDIF ;END OF GO FOR RAS
|
|
;
|
|
;Section 5K
|
|
;Command: COM file processing
|
|
;Function: To load the specified COM file from disk and execute it
|
|
;Forms:
|
|
; <command>
|
|
;
|
|
COM:
|
|
LDA FCBFN ;ANY COMMAND?
|
|
CPI ' ' ;' ' MEANS COMMAND WAS 'D:' TO SWITCH
|
|
JRNZ COM1 ;NOT <SP>, SO MUST BE TRANSIENT OR ERROR
|
|
LDA TEMPDR ;LOOK FOR DRIVE SPEC
|
|
ORA A ;IF ZERO, JUST BLANK
|
|
JZ RCPRNL
|
|
DCR A ;ADJUST FOR LOG IN
|
|
STA TDRIVE ;SET DEFAULT DRIVE
|
|
CALL SETU0D ;SET DRIVE WITH USER 0
|
|
CALL LOGIN ;LOG IN DRIVE
|
|
JMP RCPRNL ;RESTART CPR
|
|
COM1:
|
|
LDA FCBFT ;FILE TYPE MUST BE BLANK
|
|
CPI ' '
|
|
JNZ ERROR
|
|
LXI H,COMMSG ;PLACE DEFAULT FILE TYPE (COM) INTO FCB
|
|
LXI D,FCBFT ;COPY INTO FILE TYPE
|
|
LXI B,3 ;3 BYTES
|
|
LDIR
|
|
LXI H,TPA ;SET EXECUTION/LOAD ADDRESS
|
|
PUSH H ;SAVE FOR EXECUTION
|
|
CALL MEMLOAD ;LOAD MEMORY WITH FILE SPECIFIED IN CMD LINE
|
|
POP H ;GET EXECUTION ADDRESS
|
|
RNZ ;RETURN (ABORT) IF LOAD ERROR
|
|
;
|
|
; CALLPROG IS THE ENTRY POINT FOR THE EXECUTION OF THE LOADED
|
|
; PROGRAM;ON ENTRY TO THIS ROUTINE, HL MUST CONTAIN THE EXECUTION
|
|
; ADDRESS OF THE PROGRAM (SUBROUTINE) TO EXECUTE
|
|
;
|
|
CALLPROG:
|
|
SHLD EXECADR ;PERFORM IN-LINE CODE MODIFICATION
|
|
CALL DLOGIN ;LOG IN DEFAULT DRIVE
|
|
CALL SCANER ;SEARCH COMMAND LINE FOR NEXT TOKEN
|
|
LXI H,TEMPDR ;SAVE PTR TO DRIVE SPEC
|
|
PUSH H
|
|
MOV A,M ;SET DRIVE SPEC
|
|
STA FCBDN
|
|
LXI H,FCBDN+10H ;PT TO 2ND FILE NAME
|
|
CALL SCANX ;SCAN FOR IT AND LOAD IT INTO FCBDN+16
|
|
POP H ;SET UP DRIVE SPECS
|
|
MOV A,M
|
|
STA FCBDM
|
|
XRA A
|
|
STA FCBCR
|
|
LXI D,TFCB ;COPY TO DEFAULT FCB
|
|
LXI H,FCBDN ;FROM FCBDN
|
|
LXI B,33 ;SET UP DEFAULT FCB
|
|
LDIR
|
|
LXI H,CIBUFF
|
|
COM4:
|
|
MOV A,M ;SKIP TO END OF 2ND FILE NAME
|
|
ORA A ;END OF LINE?
|
|
JRZ COM5
|
|
CPI ' ' ;END OF TOKEN?
|
|
JRZ COM5
|
|
INX H
|
|
JR COM4
|
|
;
|
|
; LOAD COMMAND LINE INTO TBUFF
|
|
;
|
|
COM5:
|
|
MVI B,0 ;SET CHAR COUNT
|
|
LXI D,TBUFF+1 ;PT TO CHAR POS
|
|
COM6:
|
|
MOV A,M ;COPY COMMAND LINE TO TBUFF
|
|
STAX D
|
|
ORA A ;DONE IF ZERO
|
|
JRZ COM7
|
|
INR B ;INCR CHAR COUNT
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
JR COM6
|
|
;
|
|
; RUN LOADED TRANSIENT PROGRAM
|
|
;
|
|
COM7:
|
|
MOV A,B ;SAVE CHAR COUNT
|
|
STA TBUFF
|
|
CALL CRLF ;NEW LINE
|
|
CALL DEFDMA ;SET DMA TO 0080
|
|
CALL SETUD ;SET USER/DISK
|
|
;
|
|
; EXECUTION (CALL) OF PROGRAM (SUBROUTINE) OCCURS HERE
|
|
;
|
|
EXECADR EQU $+1 ;CHANGE ADDRESS FOR IN-LINE CODE MODIFICATION
|
|
CALL TPA ;CALL TRANSIENT
|
|
CALL DEFDMA ;SET DMA TO 0080, IN CASE
|
|
;PROG CHANGED IT ON US
|
|
CALL SETU0D ;SET USER 0/DISK
|
|
CALL LOGIN ;LOGIN DISK
|
|
JMP RESTRT ;RESTART CPR
|
|
;
|
|
; TRANSIENT LOAD ERROR
|
|
;
|
|
COM8:
|
|
POP H ;CLEAR RETURN ADDRESS
|
|
CALL RESETUSR ;RESET CURRENT USER NUMBER
|
|
; RESET MUST BE DONE BEFORE LOGIN
|
|
ERRLOG:
|
|
CALL DLOGIN ;LOG IN DEFAULT DISK
|
|
ERRJMP:
|
|
JMP ERROR
|
|
;
|
|
;Section 5L
|
|
;Command: GET
|
|
;Function: To load the specified file from disk to the specified address
|
|
;Forms:
|
|
; GET <adr> <ufn> Load the specified file at the specified page;
|
|
; <adr> is in HEX
|
|
;
|
|
IF NOT RAS ;NOT FOR REMOTE-ACCESS SYSTEM
|
|
;
|
|
GET:
|
|
CALL HEXNUM ;GET LOAD ADDRESS IN HL
|
|
PUSH H ;SAVE ADDRESS
|
|
CALL SCANER ;GET FILE NAME
|
|
POP H ;RESTORE ADDRESS
|
|
JRNZ ERRJMP ;MUST BE UNAMBIGUOUS
|
|
;
|
|
; FALL THRU TO MEMLOAD
|
|
;
|
|
ENDIF ;RAS
|
|
;
|
|
; LOAD MEMORY WITH THE FILE WHOSE NAME IS SPECIFIED IN THE COMMAND LINE
|
|
; ON INPUT, HL CONTAINS STARTING ADDRESS TO LOAD
|
|
;
|
|
MEMLOAD:
|
|
CALL MLOAD ;USER MEMORY LOAD SUBROUTINE
|
|
PUSH PSW ;SAVE RETURN STATUS
|
|
CALL RESETUSR ;RESET USER NUMBER
|
|
POP PSW ;GET RETURN STATUS
|
|
RET
|
|
|
|
;
|
|
; MEMORY LOAD SUBROUTINE
|
|
; EXIT POINTS ARE A SIMPLE RETURN WITH THE ZERO FLAG SET IF NO ERROR,
|
|
; A SIMPLE RETURN WITH THE ZERO FLAG RESET (NZ) IF MEMORY FULL, OR A JMP TO
|
|
; COM8 IF COM FILE NOT FOUND
|
|
;
|
|
MLOAD:
|
|
SHLD LOADADR ;SET LOAD ADDRESS
|
|
CALL GETUSR ;GET CURRENT USER NUMBER
|
|
STA TMPUSR ;SAVE IT FOR LATER
|
|
STA TSELUSR ;TEMP USER TO SELECT
|
|
;
|
|
; MLA is a reentry point for a non-standard CP/M Modification
|
|
; This is the return point for when the .COM (or GET) file is not found the
|
|
; first time, Drive A: is selected for a second attempt
|
|
;
|
|
MLA:
|
|
CALL SLOGIN ;LOG IN SPECIFIED DRIVE IF ANY
|
|
CALL OPENF ;OPEN COMMAND.COM FILE
|
|
JRNZ MLA1 ;FILE FOUND - LOAD IT
|
|
;
|
|
; ERROR ROUTINE TO SELECT USER 0 IF ALL ELSE FAILS
|
|
;
|
|
DFUSR EQU $+1 ;MARK IN-THE-CODE VARIABLE
|
|
MVI A,DEFUSR ;GET DEFAULT USER
|
|
TSELUSR EQU $+1 ;MARK IN-THE-CODE VARIABLE
|
|
CPI DEFUSR ;SAME?
|
|
JRZ MLA0 ;JUMP IF
|
|
STA TSELUSR ;ELSE PUT DOWN NEW ONE
|
|
MOV E,A
|
|
CALL SETUSR ;GO SET NEW USER NUMBER
|
|
JR MLA ;AND TRY AGAIN
|
|
;
|
|
; ERROR ROUTINE TO SELECT DRIVE A: IF DEFAULT WAS ORIGINALLY SELECTED
|
|
;
|
|
MLA0:
|
|
LXI H,TEMPDR ;GET DRIVE FROM CURRENT COMMAND
|
|
XRA A ;A=0
|
|
ORA M
|
|
JNZ COM8 ;ERROR IF ALREADY DISK A:
|
|
MVI M,1 ;SELECT DRIVE A:
|
|
JR MLA
|
|
;
|
|
; FILE FOUND -- PROCEED WITH LOAD
|
|
;
|
|
MLA1:
|
|
LOADADR EQU $+1 ;MEMORY LOAD ADDRESS (IN-LINE CODE MOD)
|
|
LXI H,TPA ;SET START ADDRESS OF MEMORY LOAD
|
|
ML2:
|
|
MVI A,ENTRY/256-1 ;GET HIGH-ORDER ADR OF JUST BELOW CPR
|
|
CMP H ;ARE WE GOING TO OVERWRITE THE CPR?
|
|
JRC PRNLE ;ERROR IF SO
|
|
PUSH H ;SAVE ADDRESS OF NEXT SECTOR
|
|
XCHG ;... IN DE
|
|
CALL DMASET ;SET DMA ADDRESS FOR LOAD
|
|
LXI D,FCBDN ;READ NEXT SECTOR
|
|
CALL READ
|
|
POP H ;GET ADDRESS OF NEXT SECTOR
|
|
JRNZ ML3 ;READ ERROR OR EOF?
|
|
LXI D,128 ;MOVE 128 BYTES PER SECTOR
|
|
DAD D ;PT TO NEXT SECTOR IN HL
|
|
JR ML2
|
|
;
|
|
ML3:
|
|
DCR A ;LOAD COMPLETE
|
|
RZ ;OK IF ZERO, ELSE FALL THRU TO PRNLE
|
|
;
|
|
; LOAD ERROR
|
|
;
|
|
PRNLE:
|
|
CALL PRINTC
|
|
DB 'Ful','l'+80H
|
|
MVI A,1 ;SET NON-ZERO TO INDICATE ERROR
|
|
ORA A ;SET FLAG
|
|
RET
|
|
;
|
|
END
|
|
|