home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
SUBMIT
/
EX15.LBR
/
EX15.AQM
/
EX15.ASM
Wrap
Assembly Source File
|
2000-06-30
|
26KB
|
1,310 lines
;
; EX15.ASM - An enhanced version of EXEC and EX.
;
; START 05-09-82
;
; DATE 10-19-84 *LAST MAJOR CHANGE
;
; HISTORY:
;
; 1.5 10-19-84 Modified NWARM and NCONOT to allow execution of
; EX under other system extensions such as Jim
; Lopushinski's LBRDISK
;
; 1.4 11-20-82 fix for 1.3 modification to put CP/M serial # on
; a page boundary and refresh it on warm starts.
; (Some programs are not subtracting 6 from the
; BDOS+1 location when calculating high memory,
; MBASIC is one of these)
;
; 1.3 11-07-82 fix for software that expects CP/M serial # below
; BDOS JMP address.
;
; 1.2.1 09-16-82 fix for MBASIC execution under EX 1.2 .
;
; 1.2 08-11-82 added '^:' EX runtime re-execute logic function,
; '^?' EX runtime wait for carriage return,
; logic to prevent input/EX buffer overlap,
; logic to insure (Xsub Already Present),
; logic to prevent EX runtime recursion loop,
; and prompt character logic [Larry Steeger]
;
; 1.1 08-06-82 added ';;' EX comment's support,
; '^.' print suppression function,
; '^<...^>' immediate display support,
; '^#' EX message suppression function,
; '^$' default parameter support,
; and '^|' cr,lf generation function [Larry Steeger]
;
; 1.0 08-03-82 corrected $^ error and ^<lowercase> error [Larry Steeger]
;
; ? 06-19-82 added missing TRUE and FALSE equates [Ron Fowler]
;
; ? 05-17-82 corrected last cold boot no active message
;
DATE EQU 1122H ;SET UP DATE
YEAR EQU 82H ;SET UP YEAR
MARK EQU 1 ;SET MARK
VERS EQU 5 ;SET VERSION
;
; EX15.COM is an enhancement of EXEC.COM and EX.COM
;
; Options:
;
; EX <subfile> <parameters> cr
;
; EX cr
;
; ^<?> will give control character <?>
;
; | will be CR
;
; ^| will be CR,LF
;
; ^: will cause EX to re-execute the .SUB file from the beginning
;
; ^? will cause EX to wait for a Carriage Return
; (^C will abort EX at this point also)
;
; ^$ will cause the rest of the line to be treated as a
; set of default parameters separated by blanks to be
; used if the user has not provided one on EX's command line.
;
; ^# will toggle print suppression of EX messages
;
; ^. will start print suppression of all characters
; from .SUB file until a subsequent ^. is encountered
;
; ;; will indicate that the ;; and all characters following it
; until a LF is encountered are not included in EX's
; text buffer
; (i.e. an EX only comment)
;
; ^< will start immediate display of characters from
; the .SUB file until ^> is encountered
; (i.e. display only .SUB input)
;
; $<1-9> will replace parameter<1-9> in text from the command line
;
; $$ will give $
;
; $^ will give ^
;
; $| will give |
;
; |,CR,LF,1AH will eat last from | to end of buffer
;
; ^C from console will abort EX
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
DAY0 SET (DATE AND 0FH)+'0'
DAY1 SET ((LOW DATE) SHR 4)+'0'
MONTH0 SET ((HIGH DATE)AND 0FH)+'0'
MONTH1 SET (DATE SHR 12)+'0'
;
YEAR0 SET (YEAR AND 0FH)+'0'
YEAR1 SET (YEAR SHR 4)+'0'
;
MARK0 SET MARK+'0'
VERS0 SET VERS+'0'
;
BELL EQU 7
CR EQU 0DH
LF EQU 0AH
;
PSUP EQU 80H ;^. PRINT SUPPRESS FLAG
IMON EQU 81H ;^< IMMEDIATE MODE START
IMOFF EQU 82H ;^> IMMEDIATE MODE STOP
MSUP EQU 83H ;^# EX MESSAGE SUPPRESS FLAG
CRWAIT EQU 84H ;^? EX RUNTIME WAIT FOR CR FLAG
REXEC EQU 85H ;^: EX RUNTIME RE-EXECUTE FLAG
;JMPMON EQU 0FEH ;^; EX JMP TO SYSTEM MONITOR
;
WARM EQU 0
BDISK EQU 4
BDOS EQU 5
DFCB EQU 5CH
DBUFF EQU 80H
;
; NOTE: EX15.LIB IS CREATED BY THE EX14.SUB GENERATION PROCESS
;
MACLIB EX15
;
$-PRINT
IF BASE
$+PRINT
;
; START OF EX INITIATOR CODE SEGMENT
;
ORG 100H
;
START: LXI H,0
DAD SP
SHLD CCPSTK ; CCP Stack Ptr
LXI SP,BEGREL ; User stack area
MVI A,0C9H ; (8080 RET)
STA START ; Prevent re-entrance by ZCPR
LXI D,SIGNON ; Logo
CALL PRINT
CALL EXACTV ; Check for recursion
LHLD RELOCL ; Get reloc program length
PUSH H
POP B
PUSH B ; Save length for future use
LHLD BDOS+1 ; Get base
LXI D,-806H ; Get before CCP
DAD D
MOV A,L ; Subtract reloc length
SUB C
MOV E,A
MOV A,H
SBB B
MOV D,A
PUSH D ; Save new top/start to move to
LXI H,BEGREL ; Start of move
OMOVE: MOV A,B
ORA C
JZ MOVEND
DCX B
MOV A,M
STAX D
INX D
INX H
JMP OMOVE
;
MOVEND: POP D ; Get start of moved program
POP B ; Length of move program
PUSH H ; Start of bit map
MOV H,D ; MSB offset
MOV L,E ; LSB offset
OFFLUP: MOV A,B ; Test length
ORA C ; If 0
JZ GOTO ; Jump to relocated program
DCX B ; Decrement count
LDA COUNT
INR A
STA COUNT
ANI 07H
JNZ OFFBIT ; No
XTHL ; Yes, get bit map
MOV A,M ; Get next byte
INX H ; Increment bit map pointer
XTHL ; Save for later
STA BITMAP ; Keep bit offset
OFFBIT: LDA BITMAP
RAL ; Test for offset
STA BITMAP ; Save new byte
JNC NOFSET ; No
DCX D ; Get back to LSB
LDAX D
ADD L
STAX D
INX D ; MSB
LDAX D ; Yes
ADC H ; Add in offset
STAX D ; Put in moved place
NOFSET: INX D ; Increment moved pointer
JMP OFFLUP ; Continue with relocate
;
GOTO: POP D ; Restore stack
DCX H ; Relocate program-1
PUSH H ; Save to use in relocated program
SHLD OUTBUF
INX H ; Get to beginning of relocated program
PUSH H
LXI D,DBUFF+1 ; Terminate command line with CR
PUSH D
LDA DBUFF
MOV L,A
MVI H,0
DAD D
MVI M,CR
LXI H,PRMDMY ; Start at dummy parameter for .SUB file spec
PUSH H
LXI B,PRMPNL+2
XRA A
CALL FILL ; Clear ptr area
POP H
POP D
MVI A,(PRMPNL/2)+1
STA PRMMAX ; Highest parameter # + 1 for .SUB spec
CALL PARMS ; Build pointers for command line parms
LDA DBUFF ; See if .SUB file present
ORA A
JNZ OPENSB ; Open sub file
LXI H,0
SHLD LINES ; Start line counter
MVI A,7FH ; Get buffer length
STA DBUFF-1
LXI H,BEGREL ; Set up output buffer
SHLD INBUF
GETLIN: CALL CRLF
LHLD LINES
INX H
SHLD LINES
CALL DECOUT ; Print line #
MVI E,':' ; Get prompt
CALL OUTCHR
MVI E,' '
CALL OUTCHR
LXI D,DBUFF-1
MVI C,10 ; Read console buffer
CALL BDOS
LXI D,DBUFF
LDAX D ; Get length
MOV B,A
INX D
LHLD INBUF ; Get input pointer
ORA A ; See if end
JZ ENDSTR ; Thats all folks
XCHG
CALL MOVE ;MOVE TO INPUT BUFFER
XCHG
MVI M,CR
INX H
MVI M,LF
INX H
SHLD INBUF
JMP GETLIN
;
OPENSB: LDA DFCB+9
CPI ' '
JNZ OPNSB1
LXI D,DFCB+9
LXI H,SUBNAM ; Move 'SUB' to DFCB file type
MVI B,3
CALL MOVE
OPNSB1: XRA A
STA DFCB+32
LXI D,DFCB
MVI C,15 ; Open file
CALL BDOS
INR A
JNZ READTX
LXI H,NOSBF2
LXI D,DFCB+1
MVI B,8 ; Name length
CALL MOVEFN ; Move file name
MVI B,3 ; Type length
MVI M,'.'
INX H
LXI D,DFCB+9 ; File type pointer
CALL MOVEFN ; Move file type
MVI M,'$' ; End terminator
JMP NOSUB
;
READTX: LHLD INBUF
XCHG
LXI H,80H ; Get sector offset
DAD D
SHLD INBUF
MVI C,26 ; Set DMA address
CALL BDOS
LXI D,DFCB
MVI C,20 ; Read sequential
CALL BDOS
ORA A
JZ READTX ; Read complete .SUB file
LHLD INBUF ; Make sure buffer's terminated
LXI D,-80H ; Get back to end
DAD D
ENDSTR: MVI M,1AH ; EOF character
SHLD ENDBUF ; EOB address
MOV A,L
SUI LOW BEGREL+1 ; See if buffer's empty
MOV A,H
SBI HIGH BEGREL
JC BUFLOW
XRA A
STA IMFLG1
STA IMFLG2
STA PRTFLG
STA OUTCNT
LXI H,1
SHLD LINES
LHLD OUTBUF
SHLD OUTLNE
SHLD BUFSTR
LXI D,BEGREL
MOVSTR: LDAX D
INX D
ANI 7FH ; Make sure no parity
CPI LF
JNZ MOVST0
MOVSTX: CALL INCR
JMP MOVSTR
;
MOVST0: CPI 1AH
JZ SETUP
CPI '|' ; Carriage Return
JNZ MOVST1 ; Nope
PUSH D ; Save old pointer
INX D
INX D
LDAX D ; Get present location+3
POP D ; Get old pointer
CPI 1AH ; End of buffer
JZ SETUP ; Thats all she wrote
MVI A,CR
CALL INCR ; Increment lines for errors
JMP MOVST4
;
MOVST1: MOV C,A
LDA IMFLG1
CPI IMON ; Immediate mode on ?
MOV A,C
JZ MOVST2 ; Yes..skip EX comment processing
CPI ';'
JZ EXCOMM ; Process possible EX comment
MOVST2: CPI '^'
JZ MOVST5 ; Convert control characters
CPI '$'
CZ GTPARM ; Substitute command parameter or control char
MOVST3: STA LCHR
CPI CR ; = CR?
JNZ MOVST4
MOV C,A
LDA OUTCNT
ORA A ; Any char?
MOV A,C
JZ MOVSTR ; No..use input CR only if other non-control
; ... characters in current line
MOVST4: CALL CHRSTR ; Add to buffer
CALL CNTINC ; Increment count
JMP MOVSTR
;
MOVST5: CALL GETCMD ; Validate control characters
CPI ':'
JZ REXC ; Re-execute
; CPI ';'
; JZ JMPMN ; JMP to monitor
CPI '?'
JZ GCRW ; CR wait
CPI '|'
JZ GCRLF ; CR,LF generation
CPI '$'
JZ PRMDEF ; Default parameters' line
CPI '.'
JZ PRTSUP ; Print suppress toggle
CPI '#'
JZ MSGSUP ; Message suppress toggle
CPI '<'
JZ IMPRTY ; Immediate mode start
CPI '>'
JZ IMPRTN ; Immediate mode stop
JMP MOVST3 ; Other control codes
;
REXC: MVI A,REXEC ; Convert '^:' to re-execute flag
JMP MOVST3
;
;JMPMN: MVI A,JMPMON ; Convert '^;' to JMP to Monitor flag
; JMP MOVST3
;
GCRW: MVI A,CRWAIT ; Convert '^?' to CRWAIT flag
JMP MOVST3
;
GCRLF: MVI A,CR ; Generate CR & LF
CALL CHRSTR
MVI A,LF
CALL CHRSTR
STA LCHR
JMP MOVSTR
;
PRMDEF: PUSH H
LXI H,PRMDFP
PUSH H
LXI B,PRMDFL
XRA A
CALL FILL ; Clear ptr table
POP H
MVI A,PRMDFL/2
STA PRMMAX ; Highest parameter #
CALL PARMS ; Build default parameters ptrs
POP H
INX D ; Skip CR
MVI A,LF
JMP MOVSTX ; Continue at EOL
;
EXCOMM: PUSH H
LXI H,LCHR
CMP M ; Double ;?
MOV M,A
POP H
JNZ MOVST3 ; No...continue
MOV C,A
LDA PRTFLG
CPI PSUP
MOV A,C
JZ MOVST3 ; Print suppress
LDA IMFLG1
CPI IMON
MOV A,C
JZ MOVST3 ; Immediate mode
INX H ; Yes..ignore previous ;
PUSH H
LXI H,LCHR
LDA OUTCNT
DCR A ; Drop 1 char
STA OUTCNT
EXCOML: LDAX D ; Ignore characters until EOF or LF
INX D
CPI 1AH ; EOF
JZ EXCOMX
CPI LF ; Line Feed
JNZ EXCOML
MOV M,A
LDA OUTCNT
ORA A ; Any char on this line?
JZ EXCOM2 ; No...skip CR
EXCOM1: POP H ; Yes..force CR
MVI A,CR
CALL CHRSTR
MVI A,LF
JMP MOVSTX ; Continue
;
EXCOM2: POP H
MVI A,LF
JMP MOVSTX ; Continue
;
EXCOMX: POP H
JMP SETUP
;
MSGSUP: MVI A,MSUP ; Convert '^#' to Message Suppress Flag
JMP MOVST3
;
PRTSUP: MVI A,PSUP ; Convert '^.' to Print Suppress Flag
PUSH H
LXI H,PRTFLG
CMP M ; Already on?
JNZ PRTSST ; No...set flag
XRA A ; Yes..clear flag
PRTSST: MOV M,A ; Set/reset flag
POP H
MVI A,PSUP
JMP MOVST3
;
IMPRTY: MVI A,IMON ; Convert '^<' to immediate mode start
STA LCHR
PUSH H
LXI H,IMFLG1
CMP M ; Already on?
POP H
JZ MOVSTR ; Yes..
STA IMFLG1
STA IMFLG2
JMP MOVST3 ; No...
;
IMPRTN: MVI A,IMOFF ; Convert '^>' to Immediate Mode Stop
STA LCHR
PUSH H
LXI H,IMFLG2
CMP M ; Already off?
POP H
JZ MOVSTR ; Yes..
STA IMFLG2
STA IMFLG1
JMP MOVST3 ; No...
;
CHRSTR: PUSH PSW ; Check for input/ex buffer overlap
PUSH D
PUSH H
LHLD ENDBUF
XCHG
POP H
MOV A,L
CMP E
JNZ CHRSTX ; LSB<>
MOV A,H
CMP D
JZ OVERL ; MSB =, overlap will occur; abort EX
;
CHRSTX: POP D ; Add char to EX's buffer
POP PSW
MOV M,A
DCX H
RET
;
EXACTV: LHLD BDOS+1 ; Check for EX recursion
INX H
INX H
INX H ; Skip 1st jump
MVI A,'E'
CMP M
RNZ ; Not 'E'
INX H
MVI A,'X'
CMP M
RNZ ; Not 'X'
INX H
MVI A,0FFH
CMP M
RNZ ; Not 0FFH
LXI D,EXACT
CALL PRINT ; EX already present
CCPRET: LHLD CCPSTK
SPHL
LDA 4
RET ; Return to CCP
;
SETUP: MVI M,0FFH ; Setup end of data
DCX H
MVI M,0FFH
MOV A,L ; Setup EX recur ID, XSUB present, & CP/M S/N
CPI 11 ; 12 bytes on this page?
JNC SETUP1 ; Yes..OK
DCR H ; No...drop down 1 page
SETUP1: MVI L,11 ; Force page boundary for CP/M S/N
MVI M,0FFH ; Setup EX recursion ID
DCX H
MVI M,'X'
DCX H
MVI M,'E'
DCX H
LDA BDOS+2 ; Set up BDOS jump to protect data
MOV M,A
DCX H
LDA BDOS+1
MOV M,A
DCX H
MVI M,JMP
PUSH H
LXI D,-6
DAD D ; Ptr to pseudo CP/M serial #
PUSH H
LHLD BDOS+1
DAD D ; Ptr to real CP/M serial #
POP D
MVI B,6
CALL MOVE ; Setup CP/M serial #
POP H
XTHL ; Get jump address; save top of memory
;
; (SP) Top of Memory Address
; (SP+2) Start of Buffer Address
;
PCHL ; GOTO it
;
; ERROR EXITS
;
GETERR: LXI D,CMDER ; Control character invalid
CALL PRINT
JMP LINE ; Print line # and line and exit
;
NODEFP: LXI D,NOPRM ; Unknown parameter
CALL PRINT
JMP LINE ; Print line # and line and exit
;
PRMERR: LXI D,PMERR
CALL PRINT
JMP LINE ; Print line # and line and exit
;
PRMTOO: LXI D,TOOARG ; Too many parameter arguments
CALL PRINT
LHLD ERRLNE
CALL EPRT ; Print parameter line
JMP CCPRET
;
BUFLOW: LXI D,BUFMTY ; Text buffer empty
CALL PRINT
JMP CCPRET
;
NOSUB: LXI D,NOSBF1 ; .SUB file not found
CALL PRINT
LXI D,NOTHER
CALL PRINT
JMP CCPRET
;
OVERL: LXI D,OVERLP ; Input/EX buffer overlap
CALL PRINT
JMP LINE
;
; SUBROUTINES
;
; CONTROL CODES 0-1FH
; WITH SUPPORT FOR $ . # < >
;
GETCMD: LDAX D ; Get next character
INX D ; Increment pointer
CPI '|'
RZ ; CR,LF generation
CPI 'a'-1 ; Lowercase?
JC GETUPR ; Nope
CPI 'z'+1 ; a-z?
JNC GETERR ; Nope
sui 'a'-'A' ; Get to uppercase
GETUPR: CPI '@' ; 0-1FH control code?
JNC GETCC
; CPI ';'
; RZ ; JMP to monitor
CPI ':'
RZ ; Re-execute
CPI '?'
RZ ; CR wait
CPI '$'
RZ ; Default parameters' line
CPI '.'
RZ ; Print suppress toggle
CPI '#'
RZ ; Message suppress toggle
CPI '<'
RZ ; Immediate mode start
CPI '>'
RZ ; Immediate mode stop
JMP GETERR
GETCC: SUI 40H ; Get control code
RNC
JMP GETERR
;
GTPARM: LDAX D
INX D
CPI '$'
RZ
CPI '^' ; Up arrow
RZ
CPI '|' ; Carriage Return
RZ
CPI '1'
JC PRMERR
CPI '9'+1
JNC PRMERR
SUI '1' ; Get actual # (zero relative)
ADD A ; Double for offset
STA PRMNUM
PUSH D
PUSH H
LXI H,PRMPNT
CPI PRMPNL-1
JNC NOPARM ; > highest #
MOV E,A
MVI D,0
DAD D
MOV E,M ; Get parameter pointer
INX H
MOV D,M
POP H
MOV A,E
ORA D
JZ NOPARM ; No parameter present, try defaults
MOVPRM: LDAX D ; Move parameter to buffer
INX D
ORA A
JZ ENDPAR
MOV M,A
DCX H
JMP MOVPRM
;
ENDPAR: POP D
INX H
MOV A,M
RET
;
NOPARM: PUSH H
LXI H,PRMDFP ; Try default parameters
LDA PRMNUM
CPI PRMDFL-1
JNC NODEFP ; > highest #
MOV E,A
MVI D,0
DAD D
MOV E,M ; Get parameter pointer
INX H
MOV D,M
POP H
MOV A,E
ORA D
JZ NODEFP ; No parameter present
JMP MOVPRM ; Move parameter to buffer
;
MOVEFN: LDAX D
CPI ' ' ; See if space
RZ
MOV M,A
INX D ; Increment pointers
INX H
DCR B
JNZ MOVEFN
RET
;
INCR: PUSH H ; Save output pointer
LHLD LINES
INX H ; Increment line counter
SHLD LINES
LXI H,LCHR ; Clear last character
MVI M,0
LXI H,OUTCNT ; Clear character count
MVI M,0
MOV L,E ; DE = HL
MOV H,D
SHLD BEGLIN
POP H
SHLD OUTLNE ; Save new output line
RET
;
CNTINC: CPI ' ' ; Control character?
RC ; Yes..
ANI 80H ; Special control?
RNZ ; Yes..
LDA PRTFLG
CPI PSUP ; Print suppress flag?
RZ ; Yes..
LDA IMFLG1
CPI IMON ; Immediate mode?
RZ ; Yes..
LDA OUTCNT
INR A
STA OUTCNT
RET
;
PARMS: MVI B,0 ; Clear parameter counter
XCHG
SHLD ERRLNE ; Save in case of error
XCHG
;
PARMSL: LDAX D ; Ignore leading spaces
INX D
CPI CR
JZ ENDLNE
CPI ' '
JZ PARMSL
DCX D
MOV M,E
INX H
MOV M,D
INX H
INX D
INR B ; Count + 1
LDA PRMMAX
CMP B
JC PRMTOO ; Too many arguments
;
ENDPRM: LDAX D ; Get to end of parameter
INX D
CPI CR
JZ ENDLNE
CPI ' '
JNZ ENDPRM
XRA A
DCX D
STAX D ; Terminate parameter
INX D
JMP PARMSL ; Ignore spaces between parameters
ENDLNE: XRA A
DCX D
STAX D ; Terminate last parameter
INX D
MVI A,CR
STAX D
RET
;
PRINT: MVI C,9 ; Print string at (DE)
CALL BDOS
RET
;
EPRT: MOV A,M ; Print parameter line at (HL)
CPI CR
RZ
CPI 0
JNZ EPRT1
MVI A,' '
EPRT1: INX H
PUSH H
MOV E,A
MVI C,2
CALL BDOS
POP H
JMP EPRT
;
CRLF: LXI D,CRLFS ; Print CR/LF
CALL PRINT
RET
;
LINE: LXI D,LINEM ; Print line # and line in error and exit
CALL PRINT
LHLD LINES
CALL DECOUT ; Print line #
CALL CRLF
LHLD BEGLIN
PUSH H ; Save beginning pointer
FINDCR: MOV A,M
INX H
CPI 1AH ; End of buffer
JZ FOUND
CPI CR
JNZ FINDCR
FOUND: MVI M,0 ; End of string
POP H ; Start of string
CALL PRNTHL ; Print bad line
JMP CCPRET ; Thats all folks
;
PRNTHL: MOV A,M ; Print line at (HL)
INX H
ORA A
RZ
MOV E,A
PUSH H ; Save pointer
CALL OUTCHR
POP H ; Get pointer back
JMP PRNTHL
;
OUTCHR: MVI C,2 ; Print character in E
JMP BDOS
;
DECOUT: PUSH H ; Print decimal line number
PUSH D
PUSH B
LXI B,-10 ; Radix for conversion
LXI D,-1 ; This becomes no divided by radix
DX: DAD B ; Subtract 10
INX D
JC DX
LXI B,10
DAD B ; Add radix back in once
XCHG
MOV A,H
ORA L ; Test for zero
CNZ DECOUT ; Recursive call
MOV A,E
ADI '0' ; Convert from BCD to HEX
MOV E,A ; To E for output
MVI C,2
CALL BDOS
POP B ; Restore registers
POP D
POP H
RET
;
MOVE: MOV A,M ; Move string at (HL) to (DE) for length in B
INX H
STAX D
INX D
DCR B
JNZ MOVE
RET
;
FILL: PUSH D ; Fill storage at (HL) with character in A
MOV E,A ; For length in BC
MOV A,B
ORA C
MOV A,E
POP D
RZ
DCX B
MOV M,A
INX H
JMP FILL
;
; WORKING STORAGE AREA
;
SUBNAM: DB 'SUB'
LINEM: DB ' error line # $'
EXACT: DB CR,LF,'(Ex Already Present)$'
BUFMTY DB CR,LF,'Text buffer empty$'
OVERLP: DB CR,LF,'Input/EX Buffer Overlap$'
NOPRM: DB CR,LF,'No parameter or default parameter$'
PMERR: DB CR,LF,'Parameter$'
NOSBF1: DB CR,LF,'File '
NOSBF2: DB 'filename.typ$'
NOTHER: DB ' not there$'
CMDER: DB CR,LF,'Control character$'
TOOARG: DB CR,LF,'Too many arguments - $'
SIGNON: DB 'EX ',MARK0,'.',VERS0
DB ' ',MONTH1,MONTH0,'-',DAY1,DAY0,'-',YEAR1,YEAR0,'$'
CRLFS: DB CR,LF,'$'
;
CCPSTK: DW 0 ; CCP stack ptr
IMFLG1: DB 0 ; = IMON encountered
IMFLG2: DB 0 ; = IMOFF encountered
PRTFLG: DB 0 ; = PSUP on
LCHR: DB 0 ; Last character read
PRMMAX: DB 0 ; Highest parameter #
PRMNUM: DB 0 ; Current $<1-9> number * 2 (zero relative)
ERRLNE: DW 0
BITMAP: DB 0 ; Present offset bit's
COUNT: DB 0FFH ; Present offset bit count
BEGLIN: DW BEGREL ; Beginning of old line pointer
LINES: DW 1
INBUF: DW BEGREL
ENDBUF: DW 0 ; End of input buffer
OUTCNT: DB 0
OUTLNE: DW 0
OUTBUF: DW 0
BUFSTR: DW 0
RELOCL: DW 0 ; Length of reloc program (filled in by SID)
PRMDFP: ; Default parameter ptrs
REPT 9
DW 0
ENDM
PRMDFL EQU $-PRMDFP
PRMDMY: DW 0 ; Dummy parameter for .SUB file spec
PRMPNT: ; Command line parameter ptrs
REPT 9
DW 0
ENDM
PRMPNL EQU $-PRMPNT
PATCH: ; Patch area
REPT 32
DB 'p'
ENDM
REPT 30
DW 0
ENDM
;
; Ensure 8 byte boundary for REL.UTL (RELS.UTL)
;
?PLOC SET $
IF (?PLOC MOD 8) GT 0
?PLOC SET (?PLOC AND 0FFF8H)+8 ; Get next 8 byte boundary
ORG ?PLOC
ENDIF
;
BEGREL: DS 0 ; Reloc program starts here (also used as buffer)
;
ENDIF
;
; End of EX initiator code segment
;
$-PRINT
IF NOT BASE
$+PRINT
;
; Start of EX relocated code segment
;
ORG REL
;
EX: POP H ; Get top of memory
SHLD MEMTOP
POP H ; Get start of buffer
SHLD REVBUF
SHLD SAVBUF
MOV A,M
CPI MSUP ; 1st char = Message Suppress?
JNZ EX1 ; No...
DCX H ; Yes..skip character
SHLD REVBUF
STA MSUPFL ; Set initial flag
EX1: LXI SP,MEMTOP
LHLD WARM+1
SHLD WARMPT
LXI D,BSWARM
MVI B,12
CALL MOVE ; Move BIOS jumps
LHLD WARMPT
XCHG
LXI H,LOCJMP
MVI B,12
CALL MOVE ; Move new BIOS jumps to BIOS area
;
; EX RUNTIME BIOS INTERCEPT ROUTINES
;
NWARM: LXI SP,MEMTOP
LHLD REVBUF ; See if we're at buffers end
MOV A,M
CPI 0FFH ; Test it
JZ WARMR ; Real warm start return
MVI A,0FFH ; Set Warm Boot switch for reinit in
STA BOOTED ; ... NCONOT routine
LXI H,STARTM ; Tell user we're still here
CALL PMSG ; ...
JMP BSWARM ; Go do Warm Boot
;
; JMP TABLE TO OVERLAY BIOS
;
LOCJMP: JMP NWARM ; WARM
JMP BCONST ; CONST
JMP NCONIN ; CONIN
JMP NCONOT ; CONOT
;
; CONSOLE INPUT INTERCEPT ROUTINE
;
NCONIN:
LXI H,0
DAD SP ; Save return stack level
SHLD CONSTK
LXI H,MEMTOP ; Set user stack
NCONNL: CALL BCONST ; Get console status
ORA A
JZ GETBUF ; Get character from buffer
CALL BCONIN ; Get character
CPI 'C'-40H ; See if terminate character
JZ EXABRT
CPI 'S'-40H ; 13H
JNZ NCONEX
CALL BCONIN ; Wait for next character
ANI 7FH
LHLD REVBUF
INX H
MOV M,A
SHLD REVBUF
MVI A,'S'-40H ; 13H
NCONEX: LHLD CONSTK ; Restore caller's stack
SPHL
RET
;
GETBUF: LDA PSUPFL ; Set Print Suppress flag for NCONOT
STA OUTFLG
CALL GETCHR ; Get next character
; CPI JMPMON ; JMP to monitor?
; JZ JPMON ; Yes..do it
CPI REXEC ; Re-execute?
JZ REXECR ; Yes..reset buffer ptr
CPI CRWAIT ; CR wait?
JZ CRWRTN ; Yes..wait for CR
CPI MSUP ; Message Suppress flag?
JZ MSUPCK ; Yes..toggle flag
CPI PSUP ; Print Suppress ?
JZ PSUPCK ; Yes..toggle flag
CPI IMON ; Immediate Mode start ?
JZ IMFLGS ; Yes..set flag
CPI IMOFF ; Immediate Mode stop?
JZ IMFLGS ; Yes..reset flag
CPI CR ; CR?
JNZ GETEXT ; No...exit
XRA A
STA OUTFLG ; Yes..reset Print Suppression
MVI A,CR
GETEXT: MOV C,A
LDA IMFLG
CPI IMON ; Immediate Mode ?
MOV A,C
JNZ NCONEX ; No...return to caller with char
CALL BCONOT ; Yes..immediate echo to console
JMP NCONNL ; ... Loop until IMOFF
;
REXECR: LHLD SAVBUF ; Start at top of buffer again
SHLD REVBUF
XRA A
STA IMFLG ; Reset all flags
STA PSUPFL
STA MSUPFL
JMP NCONNL ; ... Loop until ^C
;
CRWRTN: CALL BCONST ; Wait for char
JZ CRWRTN
CALL BCONIN
CPI 'C'-40H
JZ EXABRT ; = ^C
CPI CR
JZ CRWRTX ; = CR
MVI C,BELL
CALL BCONOT ; <> CR
JMP CRWRTN
;
CRWRTX: MOV C,A ; Echo CR/LF
CALL NCONOT
MVI C,LF
CALL NCONOT
JMP GETBUF
;
PSUPCK: LXI H,PSUPFL
CMP M
JNZ PSUPST ; Set flags if not equal
XRA A ; Else reset flags
PSUPST: MOV M,A ; Set/reset Saved Flag
JMP GETBUF ; And get next character (sets EXEC flag)
;
MSUPCK: LXI H,MSUPFL
CMP M
JNZ MSUPST ; Set flags if not equal
XRA A ; Else reset flag
MSUPST: MOV M,A ; Set/reset flag
JMP GETBUF ; And get next character
;
IMFLGS: STA IMFLG ; Set/reset Immediate Mode flag
JMP GETBUF ; Get next character
;
; CONSOLE OUTPUT INTERCEPT ROUTINE
;
NCONOT: LDA OUTFLG ; Print suppression?
ORA A
JNZ NCN1 ; Yes...ignore echo
MOV A,C
STA PMCHR
CALL BCONOT
NCN1: LDA BOOTED
ORA A
RZ
XRA A
STA BOOTED
LHLD MEMTOP
SHLD BDOS+1
PUSH H ; Restore CP/M S/N
LXI D,-6 ;
DAD D ; HL = BDOS + 0
XTHL ; (SP) = Pseudo BDOS + 0; HL = Pseudo BDOS + 6
INX H ; +1
MOV E,M ; Get BDOS+6
INX H ;
MOV D,M ;
XCHG ; HL = BDOS+6
LXI D,-6 ;
DAD D ; HL = BDOS+0
POP D ; DE = Pseudo BDOS+0
MVI B,6 ; Length of S/N
CALL MOVE ;
RET
;
GETCHR: LHLD REVBUF
MOV A,M
DCX H
SHLD REVBUF
CPI 0FFH ; EOB?
RNZ ; No...return
LHLD REVBUF
INX H ; Point to EOB
SHLD REVBUF
CALL MOVBAK ; Move jumps back
LHLD MEMTOP ; See if BDOS+1 = MEMTOP
XCHG
LHLD BDOS+1
MOV A,E
SUB L
MOV A,D
SBB H
JNZ EXEND ; Don't replace BDOS jump
INX D ; Get to BDOS jump
LDAX D
MOV L,A ; LSB
INX D
LDAX D
MOV H,A
SHLD BDOS+1
EXEND: CALL PMCHRS
LXI H,DONEM ; Tell user we're done
CALL PMSG
LHLD CONSTK ; Get old stack
SPHL
JMP BCONIN
;
; ^C ABORT EXIT
;
EXABRT: LXI SP,MEMTOP ; ^C aborts EX
LXI H,ABORTD
CALL PMSG
JMP WARMX
;
WARMR: CALL PMCHRS
LXI H,DONEM ; End message
CALL PMSG
;
WARMX: CALL MOVBAK ; Move jumps back
JMP WARM
;
; SUBROUTINES
;
MOVBAK: LHLD WARMPT ; Move old jump table back to BIOS
XCHG
LXI H,BSWARM
MVI B,12
CALL MOVE
CALL F121 ; CALL 1.2.1 FIX FOR MBASIC 1.1.2
RET
;
MOVE: MOV A,M ; Move string from (HL) to (DE) for length in B
INX H
STAX D
INX D
DCR B
JNZ MOVE
RET
;
PMCHRS: LDA PMCHR ; Set prompt char only if special character
CPI ' '+1
RC
CPI '0'
JC PMCHRX
CPI '9'+1
RC
CPI 'A'
JC PMCHRX
CPI 'Z'+1
RC
CPI 'a'
JC PMCHRX
CPI 'z'+1
RC
PMCHRX: STA DONEC
RET
;
PMSG: LDA MSUPFL ; Print message at (HL)
CPI MSUP ; Messages suppressed?
RZ ; Yes..exit
PUSH H
PMSGL: POP H
MOV A,M
CPI '$' ; EOM?
RZ ; Yes..exit
INX H
PUSH H
MOV C,A
CALL BCONOT
JMP PMSGL
;
F121: LXI H,BSWARM ; Ensure only BIOS 1.1.2
LXI D,NWARM ; calls from now on 1.1.2
MVI B,3 ; for programs 1.1.2
CALL MOVE ; that may have 1.1.2
LXI H,BCONIN ; copied our 1.1.2
LXI D,NCONIN ; addresses as 1.1.2
MVI B,3 ; if they were 1.1.2
CALL MOVE ; in the bios. 1.1.2
LXI H,BCONOT ; (MBASIC does this) 1.1.2
LXI D,NCONOT ; 1.1.2
MVI B,3 ; 1.1.2
CALL MOVE ; 1.1.2
RET ; 1.1.2
;
; WORKING STORAGE AREA
;
ABORTD: DB CR,LF,'>>>Ex Aborted<<<',CR,LF,'$'
STARTM: DB CR,LF,'(Ex Active)$'
DONEM: DB CR,LF,'(Ex Completed)',CR,LF
DONEC: DB '>$'
;
REPT 10
DW 0
ENDM
MEMTOP: DW 0
REVBUF: DW 0
SAVBUF: DW 0
WARMPT: DW 0
;
; ORIGINAL BIOS JMP TABLE
;
BSWARM: JMP $
BCONST: JMP $
BCONIN: JMP $
BCONOT: JMP $
;
PMCHR: DB 0
PSUPFL: DB 0
BOOTED: DB 0
OUTFLG: DB 0
IMFLG: DB 0
MSUPFL: DB 0
CONSTK: DW 0
; DB 'BDOS>'
;BDOSVE: DW 0
;
?PLEN SET $
IF (?PLEN MOD 8) GT 0
?PLEN SET (?PLEN AND 0FFF8H)+8 ; Get next boundary
ENDIF
;
DRVERL EQU ?PLEN
;
DRVL8 EQU DRVERL/8 ; Length of relocation bit map
ORG DRVERL
;
ENDIF
;
; END OF EX RELOCATED CODE SEGMENT
;
END
; that may have 1.1.2
LXI H,BCONIN ; copied our 1.1.2
LXI D,NCONIN ; addresses as 1.1.2
MVI B,3 ; if they