; ; 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 ^ 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 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