; Program: MEX+2Z ; Author: Bruce Morgen and Jay Sage ; Version: 1.2 ; Date: 9 Feb 89 ; Previous Versions: 1.1 (8 Dec 86) ; * * * IMPORTANT NOTE * * * ; ; This program is copyrighted 1989 by NAOG/ZSIG. It may be copied and ; modified freely for personal use but may not be sold or distributed ; for a fee. Modified versions must be submitted to and approved by ; NAOG/ZSIG before they may be distributed. See the file ZSIGPOL1.DOC ; on Z-Nodes for the ZSIG policy on signing out and modifying programs. ; ;______________________________________________________________________ ; ; MEX+2Z: MEX-to-ZCPR3 Chaining Program ; ; This program was derived from Bruce Morgen's MEX2Z and can be assembled ; to work with either MEX114 or Mex-Plus. The functions supported are ; slightly different -- hence the different name. NOTE: There are some ; significant differences from version 1.1. Please read carefully. This ; version must be assembled and run as a type-3 program. It inspects the ; byte at location 107H in the MEX that was running to determine the current ; data rate. It then restores that rate when it chains back to MEX. ; ; This program gives the MEX command 'CPM' a shell capability like that in ; the 16-bit version's SHELL command. The equates below must be set up for ; the appropriate version of MEX. MEX+2Z is used as follows: ; ; 1) Set the real MEX.COM file so that it will not be invoked by a command ; of the form "MEX". This can be done by renaming it (e.g., to REALMEX) ; or by putting it in a directory that is not along the search path. ; 2) Create a stand-alone or ARUNZ alias called MEX with scripts such as ; the following and invoke MEX using the alias: ; ; for renamed MEX: for MEX in non-path directory DIR: ; REALMEX $* DIR:MEX $* ; MEX+2Z MEX+2Z ; ; 3) Create a stand-alone or ARUNZ alias called MEXRR with scripts such as ; the following: ; ; for renamed MEX: for MEX in non-path directory DIR: ; GET 100 REALMEX.COM GET 100 DIR:MEX.COM ; POKE 107 $1 POKE 107 $1 ; GO GO ; MEX+2Z MEX2Z ; ; On exit from MEX, MEX+2Z runs and looks for the MEX command line left in ; memory. It scans for the command "CPM", takes anything in the command after ; that, and puts it into the ZCPR3 command line with ";MEXRR" after it so that ; the MEX alias will be run again after the other commands are finished. With ; version 1.2, the baud rate constant will be passed to MEXRR as a parameter so ; that it can poke it into place so that MEX will come back at its old rate. ; If you leave MEX with the command "CPM CRUNCH FN.FT", the file will be ; crunched and then you will return to MEX. ; ;============================================================================= ; ; R E V I S I O N H I S T O R Y ; ;============================================================================= VERSION EQU 12 ; Version 1.2 February 9, 1989, Jay Sage ; I have set this up now as a type-3 program. By loading at 200H, it ; can save MEX's current baud rate and restore it when it chains back ; to MEX. ; ; If you do not want this feature, go back to version 1.1. This version ; must run as a type-3 program (recommended at an address of 200H). ; VERSION EQU 11 ; Version 1.1 December 11, 1986, Jay Sage ; Improved processing of the MEX command line to make it more reliable ; and make it work with multiple commands in MEX-PLUS. The code makes ; use of the way MEX-PLUS maintains the command line. With MEX114 the ; command line length is not stored at the beginning of the command ; line; a value of zero is stored there. Bruce's original technique of ; scanning for the terminating carriage return must be used. The MEXPLUS ; equate takes care of this. ; Version 1.0 December 8. 1986, Bruce Morgen ; Original version for MEX114. ;============================================================================= ; ; C O N F I G U R A T I O N S E C T I O N ; ;============================================================================= NO EQU 0 YES EQU NOT NO BIHELP EQU YES ; YES to include built-in help facility .ACCEPT 'Set up for CMDRUN (YES/NO)? ',CMDRUN ;CMDRUN EQU YES ; YES if using an ARUNZ alias called by CMDRUN, ; ..NO otherwise or for standalone alias ECP EQU YES ; YES to invoke CMDRUN as ECP ('/' prefix) .ACCEPT 'Set up for MEX-Plus (YES/NO)? ',MEXPLUS ;MEXPLUS EQU YES ; YES for MEX-PLUS 1.65, NO for MEX114 IF MEXPLUS MEXCL EQU 2295H ; Mex-Plus 1.65 command buffer address MEXPTR EQU 2214H ; Address of pointer to command buffer MEXVER MACRO ; Macro with MEX version name DB 'MEX-PLUS Version 1.65' ENDM ELSE ; MEX114 MEXCL EQU 5A39H ; Mex 1.14 command buffer address MEXPTR EQU 5390H ; Address of pointer to command buffer MEXVER MACRO ; Macro with MEX version name DB 'MEX Version 1.14' ENDM ENDIF ; MEXPLUS CR EQU 0DH ; ASCII characters LF EQU 0AH TAB EQU 9 BELL EQU 7 PRINTF EQU 9 ; BDOS print string function BDOS EQU 0005 ; BDOS entry point TBUFF EQU 80H ; Command tail buffer ;============================================================================= ; ; E X T E R N A L R E F E R E N C E S ; ;============================================================================= EXTRN PSTR,CAPS,Z3INIT,PUTCL,$MEMRY IF NOT MEXPLUS EXTRN SUBHD ENDIF ;============================================================================= ; ; C O D E ; ;============================================================================= ; TYP3HDR.Z80, Version 1.1 ; This code has been modified as suggested by Charles Irvine so that it will ; function correctly with interrupts enabled. ; This is header code that can be used at the beginning of a type-3-environment ; program so that it will abort with an error message when not loaded to the ; correct address (such as when a user tries to run it under CP/M or Z30). entry: jr start0 ; Must use relative jump defb 0 ; Filler db 'Z3ENV',3 ; Type-3 environment z3env: dw 0 ; Filled in by Z33 dw entry ; Intended load address start0: ld hl,0 ; Point to warmboot entry ld a,(hl) ; Save the byte there di ; Protect against interrupts ld (hl),0c9h ; Replace warmboot with a return opcode rst 0 ; Call address 0, pushing RETADDR onto stack retaddr: ld (hl),a ; Restore byte at 0 dec sp ; Get stack pointer to point dec sp ; ..to the value of RETADDR pop hl ; Get it into HL and restore stack ei ; We can allow interrupts again ld de,retaddr ; This is where we should be xor a ; Clear carry flag push hl ; Save address again sbc hl,de ; Subtract -- we should have 0 now pop hl ; Restore value of RETADDR jr z,start ; If addresses matched, begin real code ld de,notz33msg-retaddr ; Offset to message add hl,de ex de,hl ; Switch pointer to message into DE ld c,9 jp 0005h ; Return via BDOS print string function notz33msg: defb 'Not Z33+$' ; Abort message if not Z33-compatible ; --------------------------------------------------------------------------- MEXNAM: DB ';' ; Separator IF CMDRUN ; If using ARUNZ (CMDRUN) alias IF ECP DB '/' ; Force ECP invocation ELSE DB 'CMDRUN ' ; Explicit CMDRUN invocation ENDIF ; ECP ENDIF ; CMDRUN DB 'MEXRR ' ; Alias to rerun MEX BAUDPAT: DB '5' ; This will be filled in by program DB 0,0,0,0,0,0,0,0,0,0,0 ; Room for patching (begin with space) NAMELEN EQU $ - MEXNAM START: LD (STACK),SP LD SP,$MEMRY+64 ; Establish stack (so we can be sloppy later) LD HL,(Z3ENV) CALL Z3INIT ; Initialize Z3LIB. ; ------------------------- Display built-in help if anything in command tail IF BIHELP ; Built-in help enabled LD A,(TBUFF) ; Get count of characters in tail OR A ; If nonzero, display built-in help JP NZ,HELP ENDIF ; BIHELP ; ------------------------- Get current baud rate from address 107H LD A,(107H) ADD A,'0' ; Convert to character for POKE command CP '9'+1 ; Check for value bigger than 9 JR C,SETBAUD ADD A,'A'-'0'-10 SETBAUD: LD (BAUDPAT),A ; Save in command string ; ------------------------- Check for MEX command line in memory LD HL,(MEXPTR) ; Get pointer to command line LD BC,MEXCL ; Correct value of pointer LD DE,MEXERR1 ; Point to possible error message LD A,B ; Check for agreement CP H JR NZ,ENDIT ; Error message if different LD A,C CP L JR NZ,ENDIT ; ------------------------- Scan for exit command in the MEX command line IF NOT MEXPLUS ; Fill in character count LD BC,126 ; Maximum command line length LD A,CR ; Search for terminating carriage return PUSH HL ; Save pointer to start of command buffer CPIR ; Scan for the carriage return LD DE,MEXERR2 ; Prepare for possible error message JR NZ,ENDIT ; If CPIR failed, quit with error message POP DE ; Get buffer start address back to DE CALL SUBHD ; Get number of characters in command line DEC HL ; Correct by 2 DEC HL EX DE,HL LD (HL),E ; Put count into place in buffer ENDIF ; NOT MEXPLUS LD B,(HL) ; Put character count into B INC HL ; Point to first character of command line LD DE,EXITCMD ; Point to exit command to scan for EX DE,HL ; Outer loop: look for initial character SCAN1: LD A,(DE) ; Get character from command line CALL CAPS ; Capitalize it CP (HL) ; See if it matches exit command first char JR Z,SCAN3 ; Go to check for rest of characters SCAN2: INC DE ; Point to next character in command line DJNZ SCAN1 ; Continue scan JR DONE ; If not found, we are done ; Inner loop: check rest of characters SCAN3: PUSH HL ; Save registers PUSH DE PUSH BC LD B,EXITLEN-2 ; Characters in exit command less one SCAN4: INC HL ; Bump pointers INC DE LD A,(DE) CALL CAPS CP (HL) JR NZ,SCAN5 ; Commands do not match DJNZ SCAN4 JR FOUND ; Exit command found SCAN5: POP BC ; Restore the registers POP DE POP HL JR SCAN2 ; Resume outer scan loop FOUND: EX DE,HL ; Get pointer to start of command into HL ; ------------------------- Build ZCPR3 command line ; Skip to any tail after exit command SETPTR: INC HL ; Point to next character LD A,(HL) ; Get it CP CR ; If CR, we are at end of line JR Z,DONE ; Nothing for ZCPR3 to run CP ' '+1 ; Skip over any other control characters JR C,SETPTR PUSH HL ; Save pointer for PUTCL call LD HL,MEXCL ; Point to command line again LD C,(HL) ; Get length into BC LD B,0 INC HL ; Point to first character in command line ADD HL,BC ; Increment to termininating CR LD A,(HL) ; Verify it CP CR LD DE,MEXERR2 ; Prepare for possible error message JR NZ,ENDIT ; Report error ; Add MEX reinvocation command to end of existing ; command in MEX command buffer EX DE,HL ; To DE as destination pointer. LD HL,MEXNAM ; Source pointer to HL. LD BC,NAMELEN ; Length of line as counter to BC. LDIR ; Move 'em out. POP HL ; Get back command line start. CALL PUTCL ; Stuff command line via Z3LIB. JR NZ,DONE ; Trap command line failures. LD DE,MCLERR ; Point at cmd line error msg. ; ------------------------- ENDIT: EX DE,HL ; Switch string pointer into HL CALL PSTR ; Print string pointed to by HL DONE: LD SP,(STACK) ; Restore incoming stack pointer. RET ; All done, go to Z3. IF BIHELP ; Built-in help enabled HELP: LD DE,HELPMSG ; Point to help message JR ENDIT ENDIF ; BIHELP ; ------------------------- Messages EXITCMD: DB 'CPM',0 EXITLEN EQU $ - EXITCMD MEXERR1: DB LF MEXVER ; Mex version name macro DB ' image not found in memory!' DB cr,lf,bell,0 MEXERR2: DB LF DB 'Defect in MEX command line!' DB cr,lf,bell,0 MCLERR: DB 'ZCPR3 command line error!',cr,lf,bell,0 IF BIHELP ; Built-in help enabled HELPMSG: DB LF DB TAB,'MEX+2Z Version ' DB VERSION/10+'0','.',VERSION MOD 10 +'0' DB ' [ZSIG]' DB CR,LF,LF DB 'For ' MEXVER DB ' gives a virtual shell capability' DB CR,LF DB 'to the exit command CPM.' DB CR,LF,LF DB 'Any tail after the MEX command "CPM" will be detected by' DB CR,LF DB 'MEX+2Z and run as a command by ZCPR3. Then MEX will be' DB CR,LF DB 'reinvoked at its current baud rate.' DB CR,LF,LF DB 'To use MEX+2Z you must make an alias named MEX with a script' DB CR,LF DB 'such as "REALMEX;MEX+2Z", where the real MEX.COM file has' DB CR,LF DB 'been renamed (e.g., to REALMEX) or kept off the path and' DB CR,LF DB 'invoked with an explicit DIR: prefix. You must also make' DB CR,LF DB 'an alias MEXRR that loads MEX.COM to address 100, pokes the' DB CR,LF DB 'parameter passed to the alias to address 107H, runs MEX using' DB CR,LF DB 'the GO command, and then reinvokes MEX+2Z. An example script' DB CR,LF DB 'is: "GET 100 REALMEX.COM;POKE 107 $1;GO;MEX+2Z".' DB CR,LF DB 0 ENDIF ; BIHELP STACK: DS 2 END