home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols200
/
vol276
/
zex.mac
< prev
next >
Wrap
Text File
|
1994-07-13
|
42KB
|
1,959 lines
.Z80
ASEG
;
;
; program: zex
; author: richard conn (derived from ex, which was written by someone else)
; version: 3.0
; date: 8 mar 84
; previous versions: none
;
;Modified by Bob Logan for assembly by M80 & Z80 codes 25/4/85
;
VERS EQU 30
ZEXADR EQU 0DB00H ;address of zex running module CHANGE THIS to suit
; uour own system (needs to be 400h below ZCPR3)
;
; zcpr3 definitions
;
MACLIB Z3BASE.LIB
;
; offsets to zcpr3 environment descriptor elements
;
EPOFF EQU 9 ;external path data
MCOFF EQU 24 ;command line data
;
; general equates
;
BELL EQU 7
CTRLZ EQU 1AH ;^z
DELAY EQU 6000H ;delay constant for timer loop
BS EQU 'H'-'@' ;backspace
CR EQU 0DH
LF EQU 0AH
;
; zex monitor command bytes
;
PSUP EQU 80H ;^. print suppress flag
IMON EQU 81H ;^< immediate mode start
IMOFF EQU 82H ;^> immediate mode stop
MSUP EQU 83H ;^# zex message suppress flag
CRWAIT EQU 84H ;^? zex runtime wait for cr flag
REXEC EQU 85H ;^: zex runtime re-execute flag
CRBWAIT EQU 86H ;^/ zex runtime ring bell and wait for cr flag
RNG EQU 87H ;^* ZEX RUNTIME RING BELL
UICH EQU 88H ;^" user input command char sequence
IPS EQU 89H ;^& false if print suppress
;
; cp/m constants
;
WARM EQU 0
BDISK EQU 4
BDOS EQU 5
DFCB EQU 5CH
BUFF EQU 80H
; start of zex initiator code segment
ORG 100H
; .PHASE 100H
; external ZCPR3 Environment Descriptor
JP start
db 'Z3ENV' ;this is a ZCPR3 Utility
db 1 ;external Environment Descriptor
z3eadr:
dw z3env
start:
LD HL,(z3eadr) ;pt to ZCPR3 environment
; start of Program -- Initialize ZCPR3 Environment
call z3init ;initialize the ZCPR3 Env
JP START0
;
; initial command line area
;
DB 0FFH ;size of command line
DBUFF: DB 0FFH ;size of buffer
DS 100H ;space for command line
;
; start of zex
;
START0:
DB 0 ;replaced with ret to prevent reentry
LD A,(DFCB+1) ;check for help request
CP '/' ;help?
JP Z,HELP
LD (CCPSTK),SP ;ccp stack ptr
LD SP,CCPSTK ;user stack area
LD A,0C9H ; (8080 ret)
LD (START),A ;prevent re-entrance by zcpr
LD HL,BUFF ;copy input line into dbuff
LD DE,DBUFF
LD BC,128 ;size of buffer
LDIR
LD DE,SIGNON ;logo
CALL PRINT
CALL ZEXACTV ;check for recursion
CALL ZRELOC ;relocate zex module
CALL ZPARMS ;extract parameters from command line
LD A,(DFCB+1) ;check to see if sub file present
CP ' ' ;<sp>=no
PUSH AF ;save flag
CALL NZ,OPENSB ;open and load zex file if present or abort
POP AF ;get flag
CALL Z,INPUTSB ;input commands from user
;
; hl now points to byte after loaded text
;
CALL ZMCL ;store rest of multiple command line
CALL ZLINES ;copy and process command lines
;
; set up for zex execution and run; hl pts to bottom of data area
;
PUSH HL ;save ptr to end of data
LD HL,(RELSTRT) ;get ptr to start of zex
LD (GOADR),HL ;set address to run to
DEC HL ;pt to start of data area
LD (Z3MSG+09H),HL ;set address of next char for zex processing
LD (Z3MSG+0BH),HL ;set address of first char for zex processing
LD A,0FFH ;set zex running flag
LD (Z3MSG+08H),A ;zex is now running
POP HL ;hl is ptr to end of data
LD (HL),A ;set up end of data
DEC HL
LD A,(BDOS+2) ;set up bdos jump to protect data
LD (HL),A
DEC HL
LD A,(BDOS+1)
LD (HL),A
DEC HL
LD (HL),0C3H ;sim jump
LD (BDOS+1),HL ;set new bdos address
LD HL,0 ;assume no multiple commands
LD A,(MCAVAIL) ;get flag
OR A ;0=none
JP Z,GOTOZEX ;no multiple commands, so bc=0
LD HL,(MCADR) ;get address of multiple command buffer
;
; zex monitor entry parameters --
; hl address of multiple command buffer or 0 if none
;
GOTOZEX:
DB 0C3H
GOADR: DW 0
;
; init zcpr3 environment
;
Z3INIT:
PUSH HL ;save ptr to environment
LD DE,MCOFF ;offset to cl data
ADD HL,DE
LD E,(HL) ;get cl address
INC HL
LD D,(HL)
INC HL ;get cl size
LD A,(HL)
OR D ;if all three values are 0, then no command line
OR E
LD (MCAVAIL),A ;set available flag
EX DE,HL ;hl pts to cl
LD (MCADR),HL
POP HL ;get ptr to environment
LD DE,EPOFF ;offset to external path data
ADD HL,DE
LD E,(HL) ;get external path address
INC HL
LD D,(HL)
LD A,D ;check for any
OR E
LD (EPAVAIL),A ;set available flag
EX DE,HL
LD (EPADR),HL ;set address
RET
;
; z3init buffers
;
INTPATH: ;internal path
DB 1,0 ;disk a, user 0
DB 0,0 ;end of path
MCAVAIL: ;multiple command line data
DB 0
MCADR:
DW 0
EPAVAIL: ;external path data
DB 0
EPADR:
DW 0
;
; print help message for zex
;
HELP:
LD DE,SIGNON ;print banner
CALL PRINT
LD HL,HMSG ;print message
CALL HPRINT
LD C,1 ;get char
CALL BDOS
CP 'C'-'@' ;^c?
RET Z
LD DE,CRLFS
CALL PRINT
LD DE,SIGNON
CALL PRINT
LD HL,HMSG0
CALL HPRINT
LD C,1 ;get char
CALL BDOS
CP 'C'-'@' ;^c?
RET Z
LD DE,CRLFS
CALL PRINT
LD DE,SIGNON
CALL PRINT
LD HL,HMSG1
HPRINT:
LD A,(HL) ;get char
OR A ;done?
RET Z
INC HL ;pt to next
PUSH HL ;save ptr
LD E,A ;char in e
LD C,2 ;console output
CALL BDOS
POP HL ;get ptr
JR HPRINT
HMSG:
DB CR,LF,LF
DB 'ZEX is an indirect command file processing facility, similar'
DB CR,LF,'to the standard CP/M SUBMIT facility and the other '
DB 'ZCPR2'
DB CR,LF,'indirect command file processing facility, SUB2.'
DB CR,LF,'The major difference between the SUBMIT-like programs'
DB CR,LF,'and ZEX is that ZEX is memory-based, storing a command'
DB CR,LF,'processor and the interpreted command file itself in'
DB CR,LF,'memory, just under ZCPR2.'
DB CR,LF,LF
DB 'There is a basic tradeoff to be considered when using ZEX'
DB CR,LF,'as opposed to SUB2. Since ZEX is memory-based, it '
DB 'offers'
DB CR,LF,'the advantage of greatly increased operating speed '
DB 'over'
DB CR,LF,'SUB2. Also, ZEX intercepts all input unless user '
DB 'input'
DB CR,LF,'is explicitly enabled (the ^" command), in which case'
DB ' the user'
DB CR,LF,'is allowed to enter text from his console during a '
DB 'ZEX run.'
DB CR,LF,'SUB2, on the other hand, inputs from the command file'
DB ' only'
DB CR,LF,'at the command line prompt unless XSUB is active. ZEX'
DB ' acts like'
DB CR,LF,'SUB2 and XSUB combined. The only bad feature of ZEX is'
DB ' that'
DB CR,LF,'ZEX significantly shortens the TPA work area, so '
DB 'programs which'
DB CR,LF,'require a lot of memory may have trouble running under'
DB ' ZEX.'
DB CR,LF,'This is why SUB2 is provided to the ZCPR2 user along '
DB 'with ZEX.'
DB CR,LF,LF,'Strike Any Key to Continue, ^C to Abort - ',0
HMSG0:
DB CR
DB LF,LF,'ZEX is invoked by one of the following command lines --'
DB CR,LF
DB CR,LF,' ZEX <subfile> <parameters>'
DB CR,LF,'or'
DB CR,LF,' ZEX'
DB CR,LF
DB CR,LF,'The first form executes the indicated command file'
DB CR,LF,'(<subfile> may be of type ZEX or SUB, and if a ZEX and'
DB ' SUB both'
DB CR,LF,'exist, the ZEX file is used), passing to it the '
DB 'indicated '
DB CR,LF,'parameters, similar to the way SUBMIT is used.'
DB CR,LF
DB CR,LF,'The second form allows the user to enter a series of '
DB 'commands.'
DB CR,LF,'ZEX presents the user with a prompt like "n:", where'
DB CR,LF,'n is a line number, and the user may enter any command'
DB CR,LF,'line. Input is terminated by simply striking the'
DB CR,LF,'RETURN key.'
DB CR,LF,LF,'ZEX can be aborted by ^C from console.'
DB CR,LF,LF,'The following screen displays the ZEX control codes.'
DB CR,LF,LF,'Strike Any Key to Continue, ^C to Abort - ',0
HMSG1:
DB CR,LF,LF
DB ' **** ZEX Embedded Command Processing Facility ****'
DB CR,LF,LF
DB 'ZEX supports an enhanced command processing facility which '
DB 'includes the'
DB CR,LF,'following escaped character commands which may be'
DB CR,LF,'embedded in the text of the command file or user'
DB CR,LF,'input and will be executed after the command run begins'
DB ' --'
DB CR,LF
DB CR,LF,' Cmd Meaning Cmd Meaning'
DB CR,LF,' | insert <CR> ^| insert <CR> <LF>'
DB CR,LF,' ^: rerun command file ^. suppress print of chars'
DB CR,LF,' ^# toggle ZEX msgs ^$ define default params'
DB CR,LF,' ^? wait for user <CR> ^/ ring and wait for <CR>'
DB CR,LF,' ^* ring bell ^" allow user input'
DB CR,LF,' ^< display chars only ^> stop display'
DB CR,LF,' ;; zex comment $n 1<=n<=9 for param'
DB CR,LF,' $$ =$ $^ =^'
DB CR,LF,' $| =| ^c insert ctrl char c'
DB CR,LF,LF,LF,LF,0
;
; relocate zex module into high memory just below zcpr2
;
ZRELOC: ;*****
LD HL,REST
LD BC,RELE
LD DE,ZEXADR
PUSH DE ;save load address
LDIR
POP HL ;get back load address in hl
LD (RELSTRT),HL ;save ptr
DEC HL ;relocate program-1
LD (OUTBUF),HL ;save ptr to byte in front of relocated program
RET
;
; get parameters from command line
; terminate each parameter with a binary zero, and set pointers
; to each parameter
;
ZPARMS:
LD DE,DBUFF ;terminate command line with cr
LD A,(DE) ;get char count
INC DE ;pt to first char
PUSH DE
LD L,A ;hl = number of chars in line
LD H,0
ADD HL,DE ;pt to after last char
LD (HL),CR ;store <cr>
LD HL,PRMDMY ;start at dummy parameter for .sub file spec
PUSH HL
LD BC,PRMPNL+2
XOR A
CALL FILL ;clear ptr area
POP HL ;get ptr to pointer for parameter 0
POP DE ;get ptr to first char in line
LD A,PRMPNL/2+1 ;number of parameters possible, max
LD (PRMMAX),A ;highest parameter # + 1 for .SUB SPEC
;
; parameter extraction routine hl pts to first param ptr, de pts to line
;
PARMS:
LD B,0 ;clear parameter counter
LD (ERRLNE),DE ;save in case of error
;
PARMSL:
LD A,(DE) ;ignore leading spaces
INC DE
CP CR
JR Z,ENDLNE
CP ' '
JR Z,PARMSL
DEC DE ;back up to 1st char
LD (HL),E ;save address in table
INC HL
LD (HL),D
INC HL
INC B ;count+1
LD A,(PRMMAX)
CP B
JP C,PRMTOO ;too many arguments
;
ENDPRM:
LD A,(DE) ;go to end of parameter
INC DE
CP CR
JR Z,ENDLNE
CP ' ' ;skip until <sp>
JR NZ,ENDPRM
XOR A ;a=0 to terminate param
DEC DE ;pt to <sp> following param
LD (DE),A ;terminate parameter
INC DE ;pt to char after <sp>
JR PARMSL ;ignore spaces between parameters
ENDLNE:
XOR A ;store zero after last parameter
DEC DE ;pt to cr
LD (DE),A ;terminate last parameter
INC DE ;pt to after last param
LD A,CR ;store ending cr
LD (DE),A
RET
;
; input command lines from user
;
INPUTSB:
LD HL,0
LD (LINES),HL ;start line counter
LD A,0FFH ;set buffer length
LD (DBUFF-1),A
LD HL,BEGREL ;set up output buffer
LD (INBUF),HL
GETLIN:
CALL CRLF
LD HL,(LINES)
INC HL
LD (LINES),HL
CALL DECOUT ;print line #
LD E,':' ;get prompt
CALL OUTCHR
LD E,' '
CALL OUTCHR
LD DE,DBUFF-1
LD C,10 ;read console buffer
CALL BDOS
LD DE,DBUFF
LD A,(DE) ;get length
LD B,A
INC DE
LD HL,(INBUF) ;get input pointer
OR A ;see if end
RET Z ;done with input
EX DE,HL
CALL MOVE ;move to input buffer
EX DE,HL
LD (HL),CR
INC HL
LD (HL),LF
INC HL
LD (INBUF),HL
JR GETLIN
;
; open and load sub file
;
OPENSB:
CALL PUTUD ;save user/disk
;
; set up to read zex file
;
LD DE,DFCB+9
LD HL,ZEXNAM ;move 'sub' to dfcb file type
LD BC,3
LDIR
XOR A ;zero cr field
LD (DFCB+32),A
LD DE,BUFF ;set dma address
LD C,26 ;set dma
CALL BDOS
LD DE,DFCB
LD HL,INTPATH ;pt to internal path
LD A,(EPAVAIL) ;external paths available?
OR A ;0=no
JR Z,OSB1 ;use internal path
LD HL,(EPADR) ;pt to external path
OSB1:
PUSH HL ;save path ptr
CALL FNDFILE ;look for file along path and say if it is found
POP HL ;get path ptr
JP NZ,READSB
;
; zex file not found -- set up to read sub file
;
PUSH HL ;save path ptr
CALL GETUD ;restore user/disk
LD DE,DFCB+9 ;set type to sub
LD HL,SUBNAM
LD BC,3
LDIR
XOR A ;zero cr field
LD (DFCB+32),A
POP HL ;pt to path
LD DE,DFCB ;pt to fcb
CALL FNDFILE ;look for file
JP NZ,READSB
RSBERR:
CALL GETUD ;restore user/disk
LD HL,NOSBF2
LD DE,DFCB+1
LD B,8 ;name length
CALL MOVEFN ;move file name
LD B,3 ;type length
LD (HL),'.'
INC HL
LD DE,DFCB+9 ;file type pointer
CALL MOVEFN ;move file type
LD (HL),'$' ;end terminater
JP NOSUB
;*
;* FNDFILE -- LOOK FOR FILE ALONG ZCPR3 PATH
;* INPUT PARAMETERS: HL = BASE ADDRESS OF PATH, DE = PTR TO FCB OF FILE
;* OUTPUT PARAMETERS: A=0 AND ZERO FLAG SET IF NOT FOUND, NZ IF FOUND
;*
FNDFILE:
LD (PATH),HL ;save path base address
LD C,17 ;search for first
CALL BENTRY ;look for file
INC A ;set flag
JP NZ,FF5 ;found it -- return found flag
EX DE,HL ;hl=fcb ptr
LD (FCBPTR),HL ;save it
LD HL,(PATH) ;pt to path for failure possibility
LD C,32 ;get current user
LD E,0FFH
CALL BENTRY
LD (TMPUSR),A ;save it for later
;
; main search loop
;
FF1:
LD A,(HL) ;get drive
AND 7FH ;mask msb
OR A ;0=done=command not found
JR NZ,FF2 ;no error abort?
;
; file not found error
;
XOR A ;zero flag means not found
RET
;
; look for command in directory pted to by hl; drive in a
;
FF2:
LD E,A ;disk in e
CP '$' ;current disk?
JR NZ,FF3 ;skip default drive selection if so
LD A,(BDISK) ;get default user/disk
AND 0FH ;mask for default disk
INC A ;prep for following dcr a
LD E,A ;disk number in e
FF3:
DEC E ;adjust path 1 to 0 for a, etc
LD C,14 ;select disk fct
CALL BENTRY ;select drive
INC HL ;pt to user number
LD A,(HL) ;get user number
AND 7FH ;mask out msb
INC HL ;pt to next entry in path
PUSH HL ;save ptr
LD E,A ;save in e
CP '$' ;match?
JR NZ,FF4 ;do not select current user if so
LD A,(TMPUSR) ;get original user number
LD E,A ;select user
FF4:
LD C,32
CALL BENTRY
LD HL,(FCBPTR) ;get ptr to fcb
EX DE,HL ;... in de
LD C,17 ;search for first
CALL BENTRY ;look for file
POP HL ;get ptr to next path entry
INC A ;set flag
JR Z,FF1 ;continue path search if search failed
;
; file found -- perform system test and proceed if approved
;
FF5:
LD A,0FFH ;set ok return
OR A
RET
;
; bdos routine
;
BENTRY:
PUSH HL ;save regs
PUSH DE
PUSH BC
CALL BDOS
POP BC ;get regs
POP DE
POP HL
RET
;* BUFFERS
FCBPTR:
DS 2 ;pointer to fcb for file search
TMPUSR:
DS 1 ;current user number
PATH:
DS 2 ;base address of path
;
; putud -- save away current user/disk
; getud -- restore current user/disk
;
PUTUD:
LD E,0FFH ;get current user
LD C,32 ;bdos
CALL BDOS
LD (CUSER),A ;save current user away
LD C,25 ;get current disk
CALL BDOS
LD (CDISK),A
RET
GETUD:
LD A,(CDISK) ;get current disk
LD E,A ;... in e
LD C,14 ;select disk
CALL BDOS
LD A,(CUSER) ;get current user
LD E,A ;... in e
LD C,32 ;select user
CALL BDOS
RET
CDISK:
DS 1 ;current disk number
CUSER:
DS 1 ;current user number
;
; open and read sub file
;
READSB:
LD C,15 ;open file
CALL BDOS ;bdos
INC A ;error?
JP Z,RSBERR
;
; read in and store sub file
;
READTX:
LD HL,(INBUF) ;get ptr to next byte
EX DE,HL ;set ptr in de
LD HL,80H ;get sector offset
ADD HL,DE ;hl pts to following block to be read, de pts to
LD (INBUF),HL ; block to read; save ptr to following block
LD C,26 ;set dma address
CALL BDOS
LD DE,DFCB
LD C,20 ;read sequential
CALL BDOS
OR A
JR Z,READTX ;read complete .sub file
CALL GETUD ;restore current user/disk
LD HL,(INBUF) ;make sure buffer's terminated
LD DE,-100H ;pt to first byte of last block read
ADD HL,DE
LD B,80H ;look at at most 80h bytes
SKIP1A:
LD A,(HL) ;get byte
CP CTRLZ ;eof?
JR Z,SKIP1B
INC HL ;pt to next
DEC B ;count down
JR NZ,SKIP1A
; hl now points to after last valid char in file
SKIP1B:
LD (INBUF),HL ;set ptr
RET ;done with no error
;
; this part of the code stores the rest of the command line as part of the
; command file for zcpr2; on entry, hl pts to next available byte
;
ZMCL:
EX DE,HL ;buffer pted to by de
LD HL,(MCADR) ;get base address of multiple command line
LD A,(HL) ;get low
INC HL
LD H,(HL) ;get high
LD L,A ;hl pts to next char in multiple command line
EX DE,HL ;de pts to next char in command line, hl pts to buf end
LD A,(MCAVAIL) ;multiple commands enabled?
OR A ;0=no
JR Z,ENDSTR ;terminate file; hl pts to next byte
LD A,(DE) ;get first byte
LD B,A ;save first byte in b
XOR A ;a=0
LD (DE),A ;clear command line
INC DE ;pt to next byte
LD A,B ;get first byte
CP ';' ;separation char?
JR NZ,CMCMD1 ;process if not
;
; loop to store rest of multiple command line into loaded file
;
CMCMD:
LD A,(DE) ;get byte from line
CMCMD1:
OR A ;eol if zero
JR Z,CMEND ;read in file; hl pts to next available byte
LD (HL),A ;store byte
INC HL ;pt to next
INC DE
JR CMCMD
CMEND:
LD (HL),CR ;store <cr> <lf>
INC HL
LD (HL),LF
INC HL ;pt to next available byte
;
; mark end of buffer and continue
;
ENDSTR:
LD (HL),1AH ;eof character
LD (ENDBUF),HL ;eob address
LD A,L
SUB LOW BEGREL+1 ;see if buffer's empty
LD A,H
SBC A,HIGH BEGREL
JP C,BUFLOW
RET
;
; copy and process command lines, placing final command line form under zex
; return with hl pting to next available byte in memory buffer under zex
;
ZLINES:
XOR A
LD (IMFLG1),A
LD (IMFLG2),A
LD (PRTFLG),A
LD (OUTCNT),A
LD HL,1
LD (LINES),HL ;set line count
LD HL,(OUTBUF) ;pt to byte just below loaded zex
LD (OUTLNE),HL
LD (BUFSTR),HL
LD DE,BEGREL ;pt to first byte of command buffer
;
; main copy loop to copy buffer at begrel to just under zex with processing
;
MOVSTR:
LD A,(DE) ;get next command byte
INC DE ;pt to following
AND 7FH ;make sure no parity
CP LF ;new line?
JR NZ,MOVST0
;
; new line -- don't store <lf> and increment line count
;
MOVSTX:
CALL INCR ;increment line count
JR MOVSTR ;continue
;
; begin character processing
; a contains char, de pts to byte after char, hl pts to next buffer pos
;
MOVST0:
CP 1AH ;end of input?
RET Z ;done if so
CP '|' ;carriage return?
JR NZ,MOVST1 ;nope
;
; process carriage return form (|)
;
PUSH DE ;save old pointer
INC DE ;look for eof after | (pt to lf)
INC DE ;pt to possible eof
LD A,(DE) ;get present location+2
POP DE ;get old pointer
CP 1AH ;end of buffer
RET Z ;end, so no following <cr>
LD A,CR ;make char a <cr>
CALL INCR ;increment lines for errors
JR MOVST4 ;store <cr> in a
;
; check for non-cr forms
; at this point, de pts to next char in line and hl pts to next
; byte in buffer (moving down)
;
MOVST1:
LD C,A ;save char in c
LD A,(IMFLG1)
CP IMON ;immediate mode on ?
LD A,C ;get char back
JR Z,MOVST2 ;yes..skip zex comment processing
CP ';' ;first ';'?
JP Z,EXCOMM ;process possible zex comment
MOVST2:
CP '^' ;control char?
JR Z,MOVST5 ;convert control characters
CP '$' ;parameter or control char?
CALL Z,GTPARM ;substitute command parameter or control char.
MOVST3:
LD (LCHR),A ;save last char entered
CP CR ;=cr?
JR NZ,MOVST4
LD C,A ;save char temporarily
LD A,(OUTCNT) ;get char output flag
OR A ;any char?
LD A,C
JR Z,MOVSTR ;no..use input cr only if other non-control
; characters in current line
; place char in buffer
; char in a, hl pts to buffer loc
;
MOVST4:
CALL CHRSTR ;add to buffer
CALL CNTINC ;increment count
JR MOVSTR
;
; prefix was an uparrow (^), so process control chars
;
MOVST5:
CALL GETCMD ;validate control characters
CP ':'
JR Z,REXC ;re-execute
CP '?'
JR Z,GCRW ;cr wait
CP '/'
JR Z,GCRBW ;ring bell and wait for <cr>
CP '"'
JR Z,UISET ;user input
CP '*'
JR Z,GRNG ;continually ring bell while waiting for <cr>
CP '|'
JR Z,GCRLF ;cr,lf generation
CP '$'
JR Z,PRMDEF ;default parameters' line
CP '.'
JP Z,PRTSUP ;print suppress toggle
CP '#'
JP Z,MSGSUP ;message suppress toggle
CP '<'
JP Z,IMPRTY ;immediate mode start
CP '>'
JP Z,IMPRTN ;immediate mode stop
CP '&'
JR Z,IFPSUP ;print suppress during false if
MVST3: JR MOVST3 ;other control codes
;
IFPSUP:
LD A,IPS ;convert '^&' to if print suppress flag
JR MVST3
;
REXC:
LD A,REXEC ;convert '^:' to re-execute flag
JR MVST3
;
GCRW:
LD A,CRWAIT ;convert '^?' to crwait flag
JR MVST3
;
GCRBW:
LD A,CRBWAIT ;convert '^/' to crbwait flag
JR MVST3
;
; allow user input from now on, but first skip out rest of line
;
UISET:
LD A,(DE) ;get next char
AND 7FH ;mask it
CP LF ;done?
JR Z,UISET1
CP 1AH ;eof?
JR Z,UISET1
INC DE ;pt to next char
JR UISET ;continue skipping
UISET1:
LD A,UICH ;control char
JR MVST3
;
GRNG:
LD A,RNG ;convert '^*' TO RNG FLAG
JR MVST3
;
GCRLF:
LD A,CR ;generate cr & lf
CALL CHRSTR
LD A,LF
CALL CHRSTR
LD (LCHR),A
JP MOVSTR
;
PRMDEF:
PUSH HL
LD HL,PRMDFP
PUSH HL
LD BC,PRMDFL
XOR A
CALL FILL ;clear ptr table
POP HL
LD A,PRMDFL/2
LD (PRMMAX),A ;highest parameter #
CALL PARMS ;build default parameters ptrs
POP HL
INC DE ;skip cr
LD A,LF
JP MOVSTX ;continue at eol
;
; check to see if previous char was also a ; and flush as zex comment if so
;
EXCOMM:
PUSH HL
LD HL,LCHR ;pt to previous char
CP (HL) ; double ;?
LD (HL),A ;store current char as previous char
POP HL
JP NZ,MOVST3 ;no...continue
LD C,A ;save char
LD A,(PRTFLG)
CP PSUP
LD A,C
JP Z,MOVST3 ;print suppress
LD A,(IMFLG1)
CP IMON
LD A,C
JP Z,MOVST3 ;immediate mode
INC HL ;yes..ignore previous ;
PUSH HL
LD HL,LCHR
LD A,(OUTCNT)
DEC A ;drop 1 char.
LD (OUTCNT),A
EXCOML:
LD A,(DE) ;ignore characters until eof or lf
INC DE
CP 1AH ;eof
JR Z,EXCOMX
CP LF ;line feed
JR NZ,EXCOML
LD (HL),A
LD A,(OUTCNT)
OR A ;any char. on this line?
JR Z,EXCOM2 ;no...skip cr
EXCOM1:
POP HL ;yes..force cr
LD A,CR
CALL CHRSTR
LD A,LF
JP MOVSTX ;continue
;
EXCOM2:
POP HL
LD A,LF
JP MOVSTX ;continue
;
EXCOMX:
POP HL
RET ;return to main flow, with hl pting to next byte
;
MSGSUP:
LD A,MSUP ;convert '^#' to message suppress flag
JP MOVST3
;
PRTSUP:
LD A,PSUP ;convert '^.' to print suppress flag
PUSH HL
LD HL,PRTFLG
CP (HL) ;already on?
JR NZ,PRTSST ;no...set flag
XOR A ;yes..clear flag
PRTSST:
LD (HL),A ;set/reset flag
POP HL
LD A,PSUP
JP MOVST3
;
IMPRTY:
LD A,IMON ;convert '^<' to immediate mode start
LD (LCHR),A
PUSH HL
LD HL,IMFLG1
CP (HL) ;already on?
POP HL
JP Z,MOVSTR ;yes..
LD (IMFLG1),A
LD (IMFLG2),A
JP MOVST3 ;no...
;
IMPRTN:
LD A,IMOFF ;convert '^>' to immediate mode stop
LD (LCHR),A
PUSH HL
LD HL,IMFLG2
CP (HL) ;already off?
POP HL
JP Z,MOVSTR ;yes..
LD (IMFLG2),A
LD (IMFLG1),A
JP MOVST3 ;no...
;
; place char in buffer; a=char, hl pts to buffer loc
;
CHRSTR:
PUSH AF ;check for input/zex buffer overlap
PUSH DE
PUSH HL
LD HL,(ENDBUF)
EX DE,HL
POP HL
LD A,L
CP E
JR NZ,CHRSTX ;lsb<>
LD A,H
CP D
JP Z,OVERL ;msb=, overlap will occur/abort zex
;
; add char to zex's buffer
;
CHRSTX:
POP DE ;add char. to zex's buffer
POP AF
LD (HL),A ;store char
DEC HL ;pt to next location (moving down)
RET
;
; check to see if zex is already active, and abort if so
;
ZEXACTV:
LD A,(Z3MSG+08H) ;zex running?
OR A ;0 if no
RET Z
LD DE,ZEXACT
CALL PRINT ;zex already present
;
; abort and return to zcpr2
;
CCPRET:
LD SP,(CCPSTK) ;restore stack
RET ;return to ccp
;
; error exits
;
GETERR:
LD DE,CMDER ;control character invalid
CALL PRINT
JP LINE ;print line # and line and exit
;
NUMERR:
LD DE,NONUM ;excessive number
CALL PRINT
JP LINE ;print line # and line and exit
;
PRMERR:
LD DE,PMERR
CALL PRINT
JP LINE ;print line # and line and exit
;
PRMTOO:
LD DE,TOOARG ;too many parameter arguments
CALL PRINT
LD HL,(ERRLNE)
CALL EPRT ;print parameter line
JR CCPRET
;
BUFLOW:
LD DE,BUFMTY ;text buffer empty
CALL PRINT
JR CCPRET
;
NOSUB:
LD DE,NOSBF1 ;.sub file not found
CALL PRINT
LD DE,NOTHER
CALL PRINT
JR CCPRET
;
OVERL:
LD DE,OVERLP ;input/zex buffer overlap
CALL PRINT
JP LINE
;
; subroutines
;
; control codes 0-1fh
; with support for $ . # < >
;
GETCMD:
LD A,(DE) ;get next character
INC DE ;increment pointer
CP '|'
RET Z ;cr,lf generation
CP 'a'-1 ;lowercase?
JR C,GETUPR ;nope
CP 'z'+1 ;a-z?
JP NC,GETERR ;nope
SUB 'a'-'A' ;get to uppercase
GETUPR:
CP '@' ;0-1fh control code?
JR NC,GETCC
CP ':'
RET Z ;re-execute
CP '?'
RET Z ;cr wait
CP '/'
RET Z ;cr wait and ring bell
CP '*'
RET Z ;ring bell
CP '"'
RET Z ;user input
CP '$'
RET Z ;default parameters' line
CP '.'
RET Z ;print suppress toggle
CP '#'
RET Z ;message suppress toggle
CP '<'
RET Z ;immediate mode start
CP '>'
RET Z ;immediate mode stop
CP '&'
RET Z ;false if print suppress
JP GETERR
GETCC:
SUB '@' ;get control code
RET NC
JP GETERR
;
; extract parameter element whose $n specification is pointed to by de
; de pts to char after the $
; buffer to place resulting parameter is pted to by hl
;
GTPARM:
LD A,(DE) ;get char after the $
INC DE ;pt to next char
CP '$' ;if double $, then store as $
RET Z
CP '^' ;up arrow
RET Z
CP '|' ;carriage return
RET Z
CP '1' ;check for valid digit (1-9)
JP C,PRMERR
CP '9'+1 ;range error?
JP NC,PRMERR
SUB '1' ;get actual # (zero relative)
ADD A,A ;double for offset
LD (PRMNUM),A
PUSH DE ;save ptrs
PUSH HL
LD HL,PRMPNT ;pt to parameter ptr table
CP PRMPNL-1 ;parameter number within range?
JP NC,NOPARM ;> highest #
LD E,A
LD D,0
ADD HL,DE
LD E,(HL) ;get parameter pointer
INC HL
LD D,(HL)
POP HL ;restore ptr to next byte in output buffer below zex
LD A,E ;any param?
OR D
JR Z,NOPARM ;no parameter present, try defaults
;
; move parameter pted to by de into buffer below zex, 1st byte pted to by hl
;
MOVPRM:
LD A,(DE) ;get parameter char
INC DE ;pt to next
OR A ;done?
JP Z,ENDPAR
CALL CHRSTR ;store chars
JR MOVPRM
;
; parameter placed in memory -- continue
;
ENDPAR:
POP DE ;get ptr to next char in line
POP AF ;clear stack
JP MOVSTR ;resume processing
;
; no parameter pted to
;
NOPARM:
PUSH HL ;save ptr to next byte in buffer below zex
LD HL,PRMDFP ;try default parameters
LD A,(PRMNUM)
CP PRMDFL-1
JP NC,NUMERR ;> highest #
LD E,A
LD D,0
ADD HL,DE
LD E,(HL) ;get parameter pointer
INC HL
LD D,(HL)
POP HL
LD A,E
OR D
JR NZ,MOVPRM ;move parameter into buffer
JR ENDPAR ;resume with no parameter
;
MOVEFN:
LD A,(DE)
CP ' ' ;see if space
RET Z
LD (HL),A
INC DE ;increment pointers
INC HL
DJNZ MOVEFN
RET
;
; increment line count, and affect only hl (must not affect a)
;
INCR:
PUSH HL ;save output pointer
LD HL,(LINES)
INC HL ;increment line counter
LD (LINES),HL
LD HL,LCHR ;clear last character
LD (HL),0
LD HL,OUTCNT ;clear character count
LD (HL),0
LD L,E ;de=hl
LD H,D
LD (BEGLIN),HL
POP HL
LD (OUTLNE),HL ;save new output line
RET
;
CNTINC:
CP ' ' ;control character?
RET C ;yes..
CP UICH ;user input char?
JR Z,CNTIN1
AND 80H ;special control?
RET NZ ;yes..
LD A,(PRTFLG)
CP PSUP ;print suppress flag?
RET Z ;yes..
LD A,(IMFLG1)
CP IMON ;immediate mode?
RET Z ;yes..
CNTIN1:
LD A,(OUTCNT)
INC A
LD (OUTCNT),A
RET
;
PRINT:
LD C,9 ;print string at (de)
JP BDOS
;
EPRT:
LD A,(HL) ;print parameter line at (hl)
CP CR
RET Z
CP 0
JR NZ,EPRT1
LD A,' '
EPRT1:
INC HL
PUSH HL
LD E,A
LD C,2
CALL BDOS
POP HL
JR EPRT
;
CRLF:
LD DE,CRLFS ;print cr/lf
JP PRINT
;
LINE:
LD DE,LINEM ;print line # and line in error and exit
CALL PRINT
LD HL,(LINES)
CALL DECOUT ;print line #
CALL CRLF
LD HL,(BEGLIN)
PUSH HL ;save begging pointer
FINDCR:
LD A,(HL)
INC HL
CP 1AH ;end of buffer
JR Z,FOUND
CP CR
JR NZ,FINDCR
FOUND:
LD (HL),0 ;end of string
POP HL ;start of string
CALL PRNTHL ;print bad line
JP CCPRET ;thats all folks
;
PRNTHL:
LD A,(HL) ;print line at (hl)
INC HL
OR A
RET Z
LD E,A
PUSH HL ;save pointer
CALL OUTCHR
POP HL ;get pointer back
JR PRNTHL
;
OUTCHR:
LD C,2 ;print character in e
JP BDOS
;
DECOUT:
PUSH HL ;print decimal line number
PUSH DE
PUSH BC
LD BC,-10 ;radix for conversion
LD DE,-1 ;this becomes no divided by radix
DX:
ADD HL,BC ;subtract 10
INC DE
JP C,DX
LD BC,10
ADD HL,BC ;add radix back in once
EX DE,HL
LD A,H
OR L ;test for zero
CALL NZ,DECOUT ;recursive call
LD A,E
ADD A,'0' ;convert from bcd to hex
LD E,A ;to e for output
LD C,2
CALL BDOS
POP BC ;restore registers
POP DE
POP HL
RET
;
MOVE:
LD A,(HL) ;move string at (hl) to (de) for length in b
INC HL
LD (DE),A
INC DE
DJNZ MOVE
RET
;
FILL:
PUSH DE ; fill storage at (hl) with character in a
LD E,A ; for length in bc
LD A,B
OR C
LD A,E
POP DE
RET Z
DEC BC
LD (HL),A
INC HL
JR FILL
;
; working storage area
;
SUBNAM:
DB 'SUB'
ZEXNAM:
DB 'ZEX'
LINEM:
DB ' Error Line # $'
ZEXACT:
DB CR,LF,' ZEX Already Present$'
BUFMTY:
DB CR,LF,'Text Buffer Empty$'
OVERLP:
DB CR,LF,'Input/ZEX Buffer Overlap$'
NONUM:
DB CR,LF,'Parameter Number out of range$'
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 'ZEX, Version '
DB VERS/10+'0','.',(VERS MOD 10)+'0','$'
CRLFS:
DB CR,LF,'$'
;
DS 80 ;stack space
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
RELSTRT:
DW 0
OUTBUF:
DW 0
BUFSTR:
DW 0
RELOCL:
DW 0 ;length of reloc program (filled in by sid)
PRMDFP: ;default parameter ptrs
DS 18
PRMDFL EQU $-PRMDFP
PRMDMY:
DW 0 ;dummy parameter for .sub file spec.
PRMPNT: ;command line parameter ptrs
DS 18
PRMPNL EQU $-PRMPNT
PATCH: ;patch area
REPT 32
DB 'p'
ENDM
DS 60
BEGREL:
DS 0 ;reloc program starts here (also used as buffer)
;
; ENDIF
;
; end of zex initiator code segment
;
;*****************¬ STAR╘ O╞ ZE╪ *******************
;
; start of zex relocated code segment
; hl pts to multiple command buffer
; or hl=0 if no multiple commands
;
REST EQU $
; .DEPHASE
.PHASE ZEXADR ;????
ZEX:
LD (EXMBASE),HL ;save address of mcl buffer
LD HL,(Z3MSG+09H) ;pt to next char
LD A,(HL) ;get 1st char
CP MSUP ;1st char=message suppress?
JR NZ,ZEX1 ;no...
DEC HL ;yes..skip character
LD (Z3MSG+09H),HL ;set ptr to next char
LD (MSUPFL),A ;set initial flag
ZEX1:
LD SP,MEMTOP
LD HL,(BDOS+1) ;get warm jump for standard ccp
LD (MEMTOP),HL ;set ptr to top of memory
INC HL
LD E,(HL) ;de = address of actual bdos
INC HL
LD D,(HL)
EX DE,HL ;hl pts to actual bdos
LD A,H ;subtract 8 for ccp entry point
SUB 8
LD H,A
LD L,3 ;set up for warm ccp jump
LD (CCPJMP),HL
LD HL,(WARM+1) ;save warm boot address
LD (WARMPT),HL
LD DE,BSWARM ;save old bios jumps
LD BC,12
LDIR ;move bios jumps
LD DE,(WARMPT)
LD HL,LOCJMP ;store new bios jumps
LD BC,12
LDIR ;move new bios jumps to bios area
;
; zex runtime bios intercept routines
;
NWARM:
LD SP,MEMTOP
LD HL,(Z3MSG+09H) ;see if we're at buffers end
LD A,(HL)
CP 0FFH ;test it
JP Z,WARMX ;warm return
LD HL,(WARMPT) ;set warm boot address
LD (WARM+1),HL
LD HL,(MEMTOP) ;set bdos entry address
LD (BDOS+1),HL
LD DE,BUFF ;dma address
LD C,26 ;set dma
CALL BDOS
LD A,(BDISK)
LD C,A
LD HL,(CCPJMP)
JP (HL) ;goto console processor
;
; jmp table to overlay bios with new zex-based jumps
;
LOCJMP:
JP NWARM ;warm
JP BCONST ;const
JP NCONIN ;conin
JP NCONOT ;conot
;
; console input intercept routine
;
NCONIN:
LD HL,Z3MSG+7 ;pt to zex message byte
LD A,(HL) ;get zex message
CP 2 ;suspend intercept?
JP Z,BCONIN ;get input via bios if user input active
CP 1 ;prompt just printed?
JR NZ,NCONNP
LD (HL),0 ;clear zex message
LD HL,STARTM ;print message
CALL PMSG
; lda pmchr ;print prompt char
; mov c,a
; call bconot
NCONNP:
LD A,(Z3MSG+08H) ;is zex running?
OR A ;0=no
JP Z,WARMX ;abort zex if not
LD (CONSTK),SP
LD SP,MEMTOP ;set user stack
NCONNL:
CALL BCONST ;get console status
OR A
JP Z,GETBUF ;get character from buffer
CALL BCONIN ;get character
CP 'C'-'@' ;see if terminate character
JP Z,ZEXABRT
CP 'S'-'@' ;13h
JR NZ,NCONEX
CALL BCONIN ;wait for next character
AND 7FH
LD HL,(Z3MSG+09H) ;pt to next char
INC HL
LD (HL),A
LD (Z3MSG+09H),HL ;reset ptr
LD A,'S'-'@' ;13h
NCONEX:
LD SP,(CONSTK) ;restore caller's stack
RET
;
; return next char from input buffer
;
GETBUF:
LD A,(IPSUPFL) ;combine psupfl and ipsupfl to set print flag
OR A ;0=no suppress
JR Z,GBUF0
LD HL,Z3MSG+1 ;pt to if flag
LD A,(HL) ;get if flag
OR A ;no if?
JR Z,GBUF0
INC HL
AND (HL) ;set if state
JR NZ,GBUF0 ;current if is true
LD A,0FFH ;suppress print
LD (OUTFLG),A
JR GBUF1
GBUF0:
LD A,(PSUPFL) ;set print suppress flag for nconot
LD (OUTFLG),A
GBUF1:
CALL GETCHR ;get next character
CP UICH ;user input?
JP Z,UISTRT ;yes..set user input pending flag
CP REXEC ;re-execute?
JP Z,REXECR ;yes..reset buffer ptr
CP CRWAIT ;cr wait?
JP Z,CRWRTN ;yes..wait for cr
CP CRBWAIT ;cr wait with ring bell?
JP Z,CRBWRTN ;yes..wait for cr and ring bell
CP RNG ;ring bell?
JP Z,RNGBELL ;yes..just ring the bell
CP MSUP ;message suppress flag?
JP Z,MSUPCK ;yes..toggle flag
CP PSUP ;print suppress ?
JP Z,PSUPCK ;yes..toggle flag
CP IPS ;false if print suppress?
JP Z,IPSUPCK
CP IMON ;immediate mode start ?
JP Z,IMFLGS ;yes..set flag
CP IMOFF ;immediate mode stop?
JP Z,IMFLGS ;yes..reset flag
CP CR ;cr?
JR NZ,GETEXT ;no...exit
;
; cr, so reset print suppression based only on ipsupfl
;
LD A,(IPSUPFL) ;combine psupfl and ipsupfl to set print flag
OR A ;0=no suppress
JR Z,GBUF2
LD HL,Z3MSG+1 ;pt to if flag
LD A,(HL) ;get if flag
OR A ;no if?
JR Z,GBUF2
INC HL
AND (HL) ;set if state
JR NZ,GBUF2 ;current if is true
LD A,0FFH ;suppress print
LD (OUTFLG),A
LD A,CR
JR GETEXT
GBUF2:
XOR A
LD (OUTFLG),A ;yes..reset print suppression
LD A,CR
GETEXT:
LD C,A
LD A,(IMFLG)
CP IMON ;immediate mode ?
LD A,C
JP NZ,NCONEX ;no...return to caller with char
CALL BCONOT ;yes..immediate echo to console
JP NCONNL ;...loop until imoff
;
; ^" command
;
UISTRT:
LD A,2 ;set message to suspend intercept
LD (Z3MSG+7),A
LD SP,(CONSTK) ;restore caller's stack
JP NCONIN ;get char from user for now
;
; ^: command
;
REXECR:
LD HL,(Z3MSG+0BH) ;start at top of buffer again
LD (Z3MSG+09H),HL
XOR A
LD (IMFLG),A ;reset all flags
LD (PSUPFL),A
LD (IPSUPFL),A
LD (MSUPFL),A
JP NCONNL ;...loop until ^c
;
; ^? command
;
CRWRTN:
CALL BCONIN ;get input char
CP 'C'-'@'
JP Z,ZEXABRT ;=^c
CP CR
JR Z,CRWRTX ;=<cr>
CP ' '
JR Z,CRWRTX ;=<sp>
LD C,BELL
CALL BCONOT ;<>cr
JR CRWRTN
;
; ^/ command
;
CRBWRTN:
LD HL,DELAY ;set counter
CRBWR1:
PUSH HL ;save counter
CALL BCONST ;check status
POP HL ;get counter
OR A ;set flags
JR NZ,CRBWR2
DEC HL ;count down
LD A,H ;done?
OR L
JR NZ,CRBWR1
LD C,BELL ;ring bell
CALL BCONOT
JR CRBWRTN
CRBWR2:
CALL BCONIN ;get char
CP 'C'-'@' ;abort?
JP Z,ZEXABRT
CP CR ;cont if <cr>
JR NZ,CRBWRTN
;
; ^| command
;
CRWRTX:
LD C,A ;echo cr/lf
CALL NCONOT
LD C,LF
CALL NCONOT
JP GETBUF
;
; ^* COMMAND
;
RNGBELL:
LD C,BELL ;ring bell
CALL NCONOT
JP GETBUF
;
; ^. command
;
PSUPCK:
LD HL,PSUPFL
CP (HL)
JR NZ,PSUPST ;set flags if not equal
XOR A ;else reset flags
PSUPST:
LD (HL),A ;set/reset saved flag
JP GETBUF ;and get next character (sets exec flag)
;
; ^& command
;
IPSUPCK:
LD HL,IPSUPFL
CP (HL)
JR NZ,PSUPST ;set flags if not equal
XOR A ;else reset flags
JR PSUPST ;set/reset flag in a
;
; ^# command
;
MSUPCK:
LD HL,MSUPFL
CP (HL)
JR NZ,MSUPST ;set flags if not equal
XOR A ;else reset flag
MSUPST:
LD (HL),A ;set/reset flag
JP GETBUF ;and get next character
;
; ^< and ^> commands
;
IMFLGS:
LD (IMFLG),A ;set/reset immediate mode flag
JP GETBUF ;get next character
;
; console output intercept routine
;
NCONOT:
LD A,(OUTFLG) ;print suppression?
OR A
RET NZ ;yes...ignore echo
LD A,C
LD (PMCHR),A ;set last char output
JP BCONOT
;
; get next char from buffer and terminate zex if end of buffer
;
GETCHR:
LD HL,(Z3MSG+09H) ;pt to next char
LD A,(HL) ;get it
DEC HL ;pt to following
LD (Z3MSG+09H),HL ;reset ptr
CP 0FFH ;eob?
RET NZ ;no...return
LD HL,(Z3MSG+09H) ;pt to eob
INC HL ;point to eob
LD (Z3MSG+09H),HL
CALL MOVBAK ;move jumps back
CALL BDOSRST ;restore bdos address
CALL PRDONEM
XOR A ;turn off zex
LD (Z3MSG+08H),A
LD SP,(CONSTK) ;get old stack
LD A,CR ;return carriage return
RET
;
; print done message with following prompt char
;
PRDONEM:
LD HL,DONEM ;print message
CALL PMSG
LD A,(PMCHR) ;print prompt char
LD C,A ;in c for bios
JP BCONOT
;
; restore bdos jmp if necessary
;
BDOSRST:
LD HL,(MEMTOP) ;see if bdos+1=memtop
EX DE,HL
LD HL,(BDOS+1)
LD A,E
SUB L
LD A,D
SBC A,H
RET NZ ;don't replace bdos jump
INC DE ;pt to bdos jump
LD A,(DE) ;get low address
LD L,A ;... in l
INC DE
LD A,(DE) ;get high address
LD H,A ;... in h
LD (BDOS+1),HL ;reset bdos jump
RET
;
; ^c abort exit
;
ZEXABRT:
LD SP,MEMTOP ;^c aborts zex
LD HL,ABORTD ;abort
CALL PMSG
JR WARMX1 ;don't print done message
;
; abort zex and return to zcpr2
;
WARMX:
CALL PRDONEM ;print done message
;
; entry point to abort zex without message
;
WARMX1:
XOR A ;say that zex is not running
LD (Z3MSG+08H),A
CALL MOVBAK ;move jumps back
CALL BDOSRST ;restore bdos jumps
LD HL,(EXMBASE) ;multiple command lines enabled?
LD A,H ;any on?
OR L
JP Z,WARM ;none on if address is zero, so just warm boot
;
; this section of code clears the multiple command line buffer
;
LD D,H ;de pts to multiple command buffer also
LD E,L
PUSH HL ;save ptr
LD HL,4 ;pt to first char of line
ADD HL,DE
LD (HL),0 ;set first char of line to zero for eol
EX DE,HL ;de pts to first char of line
POP HL ;get ptr
LD (HL),E ;store address of empty command (eol)
INC HL
LD (HL),D
JP WARM
;
PMSG:
PUSH HL
LD A,(IPSUPFL) ;combine psupfl and ipsupfl to set print flag
OR A ;0=no suppress
JR Z,PMSG0
LD HL,Z3MSG+1 ;pt to if flag
LD A,(HL) ;get if flag
OR A ;no if?
JR Z,PMSG0
INC HL
AND (HL) ;set if state
POP HL ;in case of return
RET Z ;skip message if suppressed
PUSH HL
PMSG0:
POP HL
LD A,(MSUPFL) ;print message at (hl)
CP MSUP ;messages suppressed?
RET Z ;yes..exit
PMSGL:
LD A,(HL) ;get next char
OR A ;end of message?
RET Z ;yes..exit
INC HL ;pt to next char
PUSH HL ;save ptr
LD C,A ;output char
CALL BCONOT
POP HL ;restore ptr
JR PMSGL
;
; subroutines
;
MOVBAK:
LD HL,(WARMPT) ;move old jump table back to bios
EX DE,HL
LD HL,BSWARM
LD BC,12
LDIR
;
; replace zex routine jumps with bios jumps
;
F121:
LD HL,BSWARM ; insure only bios 1.1.2
LD DE,NWARM ; calls from now on 1.1.2
LD BC,3 ; for programs 1.1.2
LDIR ; that may have 1.1.2
LD HL,BCONIN ; copied our 1.1.2
LD DE,NCONIN ; addresses as 1.1.2
LD BC,3 ; if they were 1.1.2
LDIR ; in the bios. 1.1.2
LD HL,BCONOT ; (mbasic does this) 1.1.2
LD DE,NCONOT ; 1.1.2
LD BC,3 ; 1.1.2
LDIR ; 1.1.2
RET
;
; working storage area
;
ABORTD:
DB CR,LF,'[ZEX Aborted]',CR,LF,0
STARTM:
DB ' ZEX: ',0
DONEM:
DB 'Done',0
DS 30 ;stack space
MEMTOP:
DW 0
EXMBASE:
DW 0
CCPJMP:
DW 0
WARMPT:
DW 0
;
; original bios jmp table
;
BSWARM:
JP $
BCONST:
JP $
BCONIN:
JP $
BCONOT:
JP $
;
PMCHR:
DB 0
PSUPFL:
DB 0
IPSUPFL:
DB 0
OUTFLG:
DB 0
NUICH:
DB 0
IMFLG:
DB 0
MSUPFL:
DB 0
CONSTK:
DW 0
;?PLEN DEFL $
; IF (?PLEN MOD 8) GT 0
;?PLEN DEFL (?PLEN AND 0FFF8H)+8 ;get next boundary
; ENDIF
;
;DRVERL EQU ?PLEN
;
;DRVL8 EQU DRVERL/8 ;length of relocation bit map
; ORG DRVERL
;
;
; end of zex relocated code segment
;
.DEPHASE
REEND EQU $
RELE EQU REEND-REST
END