mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2306 lines
44 KiB
2306 lines
44 KiB
* SYSTEM SEGMENT: SYS.RCP
|
|
* SYSTEM: ARIES-1
|
|
* CUSTOMIZED BY: RICHARD CONN
|
|
|
|
*
|
|
* PROGRAM: SYSRCP.ASM
|
|
* AUTHOR: RICHARD CONN
|
|
* VERSION: 1.0
|
|
* DATE: 3 FEB 84
|
|
* PREVIOUS VERSIONS: NONE
|
|
*
|
|
VERSION EQU 10
|
|
|
|
*
|
|
* SYSRCP is a resident command processor for ZCPR3. As with
|
|
* all resident command processors, SYSRCP performs the following functions:
|
|
*
|
|
* 1. Assuming that the EXTFCB contains the name of the
|
|
* command, SYSRCP looks to see if the first character
|
|
* of the file name field in the EXTFCB is a question
|
|
* mark; if so, it returns with the Zero Flag Set and
|
|
* HL pointing to the internal routine which prints
|
|
* its list of commands
|
|
* 2. The resident command list in SYSRCP is scanned for
|
|
* the entry contained in the file name field of
|
|
* EXTFCB; if found, SYSRCP returns with the Zero Flag
|
|
* Set and HL pointing to the internal routine which
|
|
* implements the function; if not found, SYSRCP returns
|
|
* with the Zero Flag Reset (NZ)
|
|
*
|
|
|
|
*
|
|
* Global Library which Defines Addresses for SYSRCP
|
|
*
|
|
MACLIB Z3BASE ; USE BASE ADDRESSES
|
|
MACLIB SYSRCP ; USE SYSRCP HEADER
|
|
|
|
;
|
|
CTRLC EQU 'C'-'@'
|
|
TAB EQU 09H
|
|
LF EQU 0AH
|
|
FF EQU 0CH
|
|
CR EQU 0DH
|
|
CTRLX EQU 'X'-'@'
|
|
;
|
|
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
|
|
FCB1 EQU TFCB ;1st and 2nd FCBs
|
|
FCB2 EQU TFCB+16
|
|
TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER
|
|
TPA EQU BASE+0100H ;BASE OF TPA
|
|
DIRBUF EQU BASE+4000H ;DIR BUFFER (MANY ENTRIES PERMITTED)
|
|
PAGCNT EQU DIRBUF-100H ;PAGE COUNT BUFFER
|
|
OLDFCB EQU PAGCNT+1 ;OLD FCB BUFFER
|
|
CPBLOCKS EQU 32 ;USE 4K FOR BUFFERING OF COPY
|
|
;
|
|
$-MACRO ;FIRST TURN OFF THE EXPANSIONS
|
|
;
|
|
; MACROS TO PROVIDE Z80 EXTENSIONS
|
|
; MACROS INCLUDE:
|
|
;
|
|
; 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
|
|
;
|
|
; @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,?DD ;Displacement Range Error on Jump Relative
|
|
ELSE
|
|
DB ?DD
|
|
ENDIF ;;RANGE ERROR
|
|
ENDM
|
|
;
|
|
;
|
|
; Z80 MACRO EXTENSIONS
|
|
;
|
|
JR MACRO ?N ;;JUMP RELATIVE
|
|
IF I8080 ;;8080/8085
|
|
JMP ?N
|
|
ELSE ;;Z80
|
|
DB 18H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRC MACRO ?N ;;JUMP RELATIVE ON CARRY
|
|
IF I8080 ;;8080/8085
|
|
JC ?N
|
|
ELSE ;;Z80
|
|
DB 38H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY
|
|
IF I8080 ;;8080/8085
|
|
JNC ?N
|
|
ELSE ;;Z80
|
|
DB 30H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRZ MACRO ?N ;;JUMP RELATIVE ON ZERO
|
|
IF I8080 ;;8080/8085
|
|
JZ ?N
|
|
ELSE ;;Z80
|
|
DB 28H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
JRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO
|
|
IF I8080 ;;8080/8085
|
|
JNZ ?N
|
|
ELSE ;;Z80
|
|
DB 20H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
;
|
|
DJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
|
|
IF I8080 ;;8080/8085
|
|
DCR B
|
|
JNZ ?N
|
|
ELSE ;;Z80
|
|
DB 10H
|
|
@GENDD ?N-$-1
|
|
ENDIF ;;I8080
|
|
ENDM
|
|
*
|
|
* SYSTEM Entry Point
|
|
*
|
|
org rcp ; passed for Z3BASE
|
|
|
|
db 'Z3RCP' ; Flag for Package Loader
|
|
*
|
|
* **** Command Table for RCP ****
|
|
* This table is RCP-dependent!
|
|
*
|
|
* The command name table is structured as follows:
|
|
*
|
|
* ctable:
|
|
* DB 'CMNDNAME' ; Table Record Structure is
|
|
* DW cmndaddress ; 8 Chars for Name and 2 Bytes for Adr
|
|
* ...
|
|
* DB 0 ; End of Table
|
|
*
|
|
cnsize equ 4 ; NUMBER OF CHARS IN COMMAND NAME
|
|
db cnsize ; size of text entries
|
|
ctab:
|
|
db 'H ' ; Help for RCP
|
|
dw clist
|
|
ctab1:
|
|
;
|
|
IF CPON
|
|
db 'CP ' ; Copy
|
|
dw copy
|
|
ENDIF ;CPON
|
|
;
|
|
IF DIRON
|
|
db 'DIR ' ; Directory
|
|
dw dir
|
|
ENDIF ;DIRON
|
|
;
|
|
IF ECHOON
|
|
db 'ECHO' ; Echo
|
|
dw echo
|
|
ENDIF
|
|
;
|
|
IF ERAON
|
|
db 'ERA ' ; Erase
|
|
dw era
|
|
ENDIF ;ERAON
|
|
;
|
|
IF LTON AND LISTON
|
|
db 'LIST' ; List
|
|
dw list
|
|
ENDIF ;LTON AND LISTON
|
|
;
|
|
IF NOTEON
|
|
db 'NOTE' ; Note-Comment-NOP Command
|
|
dw note
|
|
ENDIF
|
|
;
|
|
IF PEEKON
|
|
db 'P ' ; Peek into Memory
|
|
dw peek
|
|
ENDIF ;PEEKON
|
|
;
|
|
IF POKEON
|
|
db 'POKE' ; Poke Values into Memory
|
|
dw poke
|
|
ENDIF ;POKEON
|
|
;
|
|
IF PROTON
|
|
db 'PROT' ; Protection Codes
|
|
dw att
|
|
ENDIF ;PROTON
|
|
;
|
|
IF REGON
|
|
db 'REG ' ; Register Command
|
|
dw regcmd
|
|
ENDIF ;RSETON
|
|
;
|
|
IF RENON
|
|
db 'REN ' ; Rename
|
|
dw ren
|
|
ENDIF ;RENON
|
|
;
|
|
IF LTON
|
|
db 'TYPE' ; Type
|
|
dw type
|
|
ENDIF ;LTON
|
|
;
|
|
IF WHLON
|
|
db 'WHL ' ; Wheel
|
|
dw whl
|
|
db 'WHLQ' ; Wheel Query
|
|
dw whlmsg
|
|
ENDIF ;WHLON
|
|
;
|
|
db 0
|
|
*
|
|
* BANNER NAME OF RCP
|
|
*
|
|
rcp$name:
|
|
db 'SYS '
|
|
db (version/10)+'0','.',(version mod 10)+'0'
|
|
db RCPID
|
|
db 0
|
|
|
|
*
|
|
* Command List Routine
|
|
*
|
|
clist:
|
|
lxi h,rcp$name ; print RCP Name
|
|
call print1
|
|
lxi h,ctab1 ; print table entries
|
|
mvi c,1 ; set count for new line
|
|
clist1:
|
|
mov a,m ; done?
|
|
ora a
|
|
rz
|
|
dcr c ; count down
|
|
jrnz clist1a
|
|
call crlf ; new line
|
|
mvi c,4 ; set count
|
|
clist1a:
|
|
lxi d,entryname ; copy command name into message buffer
|
|
mvi b,cnsize ; number of chars
|
|
clist2:
|
|
mov a,m ; copy
|
|
stax d
|
|
inx h ; pt to next
|
|
inx d
|
|
dcr b
|
|
jnz clist2
|
|
inx h ; skip to next entry
|
|
inx h
|
|
push h ; save ptr
|
|
lxi h,entrymsg ; print message
|
|
call print1
|
|
pop h ; get ptr
|
|
jmp clist1
|
|
*
|
|
* Console Output Routine
|
|
*
|
|
conout:
|
|
push h ; save regs
|
|
push d
|
|
push b
|
|
push psw
|
|
ani 7fh ; mask MSB
|
|
mov e,a ; char in E
|
|
mvi c,2 ; output
|
|
call bdos
|
|
pop psw ; get regs
|
|
pop b
|
|
pop d
|
|
pop h
|
|
;
|
|
; This simple return doubles for the NOTE Command (NOP) and CONOUT Exit
|
|
; NOTE Command: NOTE any text
|
|
;
|
|
NOTE:
|
|
ret
|
|
*
|
|
* Print String (terminated in 0 or MSB Set) at Return Address
|
|
*
|
|
print:
|
|
xthl ; get address
|
|
call print1
|
|
xthl ; put address
|
|
ret
|
|
*
|
|
* Print String (terminated in 0 or MSB Set) pted to by HL
|
|
*
|
|
print1:
|
|
mov a,m ; done?
|
|
inx h ; pt to next
|
|
ora a ; 0 terminator
|
|
rz
|
|
call conout ; print char
|
|
rm ; MSB terminator
|
|
jmp print1
|
|
*
|
|
* CLIST Messages
|
|
*
|
|
entrymsg:
|
|
db ' ' ; command name prefix
|
|
entryname:
|
|
ds cnsize ; command name
|
|
db 0 ; terminator
|
|
|
|
*
|
|
* **** RCP Routines ****
|
|
* All code from here on is RCP-dependent!
|
|
*
|
|
|
|
;
|
|
;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
|
|
;Notes:
|
|
; The flag SYSFLG defines the letter used to display both DIR and
|
|
; SYS files (A in the above Forms section)
|
|
; The flag SOFLG defines the letter used to display only the SYS
|
|
; files (S in the above Forms section)
|
|
; The flag WIDE determines if the file names are spaced further
|
|
; apart (WIDE=TRUE) for 80-col screens
|
|
; The flag FENCE defines the character used to separate the file
|
|
; names
|
|
;
|
|
IF DIRON
|
|
DIR:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WDIR
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE ;SAVE RET ADDRESS AND SET STACK
|
|
LXI H,FCB1+1 ;MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP
|
|
MOV A,M ;GET FIRST CHAR OF FILENAME.TYP
|
|
CPI ' ' ;IF <SP>, ALL WILD
|
|
CZ FILLQ
|
|
LDA FCB2+1 ;GET FIRST CHAR OF 2ND FILE NAME
|
|
MVI B,80H ;PREPARE FOR DIR-ONLY SELECTION
|
|
CPI ' ' ;ANY FLAG?
|
|
JRZ DIRPR ;THERE IS NO FLAG, SO DIR ONLY
|
|
MVI B,1 ;SET FOR BOTH DIR AND SYS FILES
|
|
CPI SYSFLG ;SYSTEM AND DIR FLAG SPECIFIER?
|
|
JRZ DIRPR ;GOT SYSTEM SPECIFIER
|
|
CPI SOFLG ;SYS ONLY?
|
|
JRNZ DIRPR
|
|
DCR B ;B=0 FOR SYS FILES ONLY
|
|
;
|
|
ENDIF ;DIRON
|
|
;
|
|
; DIRECTORY PRINT ROUTINE; ON ENTRY, B REG IS SET AS FOLLOWS:
|
|
; 0 FOR ONLY SYSTEM FILES, 80H FOR ONLY DIR FILES, 1 FOR BOTH
|
|
;
|
|
IF DIRON OR ERAON OR LTON OR PROTON OR CPON OR RENON
|
|
DIRPR:
|
|
MOV A,B ;GET SYSTST FLAG
|
|
CALL GETDIR ;LOAD AND SORT DIRECTORY
|
|
JZ PRFNF ;PRINT NO FILE MESSAGE
|
|
MVI E,4 ;COUNT DOWN TO 0
|
|
;
|
|
; ENTRY PRINT LOOP; ON ENTRY, HL PTS TO FILES SELECTED (TERMINATED BY 0)
|
|
; AND E IS ENTRY COUNTER
|
|
;
|
|
DIR3:
|
|
MOV A,M ;CHECK FOR DONE
|
|
ORA A
|
|
JZ EXIT ;EXIT IF DONE
|
|
MOV A,E ;GET ENTRY COUNTER
|
|
ORA A ;OUTPUT <CRLF> IF 4 ENTRIES PRINTED IN LINE
|
|
CZ DIRCRLF ;NEW LINE
|
|
MOV A,E ;GET ENTRY COUNT
|
|
CPI 4 ;FIRST ENTRY?
|
|
JRZ DIR4
|
|
CALL PRINT
|
|
;
|
|
IF WIDE
|
|
;
|
|
DB ' ' ;2 SPACES
|
|
DB FENCE ;THEN FENCE CHAR
|
|
DB ' '+80H ;THEN 1 MORE SPACE
|
|
;
|
|
ELSE
|
|
;
|
|
DB ' ' ;SPACE
|
|
DB FENCE+80H ;THEN FENCE CHAR
|
|
;
|
|
ENDIF ;WIDE
|
|
;
|
|
DIR4:
|
|
CALL PRFN ;PRINT FILE NAME
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
DCR E ;DECREMENT ENTRY COUNTER
|
|
JR DIR3
|
|
;
|
|
; CRLF FOR DIR ROUTINE
|
|
;
|
|
DIRCRLF:
|
|
PUSH PSW ;DON'T AFFECT PSW
|
|
CALL CRLF ;NEW LINE
|
|
POP PSW
|
|
MVI E,4 ;RESET ENTRY COUNTER
|
|
RET
|
|
;
|
|
; AFTER A SEARCH, RETURN NZ SET IF DESIRED TYPE OF FILE FOUND, Z IF NOT
|
|
; THIS ALGORITHM LOOKS AT THE SYSTEM BIT OF THE LOCATED FILE; THIS
|
|
; BIT IS SET TO 1 IF THE FILE IS A SYSTEM FILE AND 0 IF NOT A SYSTEM
|
|
; FILE. THE FOLLOWING EXCLUSIVE OR MASKS ARE APPLIED TO RETURN Z OR NZ
|
|
; AS REQUIRED BY THE CALLING PROGRAM:
|
|
;
|
|
; SYSTEM BYTE: X 0 0 0 0 0 0 0 (AFTER 80H MASK, X=1 IF SYS, 0 IF DIR)
|
|
;
|
|
; SYS-ONLY : 0 0 0 0 0 0 0 0 (XOR 0 = 0 if X=0, = 80H if X=1)
|
|
; DIR-ONLY : 1 0 0 0 0 0 0 0 (XOR 80H = 80h if X=0, = 0 if X=1)
|
|
; BOTH : 0 0 0 0 0 0 0 1 (XOR 1 = 81H or 1H, NZ in both cases)
|
|
;
|
|
GETSBIT:
|
|
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)
|
|
LXI D,TBUFF ;PT TO BUFFER
|
|
MOV A,E ;BASE ADDRESS IN A
|
|
ADD C ;ADD IN ENTRY OFFSET
|
|
MOV E,A ;RESULT IN E
|
|
PUSH D ;SAVE PTR IN DE
|
|
ADI 10 ;ADD OFFSET OF 10 TO PT TO SYSTEM BYTE
|
|
MOV E,A ;SET ADDRESS
|
|
LDAX D ;GET BYTE
|
|
POP D ;GET PTR IN DE
|
|
ANI 80H ;LOOK AT ONLY SYSTEM BIT
|
|
SYSTST EQU $+1 ;IN-THE-CODE VARIABLE
|
|
XRI 0 ; IF SYSTST=0, SYS ONLY; IF SYSTST=80H, DIR
|
|
; ONLY; IF SYSTST=1, BOTH SYS AND DIR
|
|
RET ;NZ IF OK, Z IF NOT OK
|
|
;
|
|
; FILL FCB @HL WITH '?'
|
|
;
|
|
FILLQ:
|
|
MVI B,11 ;NUMBER OF CHARS IN FN & FT
|
|
MVI A,'?' ;STORE '?'
|
|
FILLP:
|
|
MOV M,A ;STORE BYTE
|
|
INX H ;PT TO NEXT
|
|
DJNZ FILLP ;COUNT DOWN
|
|
RET
|
|
;
|
|
; LOAD DIRECTORY AND SORT IT
|
|
; ON INPUT, A=SYSTST FLAG (0=SYS, 1=DIR, 80H=BOTH)
|
|
; DIRECTORY IS LOADED INTO DIRBUF
|
|
; RETURN WITH ZERO SET IF NO MATCH AND HL PTS TO 1ST ENTRY IF MATCH
|
|
;
|
|
GETDIR:
|
|
STA SYSTST ; SET SYSTEM TEST FLAG
|
|
CALL LOGUSR ; LOG INTO USER AREA OF FCB1
|
|
LXI H,DIRBUF ; PT TO DIR BUFFER
|
|
MVI M,0 ; SET EMPTY
|
|
LXI B,0 ; SET COUNTER
|
|
CALL SEARF ; LOOK FOR MATCH
|
|
RZ ; RETURN IF NOT FOUND
|
|
;
|
|
; STEP 1: LOAD DIRECTORY
|
|
;
|
|
GD1:
|
|
PUSH B ; SAVE COUNTER
|
|
CALL GETSBIT ; CHECK FOR SYSTEM OK
|
|
POP B
|
|
JRZ GD2 ; NOT OK, SO SKIP
|
|
PUSH B ; SAVE COUNTER
|
|
INX D ; PT TO FILE NAME
|
|
XCHG ; HL PTS TO FILE NAME, DE PTS TO BUFFER
|
|
MVI B,11 ; COPY 11 BYTES
|
|
CALL LDIR ; DO COPY
|
|
XCHG ; HL PTS TO NEXT BUFFER LOCATION
|
|
POP B ; GET COUNTER
|
|
INX B ; INCREMENT COUNTER
|
|
GD2:
|
|
CALL SEARN ; LOOK FOR NEXT
|
|
JRNZ GD1
|
|
MVI M,0 ; STORE ENDING 0
|
|
LXI H,DIRBUF ; PT TO DIR BUFFER
|
|
MOV A,M ; CHECK FOR EMPTY
|
|
ORA A
|
|
RZ
|
|
;
|
|
; STEP 2: SORT DIRECTORY
|
|
;
|
|
PUSH H ; SAVE PTR TO DIRBUF FOR RETURN
|
|
CALL DIRALPHA ; SORT
|
|
POP H
|
|
XRA A ; SET NZ FLAG FOR OK
|
|
DCR A
|
|
RET
|
|
|
|
;*
|
|
;* DIRALPHA -- ALPHABETIZES DIRECTORY IN DIRBUF; BC CONTAINS
|
|
;* THE NUMBER OF FILES IN THE DIRECTORY
|
|
;*
|
|
DIRALPHA:
|
|
MOV A,B ; ANY FILES?
|
|
ORA C
|
|
RZ
|
|
MOV H,B ; HL=BC=FILE COUNT
|
|
MOV L,C
|
|
SHLD N ; SET "N"
|
|
;*
|
|
;* SHELL SORT --
|
|
;* THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS"
|
|
;* BY KERNIGAN AND PLAUGHER, PAGE 106. COPYRIGHT, 1976, ADDISON-WESLEY.
|
|
;* ON ENTRY, BC=NUMBER OF ENTRIES
|
|
;*
|
|
N EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ; NUMBER OF ITEMS TO SORT
|
|
SHLD GAP ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2
|
|
|
|
;* FOR (GAP = N/2; GAP > 0; GAP = GAP/2)
|
|
SRTL0:
|
|
ORA A ; CLEAR CARRY
|
|
GAP EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ; GET PREVIOUS GAP
|
|
MOV A,H ; ROTATE RIGHT TO DIVIDE BY 2
|
|
RAR
|
|
MOV H,A
|
|
MOV A,L
|
|
RAR
|
|
MOV L,A
|
|
|
|
;* TEST FOR ZERO
|
|
ORA H
|
|
RZ ; DONE WITH SORT IF GAP = 0
|
|
|
|
SHLD GAP ; SET VALUE OF GAP
|
|
SHLD I ; SET I=GAP FOR FOLLOWING LOOP
|
|
|
|
;* FOR (I = GAP + 1; I <= N; I = I + 1)
|
|
SRTL1:
|
|
I EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ; ADD 1 TO I
|
|
INX H
|
|
SHLD I
|
|
|
|
;* TEST FOR I <= N
|
|
XCHG ; I IS IN DE
|
|
LHLD N ; GET N
|
|
MOV A,L ; COMPARE BY SUBTRACTION
|
|
SUB E
|
|
MOV A,H
|
|
SBB D ; CARRY SET MEANS I > N
|
|
JRC SRTL0 ; DON'T DO FOR LOOP IF I > N
|
|
|
|
LHLD I ; SET J = I INITIALLY FOR FIRST SUBTRACTION OF GAP
|
|
SHLD J
|
|
|
|
;* FOR (J = I - GAP; J > 0; J = J - GAP)
|
|
SRTL2:
|
|
LHLD GAP ; GET GAP
|
|
XCHG ; ... IN DE
|
|
J EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ; GET J
|
|
MOV A,L ; COMPUTE J - GAP
|
|
SUB E
|
|
MOV L,A
|
|
MOV A,H
|
|
SBB D
|
|
MOV H,A
|
|
SHLD J ; J = J - GAP
|
|
JRC SRTL1 ; IF CARRY FROM SUBTRACTIONS, J < 0 AND ABORT
|
|
MOV A,H ; J=0?
|
|
ORA L
|
|
JRZ SRTL1 ; IF ZERO, J=0 AND ABORT
|
|
|
|
;* SET JG = J + GAP
|
|
XCHG ; J IN DE
|
|
LHLD GAP ; GET GAP
|
|
DAD D ; J + GAP
|
|
SHLD JG ; JG = J + GAP
|
|
|
|
;* IF (V(J) <= V(JG))
|
|
CALL ICOMPARE ; J IN DE, JG IN HL
|
|
|
|
;* ... THEN BREAK
|
|
JRC SRTL1
|
|
|
|
;* ... ELSE EXCHANGE
|
|
LHLD J ; SWAP J, JG
|
|
XCHG
|
|
JG EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0
|
|
CALL ISWAP ; J IN DE, JG IN HL
|
|
|
|
;* END OF INNER-MOST FOR LOOP
|
|
JR SRTL2
|
|
|
|
;*
|
|
;* SWAP (Exchange) the elements whose indexes are in HL and DE
|
|
;*
|
|
ISWAP:
|
|
CALL IPOS ; COMPUTE POSITION FROM INDEX
|
|
XCHG
|
|
CALL IPOS ; COMPUTE 2ND ELEMENT POSITION FROM INDEX
|
|
MVI B,11 ; 11 BYTES TO FLIP
|
|
ISWAP1:
|
|
LDAX D ; GET BYTES
|
|
MOV C,M
|
|
MOV M,A ; PUT BYTES
|
|
MOV A,C
|
|
STAX D
|
|
INX H ; PT TO NEXT
|
|
INX D
|
|
DJNZ ISWAP1
|
|
RET
|
|
;*
|
|
;* ICOMPARE compares the entry pointed to by the pointer pointed to by HL
|
|
;* with that pointed to by DE (1st level indirect addressing); on entry,
|
|
;* HL and DE contain the numbers of the elements to compare (1, 2, ...);
|
|
;* on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)),
|
|
;* and Non-Zero and No-Carry means ((DE)) > ((HL))
|
|
;*
|
|
ICOMPARE:
|
|
CALL IPOS ; GET POSITION OF FIRST ELEMENT
|
|
XCHG
|
|
CALL IPOS ; GET POSITION OF 2ND ELEMENT
|
|
XCHG
|
|
;*
|
|
;* COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE;
|
|
;* NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE<HL
|
|
;* RET W/ZERO SET MEANS DE=HL
|
|
;*
|
|
IF NOT SORTNT ; TYPE AND NAME?
|
|
;*
|
|
;* COMPARE BY FILE TYPE AND FILE NAME
|
|
;*
|
|
PUSH H
|
|
PUSH D
|
|
LXI B,8 ; PT TO FT (8 BYTES)
|
|
DAD B
|
|
XCHG
|
|
DAD B
|
|
XCHG ; DE, HL NOW PT TO THEIR FT'S
|
|
MVI B,3 ; 3 BYTES
|
|
CALL COMP ; COMPARE FT'S
|
|
POP D
|
|
POP H
|
|
RNZ ; CONTINUE IF COMPLETE MATCH
|
|
MVI B,8 ; 8 BYTES
|
|
JR COMP ; COMPARE FN'S
|
|
;
|
|
ELSE ; NAME AND TYPE
|
|
;*
|
|
;* COMPARE BY FILE NAME AND FILE TYPE
|
|
;*
|
|
MVI B,11 ; COMPARE FN, FT AND FALL THRU TO COMP
|
|
;*
|
|
;* COMP COMPARES DE W/HL FOR B BYTES; RET W/CARRY IF DE<HL
|
|
;* MSB IS DISREGARDED
|
|
;*
|
|
COMP:
|
|
MOV A,M ; GET (HL)
|
|
ANI 7FH ; MASK MSB
|
|
MOV C,A ; ... IN C
|
|
LDAX D ; COMPARE
|
|
ANI 7FH ; MASK MSB
|
|
CMP C
|
|
RNZ
|
|
INX H ; PT TO NEXT
|
|
INX D
|
|
DJNZ COMP ; COUNT DOWN
|
|
RET
|
|
;
|
|
ENDIF ; NOT SORTNT
|
|
;*
|
|
;* Compute physical position of element whose index is in HL; on exit, HL
|
|
;* is the physical address of this element; Indexes are 1..N
|
|
;*
|
|
IPOS:
|
|
DCX H ; HL=(HL-1)*11+DIRBUF
|
|
MOV B,H ; BC=HL
|
|
MOV C,L
|
|
DAD H ; HL=HL*2
|
|
DAD H ; HL=HL*4
|
|
DAD B ; HL=HL*5
|
|
DAD H ; HL=HL*10
|
|
DAD B ; HL=HL*11
|
|
LXI B,DIRBUF ; ADD IN DIRBUF
|
|
DAD B
|
|
RET
|
|
;
|
|
ENDIF ;DIRON OR ERAON OR LTON OR PROTON OR CPON OR RENON
|
|
;
|
|
;Section 5B
|
|
;Command: ERA
|
|
;Function: Erase files
|
|
;Forms:
|
|
; ERA <afn> Erase Specified files and print their names
|
|
; ERA <afn> I Erase Specified files and print their names, but ask
|
|
; for verification before Erase is done
|
|
;
|
|
IF ERAON
|
|
ERA:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WERA
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
LDA FCB2+1 ;GET ERAFLG IF IT'S THERE
|
|
STA ERAFLG ;SAVE IT AS A FLAG
|
|
MVI A,1 ;DIR FILES ONLY
|
|
CALL GETDIR ;LOAD DIRECTORY OF FILES
|
|
JZ PRFNF ;ABORT IF NO FILES
|
|
;
|
|
; MAIN ERASE LOOP
|
|
;
|
|
ERA1:
|
|
PUSH H ;SAVE PTR TO FILE
|
|
CALL PRFN ;PRINT ITS NAME
|
|
SHLD NXTFILE ;SAVE PTR TO NEXT FILE
|
|
POP H ;GET PTR TO THIS FILE
|
|
CALL ROTEST ;TEST FILE PTED TO BY HL FOR R/O
|
|
JRNZ ERA3
|
|
ERAFLG EQU $+1 ;ADDRESS OF FLAG
|
|
MVI A,0 ;2ND BYTE IS FLAG
|
|
CPI 'I' ;IS IT AN INSPECT OPTION?
|
|
JRNZ ERA2 ;SKIP PROMPT IF IT IS NOT
|
|
CALL ERAQ ;ERASE?
|
|
JRNZ ERA3 ;SKIP IF NOT
|
|
ERA2:
|
|
LXI D,FCB1+1 ;COPY INTO FCB1
|
|
MVI B,11 ;11 BYTES
|
|
CALL LDIR
|
|
CALL INITFCB1 ;INIT FCB
|
|
MVI C,19 ;DELETE FILE
|
|
CALL BDOS
|
|
ERA3:
|
|
LHLD NXTFILE ;HL PTS TO NEXT FILE
|
|
MOV A,M ;GET CHAR
|
|
ORA A ;DONE?
|
|
JZ EXIT
|
|
CALL CRLF ;NEW LINE
|
|
JR ERA1
|
|
;
|
|
ENDIF ;ERAON
|
|
;
|
|
;Section 5C
|
|
;Command: LIST
|
|
;Function: Print out specified file on the LST: Device
|
|
;Forms:
|
|
; LIST <afn> Print file (NO Paging)
|
|
;Notes:
|
|
; The flags which apply to TYPE do not take effect with LIST
|
|
;
|
|
IF LTON
|
|
LIST:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WLIST
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
MVI A,0FFH ;TURN ON PRINTER FLAG
|
|
JR TYPE0
|
|
;
|
|
;Section 5D
|
|
;Command: TYPE
|
|
;Function: Print out specified file on the CON: Device
|
|
;Forms:
|
|
; TYPE <afn> Print file
|
|
; TYPE <afn> P Print file with paging flag
|
|
;Notes:
|
|
; The flag PGDFLG defines the letter which toggles the paging
|
|
; facility (P in the forms section above)
|
|
; The flag PGDFLT determines if TYPE is to page by default
|
|
; (PGDFLT=TRUE if TYPE pages by default); combined with
|
|
; PGDFLG, the following events occur --
|
|
; If PGDFLT = TRUE, PGDFLG turns OFF paging
|
|
; If PGDFLT = FALSE, PGDFLG turns ON paging
|
|
;
|
|
TYPE:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WTYPE
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
XRA A ;TURN OFF PRINTER FLAG
|
|
;
|
|
; ENTRY POINT FOR CPR LIST FUNCTION (LIST)
|
|
;
|
|
TYPE0:
|
|
STA PRFLG ;SET FLAG
|
|
LDA FCB2+1 ;GET PAGE FLAG
|
|
STA PGFLG ;SAVE IT AS A FLAG
|
|
MVI A,1 ;SELECT DIR FILES
|
|
CALL GETDIR ;ALLOW AMBIGUOUS FILES
|
|
JZ PRFNF ;NO FILES
|
|
SHLD NXTFILE ;SET PTR TO NEXT FILE
|
|
JR TYPEX2
|
|
TYPEX:
|
|
LHLD NXTFILE ;GET PTR TO NEXT FILE
|
|
MOV A,M ;ANY FILES?
|
|
ORA A
|
|
JZ EXIT
|
|
LDA PRFLG ;CHECK FOR LIST OUTPUT
|
|
ORA A ;0=TYPE
|
|
JRZ TYPEX1
|
|
MVI A,CR ;BOL ON PRINTER
|
|
CALL LCOUT
|
|
MVI A,FF ;FORM FEED THE PRINTER
|
|
CALL LCOUT
|
|
JR TYPEX2
|
|
TYPEX1:
|
|
CALL PAGEBREAK ;PAGE BREAK MESSAGE
|
|
TYPEX2:
|
|
LXI D,FCB1+1 ;COPY INTO FCB1
|
|
MVI B,11 ;11 BYTES
|
|
CALL LDIR
|
|
SHLD NXTFILE ;SET PTR TO NEXT FILE
|
|
CALL INITFCB1 ;INIT FCB1
|
|
MVI C,15 ;OPEN FILE
|
|
CALL BDOS
|
|
INR A ;SET ERROR FLAG
|
|
JZ PRFNF ;ABORT IF ERROR
|
|
MVI A,NLINES-2 ;SET LINE COUNT
|
|
STA PAGCNT
|
|
MVI A,CR ;NEW LINE
|
|
CALL LCOUT
|
|
MVI A,LF
|
|
CALL LCOUT
|
|
LXI B,080H ;SET CHAR POSITION AND TAB COUNT
|
|
; (B=0=TAB, C=080H=CHAR POSITION)
|
|
;
|
|
; MAIN LOOP FOR LOADING NEXT BLOCK
|
|
;
|
|
TYPE2:
|
|
MOV A,C ;GET CHAR COUNT
|
|
CPI 80H
|
|
JRC TYPE3
|
|
PUSH H ;READ NEXT BLOCK
|
|
PUSH B
|
|
LXI D,FCB1 ;PT TO FCB
|
|
MVI C,20 ;READ RECORD
|
|
CALL BDOS
|
|
ORA A ;SET FLAGS
|
|
POP B
|
|
POP H
|
|
JRNZ TYPE7 ;END OF FILE?
|
|
MVI C,0 ;SET CHAR COUNT
|
|
LXI H,TBUFF ;PT TO FIRST CHAR
|
|
;
|
|
; MAIN LOOP FOR PRINTING CHARS IN TBUFF
|
|
;
|
|
TYPE3:
|
|
MOV A,M ;GET NEXT CHAR
|
|
ANI 7FH ;MASK OUT MSB
|
|
CPI 1AH ;END OF FILE (^Z)?
|
|
JRZ TYPE7 ;NEXT FILE IF SO
|
|
;
|
|
; OUTPUT CHAR TO CON: OR LST: DEVICE WITH TABULATION
|
|
;
|
|
CPI CR ;RESET TAB COUNT?
|
|
JRZ TYPE4
|
|
CPI LF ;RESET TAB COUNT?
|
|
JRZ TYPE4
|
|
CPI TAB ;TAB?
|
|
JRZ TYPE5
|
|
;
|
|
; OUTPUT CHAR AND INCREMENT CHAR COUNT
|
|
;
|
|
CALL LCOUT ;OUTPUT CHAR
|
|
JZ TYPEX ;SKIP
|
|
INR B ;INCREMENT TAB COUNT
|
|
JR TYPE6
|
|
;
|
|
; OUTPUT <CR> OR <LF> AND RESET TAB COUNT
|
|
;
|
|
TYPE4:
|
|
CALL LCOUT ;OUTPUT <CR> OR <LF>
|
|
JZ TYPEX ;SKIP
|
|
MVI B,0 ;RESET TAB COUNTER
|
|
JR TYPE6
|
|
;
|
|
; TABULATE
|
|
;
|
|
TYPE5:
|
|
MVI A,' ' ;<SP>
|
|
CALL LCOUT
|
|
JZ TYPEX ;SKIP
|
|
INR B ;INCR POS COUNT
|
|
MOV A,B
|
|
ANI 7
|
|
JRNZ TYPE5
|
|
;
|
|
; CONTINUE PROCESSING
|
|
;
|
|
TYPE6:
|
|
INR C ;INCREMENT CHAR COUNT
|
|
INX H ;PT TO NEXT CHAR
|
|
CALL BREAK ;CHECK FOR ABORT
|
|
JZ TYPEX ;SKIP
|
|
JR TYPE2
|
|
TYPE7:
|
|
LXI D,FCB1 ;CLOSE FILE
|
|
MVI C,16 ;BDOS FUNCTION
|
|
CALL BDOS
|
|
JMP TYPEX
|
|
;
|
|
; SEND OUTPUT TO LST: OR CON:, AS PER THE FLAG
|
|
; RETURN WITH Z IF ABORT
|
|
;
|
|
LCOUT:
|
|
PUSH H ;SAVE REGS
|
|
PUSH D
|
|
PUSH B
|
|
MOV E,A ;CHAR IN E
|
|
MVI C,2 ;OUTPUT TO CON:
|
|
PRFLG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;2ND BYTE IS THE PRINT FLAG
|
|
ORA A ;0=TYPE
|
|
JRZ LC1
|
|
MVI C,5 ;OUTPUT TO LST:
|
|
LC1:
|
|
PUSH D ;SAVE CHAR
|
|
CALL BDOS ;OUTPUT CHAR IN E
|
|
POP D ;GET CHAR
|
|
MOV A,E
|
|
CPI LF
|
|
JRNZ LC2
|
|
LDA PRFLG ;OUTPUT TO LST:?
|
|
ORA A ;NZ = YES
|
|
JRNZ LC2
|
|
;
|
|
; CHECK FOR PAGING
|
|
;
|
|
LXI H,PAGCNT ;COUNT DOWN
|
|
DCR M
|
|
JRNZ LC2 ;JUMP IF NOT END OF PAUSE
|
|
MVI M,NLINES-2 ;REFILL COUNTER
|
|
PGFLG EQU $+1 ;POINTER TO IN-THE-CODE BUFFER
|
|
MVI A,0 ;2ND BYTE IS THE PAGING FLAG
|
|
CPI PGDFLG ;PAGE DEFAULT OVERRIDE OPTION WANTED?
|
|
;
|
|
IF PGDFLT ;IF PAGING IS DEFAULT
|
|
;
|
|
JRZ LC2 ;PGDFLG MEANS NO PAGING
|
|
;
|
|
ELSE
|
|
;
|
|
JRNZ LC2 ;PGDFLG MEANS PAGE
|
|
;
|
|
ENDIF ;PGDFLT
|
|
;
|
|
CALL PAGEBREAK ;PRINT PAGE BREAK MESSAGE
|
|
JR LC3 ;Z TO SKIP
|
|
LC2:
|
|
XRA A ;SET OK
|
|
DCR A ;NZ=OK
|
|
LC3:
|
|
POP B ;RESTORE REGS
|
|
POP D
|
|
POP H
|
|
RET
|
|
;
|
|
; PRINT PAGE BREAK MESSAGE AND GET USER INPUT
|
|
; ABORT IF ^C, RZ IF ^X
|
|
;
|
|
PAGEBREAK:
|
|
PUSH H ;SAVE HL
|
|
CALL PRINT
|
|
DB cr,lf,' Typing',' '+80H
|
|
LXI H,FCB1+1 ;PRINT FILE NAME
|
|
CALL PRFN
|
|
CALL DASH ;PRINT DASH
|
|
CALL CONIN ;GET INPUT
|
|
POP H ;RESTORE HL
|
|
PUSH PSW
|
|
CALL CRLF ;NEW LINE
|
|
POP PSW
|
|
CPI CTRLC ;^C
|
|
JZ EXIT
|
|
CPI CTRLX ;SKIP?
|
|
RET
|
|
;
|
|
ENDIF ;LTON
|
|
;
|
|
;Section 5E
|
|
;Command: REN
|
|
;Function: To change the name of an existing file
|
|
;Forms:
|
|
; REN <New ufn>=<Old ufn> Perform function
|
|
;
|
|
IF RENON
|
|
REN:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WREN
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
;
|
|
;
|
|
; STEP 1: CHECK FOR FILE 2 BEING AMBIGUOUS
|
|
;
|
|
LXI H,FCB2+1 ;CAN'T BE AMBIGUOUS
|
|
CALL AMBCHK1
|
|
;
|
|
; STEP 2: LOG INTO USER AREA
|
|
;
|
|
CALL LOGUSR ;LOG INTO USER AREA OF FCB1
|
|
;
|
|
; STEP 3: SEE IF NEW FILE ALREADY EXISTS
|
|
; EXTEST PERFORMS A NUMBER OF CHECKS:
|
|
; 1) AMBIGUITY
|
|
; 2) R/O
|
|
; 3) IF FILE EXISTS AND NOT R/O, PERMISSION TO DELETE
|
|
;
|
|
CALL EXTEST
|
|
JZ EXIT ;R/O OR NO PERMISSION
|
|
;
|
|
; STEP 4: EXCHANGE FILE NAME FIELDS FOR RENAME
|
|
;
|
|
LXI H,FCB1 ;EXCHANGE NAMES ONLY
|
|
PUSH H ;SAVE PTR
|
|
INX H
|
|
LXI D,FCB2+1
|
|
MVI B,11 ;11 BYTES
|
|
REN1:
|
|
LDAX D ;GET OLD
|
|
MOV C,A
|
|
MOV A,M
|
|
STAX D ;PUT NEW
|
|
MOV M,C
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ REN1
|
|
;
|
|
; STEP 5: SEE IF OLD FILE IS R/O
|
|
;
|
|
CALL SEARF ;LOOK FOR FILE
|
|
JZ PRFNF
|
|
CALL GETSBIT ;GET PTR TO ENTRY IN TBUFF
|
|
XCHG ;HL PTS TO ENTRY
|
|
INX H ;PT TO FN
|
|
CALL ROTEST ;SEE IF FILE IS R/O
|
|
JNZ EXIT
|
|
;
|
|
; STEP 6: RENAME THE FILE
|
|
;
|
|
POP D ;GET PTR TO FCB
|
|
MVI C,23 ;RENAME
|
|
CALL BDOS
|
|
INR A ;SET ZERO FLAG IF ERROR
|
|
JZ PRFNF ;PRINT NO SOURCE FILE MESSAGE
|
|
JMP EXIT
|
|
;
|
|
ENDIF ;RENON
|
|
;
|
|
;Section 5F
|
|
;Command: PROT
|
|
;Function: To set the attributes of a file (R/O and SYS)
|
|
;
|
|
;Form:
|
|
; PROT afn RSI
|
|
;If either R or S are omitted, the file is made R/W or DIR, resp;
|
|
;R and S may be in any order. If I is present, Inspection is enabled.
|
|
;
|
|
IF PROTON
|
|
ATT:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WPROT
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
XRA A ;SET NO INSPECT
|
|
STA INSPECT
|
|
LXI H,0 ;SET R/O AND SYS ATTRIBUTES OFF
|
|
LXI D,FCB2+1 ;PT TO ATTRIBUTES
|
|
MVI B,3 ;3 CHARS MAX
|
|
ATT1:
|
|
LDAX D ;GET CHAR
|
|
INX D ;PT TO NEXT
|
|
CPI 'I' ;INSPECT?
|
|
JRZ ATTI
|
|
CPI 'R' ;SET R/O?
|
|
JRZ ATTR
|
|
CPI 'S' ;SET SYS?
|
|
JRZ ATTS
|
|
ATT2:
|
|
DJNZ ATT1
|
|
JR ATT3
|
|
ATTI:
|
|
STA INSPECT ;SET FLAG
|
|
JR ATT2
|
|
ATTR:
|
|
MVI H,80H ;SET R/O BIT
|
|
JR ATT2
|
|
ATTS:
|
|
MVI L,80H ;SET SYS BIT
|
|
JR ATT2
|
|
ATT3:
|
|
SHLD FATT ;SAVE FILE ATTRIBUTES
|
|
MVI A,1 ;SELECT DIR AND SYS FILES
|
|
CALL GETDIR ;LOAD DIRECTORY
|
|
JZ PRFNF ;NO FILE ERROR
|
|
SHLD NXTFILE ;PT TO NEXT FILE
|
|
JR ATT5
|
|
ATT4:
|
|
LHLD NXTFILE ;PT TO NEXT FILE
|
|
MOV A,M ;END OF LIST?
|
|
ORA A
|
|
JZ EXIT
|
|
CALL CRLF ;NEW LINE
|
|
ATT5:
|
|
PUSH H ;SAVE PTR TO CURRENT FILE
|
|
CALL PRFN ;PRINT ITS NAME
|
|
SHLD NXTFILE ;SAVE PTR TO NEXT FILE
|
|
CALL PRINT
|
|
DB ' Set to R','/'+80H
|
|
LHLD FATT ;GET ATTRIBUTES
|
|
MVI C,'W' ;ASSUME R/W
|
|
MOV A,H ;GET R/O BIT
|
|
ORA A
|
|
JRZ ATT6
|
|
MVI C,'O' ;SET R/O
|
|
ATT6:
|
|
MOV A,C ;GET CHAR
|
|
CALL CONOUT
|
|
MOV A,L ;GET SYS FLAG
|
|
ORA A ;SET FLAG
|
|
JRZ ATT7
|
|
CALL PRINT
|
|
DB ' and SY','S'+80H
|
|
ATT7:
|
|
INSPECT EQU $+1 ;PTR FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;GET INSPECT FLAG
|
|
ORA A ;Z=NO
|
|
POP H ;GET PTR TO CURRENT FILE
|
|
JRZ ATT8
|
|
CALL ERAQ1 ;ASK FOR Y/N
|
|
JRNZ ATT4 ;ADVANCE TO NEXT FILE IF NOT Y
|
|
ATT8:
|
|
LXI D,FCB1+1 ;COPY INTO FCB1
|
|
MVI B,11 ;11 BYTES
|
|
CALL LDIR
|
|
FATT EQU $+1 ;PTR FOR IN-THE-CODE MODIFICATION
|
|
LXI H,0 ;GET ATTRIBUTES
|
|
DCX D ;PT TO SYS BYTE
|
|
DCX D
|
|
MOV A,L ;GET SYS FLAG
|
|
CALL ATTSET ;SET ATTRIBUTE CORRECTLY
|
|
DCX D ;PT TO R/O BYTE
|
|
MOV A,H ;GET R/O FLAG
|
|
CALL ATTSET
|
|
LXI D,FCB1 ;PT TO FCB
|
|
MVI C,30 ;SET ATTRIBUTES
|
|
CALL BDOS
|
|
JR ATT4
|
|
ATTSET:
|
|
ORA A ;0=CLEAR ATTRIBUTE
|
|
JRZ ATTST1
|
|
LDAX D ;GET BYTE
|
|
ORI 80H ;SET ATTRIBUTE
|
|
STAX D
|
|
RET
|
|
ATTST1:
|
|
LDAX D ;GET BYTE
|
|
ANI 7FH ;CLEAR ATTRIBUTE
|
|
STAX D
|
|
RET
|
|
;
|
|
ENDIF ;PROTON
|
|
;
|
|
;Section 5G
|
|
;Command: CP
|
|
;Function: To copy a file from one place to another
|
|
;
|
|
;Form:
|
|
; CP new=old
|
|
;
|
|
IF CPON
|
|
COPY:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WCP
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
;
|
|
; STEP 0: IF NEW IS BLANK, MAKE IT THE SAME NAME AND TYPE AS OLD
|
|
;
|
|
LXI D,FCB1+1 ;PT TO NEW FILE NAME
|
|
LDAX D ;GET FIRST CHAR
|
|
CPI ' ' ;NO NAME?
|
|
JRNZ COPY0
|
|
LXI H,FCB2+1 ;MAKE SAME AS OLD
|
|
MVI B,11 ;11 BYTES
|
|
CALL LDIR
|
|
;
|
|
; STEP 1: SEE IF NEW=OLD AND ABORT IF SO
|
|
;
|
|
COPY0:
|
|
LXI H,FCB1 ;PT TO NEXT
|
|
LXI D,FCB2 ;PT TO OLD
|
|
PUSH H ;SAVE PTRS
|
|
PUSH D
|
|
INX H ;PT TO FILE NAME
|
|
INX D
|
|
MVI B,13 ;COMPARE 13 BYTES
|
|
COPY1:
|
|
LDAX D ;GET OLD
|
|
CMP M ;COMPARE TO NEW
|
|
JRNZ COPY2
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ COPY1
|
|
MVI C,25 ;GET CURRENT DISK
|
|
CALL BDOS
|
|
INR A ;MAKE 1..P
|
|
MOV B,A ;CURRENT DISK IN B
|
|
POP D ;GET PTR TO DN
|
|
POP H
|
|
LDAX D ;GET DISK
|
|
MOV C,A ;... IN C
|
|
ORA A ;CURRENT?
|
|
JRNZ COPY1A
|
|
MOV C,B ;MAKE C CURRENT
|
|
COPY1A:
|
|
MOV A,M ;GET DISK
|
|
ORA A ;CURRENT?
|
|
JRNZ COPY1B
|
|
MOV A,B ;MAKE A CURRENT
|
|
COPY1B:
|
|
CMP C ;SAME DISK ALSO?
|
|
JRNZ COPY3 ;CONTINUE WITH OPERATION
|
|
JR CPERR
|
|
COPY2:
|
|
POP D ;GET PTRS
|
|
POP H
|
|
;
|
|
; STEP 2: SET USER NUMBERS
|
|
;
|
|
COPY3:
|
|
LDA FCB1+13 ;GET NEW USER
|
|
STA USRNEW
|
|
LDA FCB2+13 ;GET OLD USER
|
|
STA USROLD
|
|
;
|
|
; STEP 3: SEE IF OLD FILE EXISTS
|
|
;
|
|
LXI H,OLDFCB ;COPY OLD INTO 2ND FCB
|
|
PUSH H ;SAVE PTR TO 2ND FCB
|
|
XCHG
|
|
MVI B,14 ;14 BYTES
|
|
CALL LDIR
|
|
CALL LOGOLD ;LOG IN USER NUMBER OF OLD FCB
|
|
POP H ;GET PTR TO 2ND FCB
|
|
CALL INITFCB2 ;INIT FCB
|
|
MVI C,17 ;LOOK FOR FILE
|
|
CALL BDOS
|
|
INR A ;CHECK FOR ERROR
|
|
JZ PRFNF ;FILE NOT FOUND
|
|
;
|
|
; STEP 4: SEE IF NEW EXISTS
|
|
;
|
|
CALL LOGNEW ;LOG INTO NEW'S USER AREA
|
|
CALL EXTEST ;TEST
|
|
JZ EXIT ;ERROR EXIT
|
|
;
|
|
; STEP 5: CREATE NEW
|
|
;
|
|
LXI D,FCB1 ;PT TO FCB
|
|
MVI C,22 ;MAKE FILE
|
|
CALL BDOS
|
|
INR A ;ERROR?
|
|
JRNZ COPY4
|
|
;
|
|
; COPY ERROR
|
|
;
|
|
CPERR:
|
|
CALL PRINT
|
|
DB ' Copy','?'+80H
|
|
JMP EXIT
|
|
;
|
|
; STEP 6: OPEN OLD
|
|
;
|
|
COPY4:
|
|
CALL LOGOLD ;GET USER
|
|
LXI H,OLDFCB ;PT TO FCB
|
|
CALL INITFCB2 ;INIT FCB
|
|
MVI C,15 ;OPEN FILE
|
|
CALL BDOS
|
|
;
|
|
; STEP 7: COPY OLD TO NEW WITH BUFFERING
|
|
;
|
|
COPY5:
|
|
CALL LOGOLD ;GET USER
|
|
MVI B,0 ;SET COUNTER
|
|
LXI H,TPA ;SET NEXT ADDRESS TO COPY INTO
|
|
COPY5A:
|
|
PUSH H ;SAVE ADDRESS AND COUNTER
|
|
PUSH B
|
|
LXI D,OLDFCB ;READ BLOCK FROM FILE
|
|
MVI C,20
|
|
CALL BDOS
|
|
POP B ;GET COUNTER AND ADDRESS
|
|
POP D
|
|
ORA A ;OK?
|
|
JRNZ COPY5B
|
|
PUSH B ;SAVE COUNTER
|
|
LXI H,TBUFF ;COPY FROM BUFFER
|
|
MVI B,128 ;128 BYTES
|
|
CALL LDIR
|
|
XCHG ;HL PTS TO NEXT
|
|
POP B ;GET COUNTER
|
|
INR B ;INCREMENT IT
|
|
MOV A,B ;DONE?
|
|
CPI CPBLOCKS ;DONE IF CPBLOCKS LOADED
|
|
JRNZ COPY5A
|
|
COPY5B:
|
|
MOV A,B ;GET COUNT
|
|
ORA A
|
|
JRZ COPY6 ;DONE IF NOTHING LOADED
|
|
PUSH B ;SAVE COUNT
|
|
CALL LOGNEW ;GET USER
|
|
LXI H,TPA ;PT TO TPA
|
|
COPY5C:
|
|
LXI D,TBUFF ;COPY INTO TBUFF
|
|
MVI B,128 ;128 BYTES
|
|
CALL LDIR
|
|
PUSH H ;SAVE PTR TO NEXT
|
|
LXI D,FCB1 ;PT TO FCB
|
|
MVI C,21 ;WRITE BLOCK
|
|
CALL BDOS
|
|
ORA A
|
|
JRNZ CPERR ;COPY ERROR
|
|
POP H ;GET PTR TO NEXT BLOCK
|
|
POP B ;GET COUNT
|
|
DCR B ;COUNT DOWN
|
|
JRZ COPY5 ;GET NEXT
|
|
PUSH B ;SAVE COUNT
|
|
JR COPY5C
|
|
;
|
|
; STEP 8: CLOSE FILES
|
|
;
|
|
COPY6:
|
|
CALL LOGOLD ;GET USER
|
|
LXI D,OLDFCB ;PT TO FCB
|
|
MVI C,16 ;CLOSE FILE
|
|
CALL BDOS
|
|
CALL LOGNEW ;GET USER
|
|
LXI D,FCB1 ;PT TO FCB
|
|
MVI C,16 ;CLOSE FILE
|
|
CALL BDOS
|
|
CALL PRINT
|
|
DB ' Don','e'+80H
|
|
JMP EXIT
|
|
;
|
|
; LOG INTO USER NUMBER OF OLD FILE
|
|
;
|
|
LOGOLD:
|
|
USROLD EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;GET NUMBER
|
|
JMP SETUSR
|
|
;
|
|
; LOG INTO USER NUMBER OF NEW FILE
|
|
;
|
|
LOGNEW:
|
|
USRNEW EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
MVI A,0 ;GET NUMBER
|
|
JMP SETUSR
|
|
;
|
|
ENDIF ;CPON
|
|
;
|
|
;Section 5H
|
|
;Command: PEEK
|
|
;Function: Display memory
|
|
;
|
|
;Form:
|
|
; PEEK startadr - 256 bytes displayed
|
|
; PEEK startadr endadr - range of bytes displayed
|
|
;
|
|
IF PEEKON
|
|
PEEK:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WPEEK
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
LXI H,TBUFF+1 ;FIND FIRST NUMBER
|
|
NXTPEEK EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION
|
|
LXI D,0 ;DEFAULT PEEK ADDRESS IF NONE
|
|
CALL SKSP ;SKIP TO NON-BLANK
|
|
CNZ HEXNUM ;GET START ADDRESS IF ANY (ELSE DEFAULT)
|
|
CALL PRINT
|
|
DB ' Pee','k'+80H
|
|
CALL ADRAT ;PRINT ADDRESS MESSAGE
|
|
PUSH D ;SAVE IT
|
|
LXI B,256 ;COMPUTE END ADDRESS
|
|
XCHG
|
|
DAD B
|
|
XCHG ;END ADDRESS IN DE
|
|
CALL SKSP ;SKIP TO NON-BLANK
|
|
JRZ PEEK1 ;PROCESS
|
|
CALL HEXNUM ;GET 2ND NUMBER IN DE
|
|
PEEK1:
|
|
POP H ;HL IS START ADDRESS, DE IS END ADDRESS
|
|
CALL PEEK2 ;DO PEEK
|
|
SHLD NXTPEEK ;SET CONTINUED PEEK ADDRESS
|
|
JMP EXIT
|
|
;
|
|
; DISPLAY LOOP
|
|
;
|
|
PEEK2:
|
|
MOV A,D ;SEE IF DE<=HL
|
|
CMP H
|
|
RC ;OUT OF BOUNDS
|
|
JRNZ PEEK2A ;HL > DE
|
|
MOV A,E
|
|
CMP L
|
|
RZ
|
|
RC
|
|
PEEK2A:
|
|
CALL CRLF ;NEW LINE
|
|
MOV A,H ;PRINT ADDRESS
|
|
CALL PASHC
|
|
MOV A,L
|
|
CALL PAHC
|
|
CALL DASH ;PRINT LEADER
|
|
MVI B,16 ;16 BYTES TO DISPLAY
|
|
PUSH H ;SAVE START ADDRESS
|
|
PEEK3:
|
|
MOV A,M ;GET NEXT BYTE
|
|
CALL PASHC ;PRINT WITH LEADING SPACE
|
|
INX H ;PT TO NEXT
|
|
DJNZ PEEK3
|
|
POP H ;PT TO FIRST
|
|
MVI B,16 ;16 BYTES
|
|
MVI A,' ' ;SPACE AND FENCE
|
|
CALL CONOUT
|
|
CALL PRINT
|
|
DB FENCE+80H
|
|
PEEK4:
|
|
MOV A,M ;GET NEXT BYTE
|
|
MVI C,'.' ;ASSUME DOT
|
|
ANI 7FH ;MASK IT
|
|
CPI ' ' ;DOT IF LESS THAN SPACE
|
|
JRC PEEK5
|
|
CPI 7FH ;DON'T PRINT DEL
|
|
JRZ PEEK5
|
|
MOV C,A ;CHAR IN C
|
|
PEEK5:
|
|
MOV A,C ;GET CHAR
|
|
CALL CONOUT ;SEND IT
|
|
INX H ;PT TO NEXT
|
|
DJNZ PEEK4
|
|
CALL PRINT ;CLOSING FENCE
|
|
DB FENCE+80H
|
|
CALL BREAK ;ALLOW ABORT
|
|
JR PEEK2
|
|
;
|
|
ENDIF ;PEEKON
|
|
;
|
|
; PRINT A AS 2 HEX CHARS
|
|
; PASHC - LEADING SPACE
|
|
;
|
|
IF PEEKON OR POKEON
|
|
PASHC:
|
|
PUSH PSW ;SAVE A
|
|
CALL PRINT
|
|
DB ' '+80H
|
|
POP PSW
|
|
PAHC:
|
|
PUSH B ;SAVE BC
|
|
MOV C,A ;BYTE IN C
|
|
RRC ;EXCHANGE NYBBLES
|
|
RRC
|
|
RRC
|
|
RRC
|
|
CALL PAH ;PRINT HEX CHAR
|
|
MOV A,C ;GET LOW
|
|
POP B ;RESTORE BC AND FALL THRU TO PAH
|
|
PAH:
|
|
ANI 0FH ;MASK
|
|
ADI '0' ;CONVERT TO ASCII
|
|
CPI '9'+1 ;LETTER?
|
|
JRC PAH1
|
|
ADI 7 ;ADJUST TO LETTER
|
|
PAH1:
|
|
JMP CONOUT
|
|
;
|
|
ENDIF ;PEEKON OR POKEON
|
|
;
|
|
;Section 5I
|
|
;Command: POKE
|
|
;Function: Place Values into Memory
|
|
;
|
|
;Form:
|
|
; POKE startadr val1 val2 ...
|
|
;
|
|
IF POKEON
|
|
POKE:
|
|
;
|
|
; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED
|
|
;
|
|
IF WPOKE
|
|
CALL WHLTST
|
|
ENDIF ;WHEEL APPROVAL
|
|
;
|
|
CALL RETSAVE
|
|
LXI H,TBUFF+1 ;PT TO FIRST CHAR
|
|
CALL SKSP ;SKIP TO NON-BLANK
|
|
JRZ NOARGS ;ARG ERROR
|
|
CALL HEXNUM ;CONVERT TO NUMBER
|
|
CALL PRINT
|
|
DB ' Pok','e'+80H
|
|
CALL ADRAT ;PRINT AT MESSAGE
|
|
;
|
|
; LOOP FOR STORING HEX VALUES SEQUENTIALLY VIA POKE
|
|
;
|
|
POKE1:
|
|
PUSH D ;SAVE ADDRESS
|
|
CALL SKSP ;SKIP TO NON-BLANK
|
|
JZ EXIT ;DONE
|
|
CPI '"' ;QUOTED TEXT?
|
|
JRZ POKE2
|
|
CALL HEXNUM ;GET NUMBER
|
|
MOV A,E ;GET LOW
|
|
POP D ;GET ADDRESS
|
|
STAX D ;STORE NUMBER
|
|
INX D ;PT TO NEXT
|
|
JR POKE1
|
|
;
|
|
; STORE ASCII CHARS
|
|
;
|
|
POKE2:
|
|
POP D ;GET NEXT ADDRESS
|
|
INX H ;PT TO NEXT CHAR
|
|
POKE3:
|
|
MOV A,M ;GET NEXT CHAR
|
|
ORA A ;DONE?
|
|
JZ EXIT
|
|
STAX D ;PUT CHAR
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
JR POKE3
|
|
;
|
|
; No Argument Error
|
|
;
|
|
NOARGS:
|
|
CALL PRINT
|
|
DB ' Arg','?'+80H
|
|
JMP EXIT
|
|
;
|
|
ENDIF ;POKEON
|
|
;
|
|
;Section 5J
|
|
;Command: REG
|
|
;Function: Manipulate Memory Registers
|
|
;
|
|
;Forms:
|
|
; REG D or REG <-- Display Register Value
|
|
; REG Mreg <-- Decrement Register Value
|
|
; REG Preg <-- Increment Register Value
|
|
; REG Sreg value <-- Set Register Value
|
|
;
|
|
IF REGON
|
|
REGCMD:
|
|
LXI H,FCB1+1 ;PT TO FIRST ARG
|
|
MOV A,M ;GET FIRST CHAR
|
|
PUSH PSW ;SAVE CHAR
|
|
CPI 'A' ;ASSUME DIGIT IF LESS THAN 'A'
|
|
JRC REGC1
|
|
INX H ;PT TO DIGIT
|
|
REGC1:
|
|
MOV A,M ;GET DIGIT
|
|
CALL REGPTR ;PT TO REGISTER
|
|
POP PSW ;GET CHAR
|
|
CPI 'S' ;SET?
|
|
JRZ RSET
|
|
CPI 'P' ;PLUS?
|
|
JRZ RINC
|
|
CPI 'M' ;MINUS?
|
|
JRZ RDEC
|
|
;
|
|
; SHOW REGISTER VALUES
|
|
;
|
|
RSHOW:
|
|
XRA A ;SELECT REGISTER 0
|
|
MOV B,A ;COUNTER SET TO 0 IN B
|
|
CALL REGP2 ;HL PTS TO REGISTER 0
|
|
RSHOW1:
|
|
MOV A,B ;GET COUNTER VALUE
|
|
CPI 10
|
|
JZ CRLF ;NEW LINE AND EXIT IF DONE
|
|
CALL PRINT
|
|
DB ' Reg',' '+80H
|
|
MOV A,B ;PRINT REGISTER NUMBER
|
|
ADI '0'
|
|
CALL CONOUT
|
|
CALL PRINT
|
|
DB ' ','='+80H
|
|
PUSH B ;SAVE COUNTER
|
|
CALL REGOUT ;PRINT REGISTER VALUE
|
|
POP B ;GET COUNTER
|
|
INR B ;INCREMENT COUNTER
|
|
MOV A,B ;CHECK FOR NEW LINE
|
|
ANI 3
|
|
CZ CRLF
|
|
INX H ;PT TO NEXT REGISTER
|
|
JR RSHOW1
|
|
;
|
|
; INCREMENT REGISTER VALUE
|
|
; HL PTS TO MEMORY REGISTER ON INPUT
|
|
;
|
|
RINC:
|
|
INR M ;INCREMENT IT
|
|
JR REGOUT ;PRINT RESULT
|
|
;
|
|
; DECREMENT REGISTER VALUE
|
|
; HL PTS TO MEMORY REGISTER ON INPUT
|
|
;
|
|
RDEC:
|
|
DCR M ;DECREMENT VALUE
|
|
JR REGOUT ;PRINT RESULT
|
|
;
|
|
; SET REGISTER VALUE
|
|
; HL PTS TO REGISTER ON INPUT
|
|
;
|
|
RSET:
|
|
LXI D,FCB2+1 ;PT TO VALUE
|
|
MVI B,0 ;INIT VALUE TO ZERO
|
|
RSET1:
|
|
LDAX D ;GET NEXT DIGIT
|
|
INX D ;PT TO NEXT
|
|
SUI '0' ;CONVERT TO BINARY
|
|
JRC RSET2
|
|
CPI 10 ;RANGE?
|
|
JRNC RSET2
|
|
MOV C,A ;DIGIT IN C
|
|
MOV A,B ;MULTIPLY OLD BY 10
|
|
ADD A ;*2
|
|
ADD A ;*4
|
|
ADD B ;*5
|
|
ADD A ;*10
|
|
ADD C ;ADD IN NEW DIGIT
|
|
MOV B,A ;RESULT IN B
|
|
JR RSET1
|
|
RSET2:
|
|
MOV M,B ;SET VALUE
|
|
REGOUT:
|
|
CALL PRINT ;PRINT LEADING SPACE
|
|
DB ' '+80H
|
|
MOV A,M ;GET REGISTER VALUE
|
|
MVI B,100 ;PRINT 100'S
|
|
MVI C,0 ;SET LEADING SPACE FLAG
|
|
CALL DECB ;PRINT 100'S
|
|
MVI B,10 ;PRINT 10'S
|
|
CALL DECB ;PRINT 10'S
|
|
ADI '0' ;PRINT 1'S
|
|
JMP CONOUT
|
|
;
|
|
; SUBTRACT B FROM A UNTIL CARRY, THEN PRINT DIGIT COUNT
|
|
;
|
|
DECB:
|
|
MVI D,'0' ;SET DIGIT
|
|
DECB1:
|
|
SUB B ;SUBTRACT
|
|
JRC DECB2
|
|
INR D ;ADD 1 TO DIGIT CHAR
|
|
JR DECB1
|
|
DECB2:
|
|
ADD B ;ADD BACK IN
|
|
MOV E,A ;SAVE A IN E
|
|
MOV A,D ;GET DIGIT CHAR
|
|
CPI '0' ;LEADING ZERO CHECK
|
|
JRNZ DECB3
|
|
MOV A,C ;ANY LEADING DIGIT YET?
|
|
ORA A
|
|
JRZ DECB4
|
|
DECB3:
|
|
MOV A,D ;GET DIGIT CHAR
|
|
CALL CONOUT ;PRINT IT
|
|
INR C ;SET C<>0 FOR LEADING DIGIT CHECK
|
|
DECB4:
|
|
MOV A,E ;RESTORE A FOR NEXT ROUND
|
|
RET
|
|
|
|
;
|
|
; SET HL TO POINT TO MEMORY REGISTER WHOSE INDEX IS PTED TO BY HL
|
|
; ON INPUT, A CONTAINS REGISTER CHAR
|
|
; ON OUTPUT, HL = ADDRESS OF MEMORY REGISTER (REG 0 ASSUMED IF ERROR)
|
|
;
|
|
REGPTR:
|
|
MVI B,0 ;INIT TO ZERO
|
|
SUI '0' ;CONVERT
|
|
JRC REGP1
|
|
CPI 10 ;RANGE
|
|
JRNC REGP1
|
|
MOV B,A ;VALUE IN B
|
|
REGP1:
|
|
MOV A,B ;VALUE IN A
|
|
REGP2:
|
|
LXI H,Z3MSG+30H ;PT TO MEMORY REGISTERS
|
|
ADD L ;PT TO PROPER REGISTER
|
|
MOV L,A
|
|
MOV A,H
|
|
ACI 0
|
|
MOV H,A ;HL PTS TO REGISTER
|
|
RET
|
|
;
|
|
ENDIF ;REGON
|
|
|
|
;
|
|
;Section 5K
|
|
;Command: WHL/WHLQ
|
|
;Function: Set the Wheel Byte on or off
|
|
;
|
|
;Form:
|
|
; WHL -- turn Wheel Byte OFF
|
|
; WHL password -- turn Wheel Byte ON if password is correct
|
|
; WHLQ -- find out status of Wheel Byte
|
|
;
|
|
IF WHLON
|
|
WHL:
|
|
LXI H,FCB1+1 ;PT TO FIRST CHAR
|
|
MOV A,M ;GET IT
|
|
CPI ' ' ;TURN BYTE OFF IF NO PASSWORD
|
|
JRZ WHLOFF
|
|
LXI D,WHLPASS
|
|
MVI B,8 ;CHECK 8 CHARS
|
|
WHL1:
|
|
LDAX D ;GET CHAR
|
|
CMP M ;COMPARE
|
|
JRNZ WHLMSG
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ WHL1
|
|
;
|
|
; TURN ON WHEEL BYTE
|
|
;
|
|
MVI A,0FFH ;TURN ON WHEEL BYTE
|
|
JR WHLSET
|
|
;
|
|
; TURN OFF WHEEL BYTE
|
|
;
|
|
WHLOFF:
|
|
XRA A ;TURN OFF WHEEL BYTE
|
|
WHLSET:
|
|
STA Z3WHL ;SET WHEEL BYTE AND PRINT MESSAGE
|
|
;
|
|
; PRINT WHEEL BYTE MESSAGE
|
|
;
|
|
WHLMSG:
|
|
CALL PRINT
|
|
DB ' Wheel Byte',' '+80H
|
|
LDA Z3WHL ;GET WHEEL BYTE
|
|
ORA A ;ZERO IS OFF
|
|
JRZ OFFM
|
|
CALL PRINT
|
|
DB 'O','N'+80H
|
|
RET
|
|
OFFM:
|
|
CALL PRINT
|
|
DB 'OF','F'+80H
|
|
RET
|
|
;
|
|
; WHEEL PASSWORD DEFINED FROM SYSRCP.LIB FILE
|
|
;
|
|
DB 'Z'-'@' ;LEADING ^Z IN CASE OF TYPE
|
|
WHLPASS:
|
|
WPASS ;USE MACRO
|
|
;
|
|
ENDIF ;WHLON
|
|
|
|
;
|
|
;Section 5L
|
|
;Command: ECHO
|
|
;Function: Echo Text without Interpretation to Console or Printer
|
|
;
|
|
;Form:
|
|
; ECHO text <-- echo text to console
|
|
; ECHO $text <-- echo text to printer
|
|
;
|
|
; Additionally, if a form feed character is encountered in the
|
|
; output string, no further output will be done, a new line will be
|
|
; issued, and this will be followed by a form feed character. That is:
|
|
;
|
|
; ECHO $text^L
|
|
;
|
|
; will cause "text" to be printed on the printer followed by CR, LF, FF.
|
|
;
|
|
ECHO:
|
|
LXI H,TBUFF+1 ;PT TO FIRST CHAR
|
|
ECHO1:
|
|
MOV A,M ;SKIP LEADING SPACES
|
|
INX H ;PT TO NEXT
|
|
CPI ' '
|
|
JRZ ECHO1
|
|
;
|
|
IF ECHOLST
|
|
MOV B,A ;CHAR IN B
|
|
CPI '$' ;PRINT FLAG?
|
|
JRZ ECHO2
|
|
ENDIF ;ECHOLST
|
|
;
|
|
DCX H ;PT TO CHAR
|
|
;
|
|
; LOOP TO ECHO CHARS
|
|
;
|
|
ECHO2:
|
|
MOV A,M ;GET CHAR
|
|
ORA A ;EOL?
|
|
JRZ ECHO4
|
|
;
|
|
IF ECHOLST
|
|
CPI FF ;FORM FEED?
|
|
JRZ ECHO3
|
|
ENDIF ;ECHOLST
|
|
;
|
|
ECHO2C:
|
|
CALL ECHOUT ;SEND CHAR
|
|
INX H ;PT TO NEXT
|
|
JR ECHO2
|
|
;
|
|
; FORM FEED - SEND NEW LINE FOLLOWED BY FORM FEED IF PRINTER OUTPUT
|
|
;
|
|
IF ECHOLST
|
|
ECHO3:
|
|
MOV A,B ;CHECK FOR PRINTER OUTPUT
|
|
CPI '$'
|
|
JRNZ ECHOFF ;SEND FORM FEED NORMALLY IF NOT PRINTER
|
|
CALL ECHONL ;SEND NEW LINE
|
|
MVI A,FF ;SEND FORM FEED
|
|
JR ECHOUT
|
|
;
|
|
; SEND FORM FEED CHAR TO CONSOLE
|
|
;
|
|
ECHOFF:
|
|
MVI A,FF ;GET CHAR
|
|
JR ECHO2C
|
|
ENDIF ;ECHOLST
|
|
;
|
|
; END OF PRINT LOOP - CHECK FOR PRINTER TERMINATION
|
|
;
|
|
ECHO4:
|
|
IF NOT ECHOLST
|
|
;
|
|
RET
|
|
;
|
|
ELSE
|
|
;
|
|
MOV A,B ;CHECK FOR PRINTER OUTPUT
|
|
CPI '$'
|
|
RNZ ;DONE IF NO PRINTER OUTPUT
|
|
;
|
|
; OUTPUT A NEW LINE
|
|
;
|
|
ECHONL:
|
|
MVI A,CR ;OUTPUT NEW LINE ON PRINTER
|
|
CALL ECHOUT
|
|
MVI A,LF ;FALL THRU TO ECHOUT
|
|
;
|
|
ENDIF ;NOT ECHOLST
|
|
;
|
|
; OUTPUT CHAR TO PRINTER OR CONSOLE
|
|
;
|
|
ECHOUT:
|
|
MOV C,A ;CHAR IN C
|
|
PUSH H ;SAVE HL
|
|
PUSH B ;SAVE BC
|
|
LXI D,0CH-3 ;OFFSET FOR CONSOLE OUTPUT
|
|
;
|
|
IF ECHOLST
|
|
MOV A,B ;CHECK FOR PRINTER
|
|
CPI '$'
|
|
JRNZ ECHOUT1
|
|
INX D ;ADD 3 FOR PRINTER OFFSET
|
|
INX D
|
|
INX D
|
|
;
|
|
ENDIF ;ECHOLST
|
|
;
|
|
; OUTPUT CHAR IN C WITH BIOS OFFSET IN DE
|
|
;
|
|
ECHOUT1:
|
|
CALL BIOUT ;BIOS OUTPUT
|
|
POP B ;RESTORE BC,HL
|
|
POP H
|
|
RET
|
|
|
|
;
|
|
; OUTPUT CHAR IN C TO BIOS WITH OFFSET IN DE
|
|
;
|
|
BIOUT:
|
|
LHLD WBOOT+1 ;GET ADDRESS OF WARM BOOT
|
|
DAD D ;PT TO ROUTINE
|
|
PCHL ;JUMP TO IT
|
|
|
|
;
|
|
; ** SUPPORT UTILITIES **
|
|
;
|
|
|
|
;
|
|
; CHECK FOR USER INPUT; IF ^C, RETURN WITH Z
|
|
;
|
|
BREAK:
|
|
PUSH H ;SAVE REGS
|
|
PUSH D
|
|
PUSH B
|
|
MVI E,0FFH ;GET CHAR IF ANY
|
|
MVI C,6 ;CONSOLE STATUS CHECK
|
|
CALL BDOS
|
|
POP B ;RESTORE REGS
|
|
POP D
|
|
POP H
|
|
CPI CTRLC ;CHECK FOR ABORT
|
|
JZ EXIT ;EXIT
|
|
CPI CTRLX ;SKIP?
|
|
RET
|
|
|
|
;
|
|
; COPY HL TO DE FOR B BYTES
|
|
;
|
|
LDIR:
|
|
MOV A,M ;GET
|
|
STAX D ;PUT
|
|
INX H ;PT TO NEXT
|
|
INX D
|
|
DJNZ LDIR ;LOOP
|
|
RET
|
|
|
|
;
|
|
; PRINT FILE NOT FOUND MESSAGE
|
|
;
|
|
PRFNF:
|
|
CALL PRINT
|
|
DB ' No File','s'+80H
|
|
JMP EXIT
|
|
|
|
;
|
|
; OUTPUT NEW LINE TO CON:
|
|
;
|
|
CRLF:
|
|
MVI A,CR
|
|
CALL CONOUT
|
|
MVI A,LF
|
|
JMP CONOUT
|
|
|
|
;
|
|
; SEARCH FOR FIRST AND NEXT
|
|
;
|
|
SEARF:
|
|
PUSH B ; SAVE COUNTER
|
|
PUSH H ; SAVE HL
|
|
MVI C,17 ; SEARCH FOR FIRST FUNCTION
|
|
SEARF1:
|
|
LXI D,FCB1 ; PT TO FCB
|
|
CALL BDOS
|
|
INR A ; SET ZERO FLAG FOR ERROR RETURN
|
|
POP H ; GET HL
|
|
POP B ; GET COUNTER
|
|
RET
|
|
SEARN:
|
|
PUSH B ; SAVE COUNTER
|
|
PUSH H ; SAVE HL
|
|
MVI C,18 ; SEARCH FOR NEXT FUNCTION
|
|
JR SEARF1
|
|
|
|
;
|
|
; CONSOLE INPUT
|
|
;
|
|
CONIN:
|
|
PUSH H ; SAVE REGS
|
|
PUSH D
|
|
PUSH B
|
|
MVI C,1 ; INPUT
|
|
CALL BDOS
|
|
POP B ; GET REGS
|
|
POP D
|
|
POP H
|
|
ANI 7FH ; MASK MSB
|
|
CPI 61H
|
|
RC
|
|
ANI 5FH ; TO UPPER CASE
|
|
RET
|
|
|
|
;
|
|
; LOG INTO USER AREA CONTAINED IN FCB1
|
|
;
|
|
LOGUSR:
|
|
LDA FCB1+13 ;GET USER NUMBER
|
|
SETUSR:
|
|
MOV E,A
|
|
MVI C,32 ;USE BDOS FCT
|
|
JMP BDOS
|
|
|
|
;
|
|
; PRINT FILE NAME PTED TO BY HL
|
|
;
|
|
PRFN:
|
|
CALL PRINT ;LEADING SPACE
|
|
DB ' '+80H
|
|
MVI B,8 ;8 CHARS
|
|
CALL PRFN1
|
|
MVI A,'.' ;DOT
|
|
CALL CONOUT
|
|
MVI B,3 ;3 CHARS
|
|
PRFN1:
|
|
MOV A,M ; GET CHAR
|
|
INX H ; PT TO NEXT
|
|
CALL CONOUT ; PRINT CHAR
|
|
DJNZ PRFN1 ; COUNT DOWN
|
|
RET
|
|
|
|
;
|
|
; SAVE RETURN ADDRESS
|
|
;
|
|
RETSAVE:
|
|
POP D ; GET RETURN ADDRESS
|
|
POP H ; GET RETURN ADDRESS TO ZCPR3
|
|
SHLD Z3RET ; SAVE IT
|
|
PUSH H ; PUT RETURN ADDRESS TO ZCPR3 BACK
|
|
PUSH D ; PUT RETURN ADDRESS BACK
|
|
RET
|
|
|
|
;
|
|
; EXIT TO ZCPR3
|
|
;
|
|
EXIT:
|
|
Z3RET EQU $+1 ; POINTER TO IN-THE-CODE MODIFICATION
|
|
LXI H,0 ; RETURN ADDRESS
|
|
PCHL ; GOTO ZCPR3
|
|
|
|
;
|
|
; TEST WHEEL BYTE FOR APPROVAL
|
|
; IF WHEEL BYTE IS 0 (OFF), ABORT WITH A MESSAGE (FLUSH RET ADR AND EXIT)
|
|
;
|
|
IF WHEEL ;IF ANY WHEEL OPTION IS RUNNING
|
|
WHLTST:
|
|
LDA Z3WHL ;GET WHEEL BYTE
|
|
ORA A ;ZERO?
|
|
RNZ
|
|
POP PSW ;CLEAR STACK
|
|
CALL PRINT
|
|
DB ' No Whee','l'+80H
|
|
RET
|
|
ENDIF ;WHEEL
|
|
|
|
;
|
|
; PRINT A DASH
|
|
;
|
|
IF LTON OR PEEKON
|
|
DASH:
|
|
CALL PRINT
|
|
DB ' -',' '+80H
|
|
RET
|
|
;
|
|
ENDIF ;LTON OR PEEKON
|
|
;
|
|
; PRINT ADDRESS MESSAGE
|
|
; PRINT ADDRESS IN DE
|
|
;
|
|
IF PEEKON OR POKEON
|
|
ADRAT:
|
|
CALL PRINT
|
|
DB ' at',' '+80H
|
|
MOV A,D ;PRINT HIGH
|
|
CALL PAHC
|
|
MOV A,E ;PRINT LOW
|
|
JMP PAHC
|
|
;
|
|
; EXTRACT HEXADECIMAL NUMBER FROM LINE PTED TO BY HL
|
|
; RETURN WITH VALUE IN DE AND HL PTING TO OFFENDING CHAR
|
|
;
|
|
HEXNUM:
|
|
LXI D,0 ;DE=ACCUMULATED VALUE
|
|
MVI B,5 ;B=CHAR COUNT
|
|
HNUM1:
|
|
MOV A,M ;GET CHAR
|
|
CPI ' '+1 ;DONE?
|
|
RC ;RETURN IF SPACE OR LESS
|
|
INX H ;PT TO NEXT
|
|
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:
|
|
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
|
|
RET
|
|
;
|
|
; NUMBER ERROR
|
|
;
|
|
NUMERR:
|
|
CALL PRINT
|
|
DB ' Num','?'+80H
|
|
JMP EXIT
|
|
;
|
|
; SKIP TO NEXT NON-BLANK
|
|
;
|
|
SKSP:
|
|
MOV A,M ;GET CHAR
|
|
INX H ;PT TO NEXT
|
|
CPI ' ' ;SKIP SPACES
|
|
JRZ SKSP
|
|
DCX H ;PT TO GOOD CHAR
|
|
ORA A ;SET EOL FLAG
|
|
RET
|
|
;
|
|
ENDIF ;PEEKON OR POKEON
|
|
;
|
|
; Test File in FCB for unambiguity and existence, ask user to delete if so
|
|
; Return with Z flag set if R/O or no permission to delete
|
|
;
|
|
IF RENON OR CPON
|
|
EXTEST:
|
|
CALL AMBCHK ;AMBIGUOUS FILE NAMES NOT ALLOWED
|
|
CALL SEARF ;LOOK FOR SPECIFIED FILE
|
|
JRZ EXOK ;OK IF NOT FOUND
|
|
CALL GETSBIT ;POSITION INTO DIR
|
|
INX D ;PT TO FILE NAME
|
|
XCHG ;HL PTS TO FILE NAME
|
|
PUSH H ;SAVE PTR TO FILE NAME
|
|
CALL PRFN ;PRINT FILE NAME
|
|
POP H
|
|
CALL ROTEST ;CHECK FOR R/O
|
|
JRNZ EXER
|
|
CALL ERAQ ;ERASE?
|
|
JRNZ EXER ;RESTART AS ERROR IF NO
|
|
LXI D,FCB1 ;PT TO FCB1
|
|
MVI C,19 ;DELETE FILE
|
|
CALL BDOS
|
|
EXOK:
|
|
XRA A
|
|
DCR A ;NZ = OK
|
|
RET
|
|
EXER:
|
|
XRA A ;ERROR FLAG - FILE IS R/O OR NO PERMISSION
|
|
RET
|
|
|
|
;
|
|
; CHECK FOR AMBIGUOUS FILE NAME IN FCB1
|
|
; RETURN Z IF SO
|
|
;
|
|
AMBCHK:
|
|
LXI H,FCB1+1 ;PT TO FCB
|
|
;
|
|
; CHECK FOR AMBIGUOUS FILE NAME PTED TO BY HL
|
|
;
|
|
AMBCHK1:
|
|
PUSH H
|
|
MVI B,11 ;11 BYTES
|
|
AMB1:
|
|
MOV A,M ;GET CHAR
|
|
ANI 7FH ;MASK
|
|
CPI '?'
|
|
JRZ AMB2
|
|
INX H ;PT TO NEXT
|
|
DJNZ AMB1
|
|
DCR B ;SET NZ FLAG
|
|
POP D
|
|
RET
|
|
AMB2:
|
|
POP H ;PT TO FILE NAME
|
|
CALL PRFN
|
|
CALL PRINT
|
|
DB ' is AF','N'+80H
|
|
JMP EXIT
|
|
;
|
|
ENDIF ;RENON OR CPON
|
|
;
|
|
; CHECK USER TO SEE IF HE APPROVES ERASE OF FILE
|
|
; RETURN WITH Z IF YES
|
|
;
|
|
IF RENON OR CPON OR ERAON OR PROTON
|
|
ERAQ:
|
|
CALL PRINT
|
|
DB ' - Eras','e'+80H
|
|
ERAQ1:
|
|
CALL PRINT
|
|
DB ' (Y/N)?',' '+80H
|
|
CALL CONIN ;GET RESPONSE
|
|
CPI 'Y' ;KEY ON YES
|
|
RET
|
|
;
|
|
ENDIF ;RENON OR CPON OR ERAON OR PROTON
|
|
;
|
|
; TEST FILE PTED TO BY HL FOR R/O
|
|
; NZ IF R/O
|
|
;
|
|
IF RENON OR ERAON OR CPON
|
|
ROTEST:
|
|
PUSH H ;ADVANCE TO R/O BYTE
|
|
LXI B,8 ;PT TO 9TH BYTE
|
|
DAD B
|
|
MOV A,M ;GET IT
|
|
ANI 80H ;MASK BIT
|
|
PUSH PSW
|
|
LXI H,ROMSG
|
|
CNZ PRINT1 ;PRINT IF NZ
|
|
POP PSW ;GET FLAG
|
|
POP H ;GET PTR
|
|
RET
|
|
ROMSG:
|
|
DB ' is R/','O'+80H
|
|
;
|
|
ENDIF ;RENON OR ERAON OR CPON
|
|
;
|
|
; INIT FCB1, RETURN WITH DE PTING TO FCB1
|
|
;
|
|
IF ERAON OR LTON OR CPON
|
|
INITFCB1:
|
|
LXI H,FCB1 ;PT TO FCB
|
|
INITFCB2:
|
|
PUSH H ;SAVE PTR
|
|
LXI B,12 ;PT TO FIRST BYTE
|
|
DAD B
|
|
MVI B,24 ;ZERO 24 BYTES
|
|
XRA A ;ZERO FILL
|
|
CALL FILLP ;FILL MEMORY
|
|
POP D ;PT TO FCB
|
|
RET
|
|
;
|
|
ENDIF ;ERAON OR LTON OR CPON
|
|
;
|
|
; BUFFERS
|
|
;
|
|
NXTFILE:
|
|
DS 2 ;PTR TO NEXT FILE IN LIST
|
|
|
|
;
|
|
; SIZE ERROR TEST
|
|
;
|
|
IF ($ GT (RCP + RCPS*128))
|
|
SIZERR EQU NOVALUE ;RCP IS TOO LARGE FOR BUFFER
|
|
ENDIF
|
|
|
|
;
|
|
; END OF SYS.RCP
|
|
;
|
|
|
|
END
|
|
|