; ; PROGRAM: ZEX ; AUTHOR: RICHARD CONN (DERIVED FROM EX, WHICH WAS WRITTEN BY SOMEONE ELSE) ; VERSION: 1.3 ; DATE: 6 JAN 83 ; PREVIOUS VERSIONS: 1.0 (12 NOV 82), 1.1 (8 DEC 82), 1.2 (3 JAN 83) ; VERS EQU 13 ; ; ZEX 1.0 -- EX 1.2.1 implemented for ZCPR2 by Richard Conn ; DATE: 12 NOV 82 ; Extensions to EX are: ; Multiple command buffer is preserved, and any commands ; following the ZEX command are executed after ; the ZEX command file is completed (ZEX T;DIR ; will execute commands in T.SUB and then run DIR) ; ZCPR2 Search Path is following when looking for the ; file specified to ZEX ; Command File Type may be SUB or ZEX ; Added ^* form to simply ring the bell ; Added ^/ form to act like ^? but ring bell periodically ; Added ^" form to allow user input in the middle of a ; command file operation ; Major rewrite of EX to improve readability and to impose ; a structured organization on the code for maintenance ; purposes ; Major change in the abort system so that the multiple command ; line buffer of ZCPR2 will be properly cleared on ; abort; without this change, ZEX would crash the system ; in attempting to abort out of the ^/ and ^? forms; ; EX will probably always crash a ZCPR2 system with ; multiple commands enabled if an abort from ^? is ; attempted ; ; EX12.ASM - An enhanced version of EXEC and EX. ; ; START 05-09-82 ; ; DATE 08-11-82 *LAST MAJOR CHANGE ; ; HISTORY: ; ; ZEX 1.0 11-12-82 modify for use under ZCPR2; main change is to place ; rest of multiple command line at end of SUB file ; ; 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 ; ; ; EX12.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 ZEX TO RING THE BELL AND WAIT FOR A CARRIAGE RETURN ; (^C WILL ABORT ZEX AT THIS POINT ALSO) ; ; ^* WILL CAUSE ZEX TO RING THE BELL ; ; ^" WILL CAUSE ZEX TO STOP PROVIDING INPUT UNTIL THE NUICH CHAR IS ; OUTPUT ; ; ^$ 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 ; ; GENERAL EQUATES ; BELL EQU 7 CTRLZ EQU 1AH ;^Z DELAY EQU 6000H ;DELAY CONSTANT FOR TIMER LOOP 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 ;^# EX MESSAGE SUPPRESS FLAG CRWAIT EQU 84H ;^? EX RUNTIME WAIT FOR CR FLAG REXEC EQU 85H ;^: EX RUNTIME RE-EXECUTE FLAG CRBWAIT EQU 86H ;^/ EX RUNTIME RING BELL AND WAIT FOR CR FLAG RNG EQU 87H ;^* EX RUNTIME RING BELL UICH EQU 88H ;^" USER INPUT COMMAND CHAR SEQUENCE DNUICH EQU '>'+80H ;USER INPUT TERMINATION CHAR ; ; CP/M CONSTANTS ; WARM EQU 0 BDISK EQU 4 BDOS EQU 5 DFCB EQU 5CH BUFF EQU 80H ; ; NOTE: ZEX10.LIB IS CREATED BY THE ZEX10.SUB GENERATION PROCESS ; MACLIB ZEX10 ; $-PRINT IF BASE $+PRINT ; ; START OF EX INITIATOR CODE SEGMENT ; ORG 100H ; ; Branch to Start of Program ; jmp start ; ;****************************************************************** ; ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format ; ; This data block precisely defines the data format for ; initial features of a ZCPR2 system which are required for proper ; initialization of the ZCPR2-Specific Routines in SYSLIB. ; ; ; EXTERNAL PATH DATA ; EPAVAIL: DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES) EPADR: DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE ; ; INTERNAL PATH DATA ; INTPATH: DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT ; DISK = 1 FOR A, '$' FOR CURRENT ; USER = NUMBER, '$' FOR CURRENT DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT DB 0 ; END OF PATH ; ; MULTIPLE COMMAND LINE BUFFER DATA ; MCAVAIL: DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE? MCADR: DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE ; ; DISK/USER LIMITS ; MDISK: DB 4 ; MAXIMUM NUMBER OF DISKS MUSER: DB 31 ; MAXIMUM USER NUMBER ; ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK ; DOK: DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES) UOK: DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES) ; ; PRIVILEGED USER DATA ; PUSER: DB 10 ; BEGINNING OF PRIVILEGED USER AREAS PPASS: DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL ; ; CURRENT USER/DISK INDICATOR ; CINDIC: DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS) ; ; DMA ADDRESS FOR DISK TRANSFERS ; DMADR: DW 80H ; TBUFF AREA ; ; NAMED DIRECTORY INFORMATION ; NDRADR: DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY NDNAMES: DB 64 ; MAX NUMBER OF DIRECTORY NAMES DNFILE: DB 'NAMES ' ; NAME OF DISK NAME FILE DB 'DIR' ; TYPE OF DISK NAME FILE ; ; REQUIREMENTS FLAGS ; EPREQD: DB 0FFH ; EXTERNAL PATH? MCREQD: DB 0FFH ; MULTIPLE COMMAND LINE? MXREQD: DB 000H ; MAX USER/DISK? UDREQD: DB 000H ; ALLOW USER/DISK CHANGE? PUREQD: DB 000H ; PRIVILEGED USER? CDREQD: DB 0FFH ; CURRENT INDIC AND DMA? NDREQD: DB 000H ; NAMED DIRECTORIES? Z2CLASS: DB 4 ; CLASS 4 DB 'ZCPR2' DS 10 ; RESERVED ; ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA ; ;****************************************************************** ; ; ; END USER INPUT COMMAND CHAR ; TNUICH: DB DNUICH ;INIT TO DEFAULT VALUE ; ; INITIAL COMMAND LINE AREA ; DB 0FFH ;SIZE OF COMMAND LINE DBUFF EQU $ DB 0FFH ;SIZE OF BUFFER DS 100H ;SPACE FOR COMMAND LINE ; ; START OF ZEX ; START: NOP ;REPLACED WITH RET TO PREVENT REENTRY LDA DFCB+1 ;CHECK FOR HELP REQUEST CPI '/' ;HELP? JZ HELP LXI H,0 DAD SP SHLD CCPSTK ;CCP STACK PTR LXI SP,CCPSTK ;USER STACK AREA MVI A,0C9H ; (8080 RET) STA START ;PREVENT RE-ENTRANCE BY ZCPR LXI H,BUFF ;COPY INPUT LINE INTO DBUFF LXI D,DBUFF MVI B,128 ;SIZE OF BUFFER CALL MOVE LXI D,SIGNON ;LOGO CALL PRINT CALL EXACTV ;CHECK FOR RECURSION CALL ZRELOC ;RELOCATE ZEX MODULE CALL ZPARMS ;EXTRACT PARAMETERS FROM COMMAND LINE LDA DFCB+1 ;CHECK TO SEE IF SUB FILE PRESENT CPI ' ' ;=NO PUSH PSW ;SAVE FLAG CNZ OPENSB ;OPEN AND LOAD SUB FILE IF PRESENT OR ABORT POP PSW ;GET FLAG CZ 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 H ;SAVE PTR TO END OF DATA LHLD RELSTRT ;GET PTR TO START OF ZEX SHLD GOADR ;SET ADDRESS TO RUN TO MOV D,H ;DE IS START OF DATA AREA ALSO MOV E,L DCX H ;PT TO START OF DATA AREA XTHL ;HL IS PTR TO END OF DATA, (SP) IS BEGINNING OF DATA ; FROM TOP DOWN MVI M,0FFH ;SET UP END OF DATA DCX H MVI M,'X' ;SET UP EX RECURSION ID DCX H MVI M,'E' DCX H MVI M,'Z' ;ZEX BACKWARDS (FROM TOP DOWN) 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 POP D ;GET START OF BUFFER ADDRESS IN DE LXI B,0 ;ASSUME NO MULTIPLE COMMANDS LDA MCAVAIL ;GET FLAG ORA A ;0=NONE JZ GOTOZEX ;NO MULTIPLE COMMANDS, SO BC=0 PUSH H ;SAVE HL LHLD MCADR ;GET ADDRESS OF MULTIPLE COMMAND BUFFER MOV B,H ;... IN BC MOV C,L POP H ; ; ZEX MONITOR ENTRY PARAMETERS -- ; HL TOP OF MEMORY ADDRESS ; DE START OF BUFFER ADDRESS ; BC ADDRESS OF MULTIPLE COMMAND BUFFER OR 0 IF NONE ; A END OF USER INPUT CHAR ; GOTOZEX: LDA TNUICH ;GET END OF USER INPUT CHAR GOADR EQU $+1 JMP $ ; ; PRINT HELP MESSAGE FOR ZEX ; HELP: LXI D,SIGNON ;PRINT BANNER CALL PRINT LXI H,HMSG ;PRINT MESSAGE CALL HPRINT MVI C,1 ;GET CHAR CALL BDOS CPI 'C'-'@' ;^C? RZ LXI D,CRLFS CALL PRINT LXI D,SIGNON CALL PRINT LXI H,HMSG0 CALL HPRINT MVI C,1 ;GET CHAR CALL BDOS CPI 'C'-'@' ;^C? RZ LXI D,CRLFS CALL PRINT LXI D,SIGNON CALL PRINT LXI H,HMSG1 HPRINT: MOV A,M ;GET CHAR ORA A ;DONE? RZ INX H ;PT TO NEXT PUSH H ;SAVE PTR MOV E,A ;CHAR IN E MVI C,2 ;CONSOLE OUTPUT CALL BDOS POP H ;GET PTR JMP 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 ' 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,'( 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 ^| insert ' 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 ^/ ring and wait for ' 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: LHLD RELOCL ;GET RELOC PROGRAM LENGTH MOV B,H ;BC=HL=RELOC PROGRAM LENGTH MOV C,L 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 D ;SAVE PTR TO START OF 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 POP H ;PT TO FIRST BYTE OF PROGRAM SHLD RELSTRT ;SAVE PTR DCX H ;RELOCATE PROGRAM-1 SHLD OUTBUF ;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: LXI D,DBUFF+1 ;TERMINATE COMMAND LINE WITH CR PUSH D LDA DBUFF MOV L,A ;HL = NUMBER OF CHARS IN LINE MVI H,0 DAD D ;PT TO AFTER LAST CHAR MVI M,CR ;STORE 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 ;GET PTR TO POINTER FOR PARAMETER 0 POP D ;GET PTR TO FIRST CHAR IN LINE MVI A,(PRMPNL/2)+1 ;NUMBER OF PARAMETERS POSSIBLE, MAX STA PRMMAX ;HIGHEST PARAMETER # + 1 for .SUB SPEC ; ; PARAMETER EXTRACTION ROUTINE; HL PTS TO FIRST PARAM PTR, DE PTS TO LINE ; 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 ;BACK UP TO 1ST CHAR MOV M,E ;SAVE ADDRESS IN TABLE INX H MOV M,D INX H INR B ;COUNT+1 LDA PRMMAX CMP B JC PRMTOO ;TOO MANY ARGUMENTS ; ENDPRM: LDAX D ;GO TO END OF PARAMETER INX D CPI CR JZ ENDLNE CPI ' ' ;SKIP UNTIL JNZ ENDPRM XRA A ;A=0 TO TERMINATE PARAM DCX D ;PT TO FOLLOWING PARAM STAX D ;TERMINATE PARAMETER INX D ;PT TO CHAR AFTER JMP PARMSL ;IGNORE SPACES BETWEEN PARAMETERS ENDLNE: XRA A ;STORE ZERO AFTER LAST PARAMETER DCX D ;PT TO CR STAX D ;TERMINATE LAST PARAMETER INX D ;PT TO AFTER LAST PARAM MVI A,CR ;STORE ENDING CR STAX D RET ; ; INPUT COMMAND LINES FROM USER ; INPUTSB: LXI H,0 SHLD LINES ;START LINE COUNTER MVI A,0FFH ;SET 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 RZ ;DONE WITH INPUT XCHG CALL MOVE ;MOVE TO INPUT BUFFER XCHG MVI M,CR INX H MVI M,LF INX H SHLD INBUF JMP GETLIN ; ; OPEN AND LOAD SUB FILE ; OPENSB: CALL PUTUD ;SAVE USER/DISK ; ; SET UP TO READ ZEX FILE ; LXI D,DFCB+9 LXI H,ZEXNAM ;MOVE 'SUB' TO DFCB FILE TYPE MVI B,3 CALL MOVE XRA A ;ZERO CR FIELD STA DFCB+32 LXI D,BUFF ;SET DMA ADDRESS MVI C,26 ;SET DMA CALL BDOS LXI D,DFCB LXI H,INTPATH ;PT TO INTERNAL PATH LDA EPAVAIL ;EXTERNAL PATHS AVAILABLE? ORA A ;0=NO JZ OSB1 ;USE INTERNAL PATH LHLD EPADR ;PT TO EXTERNAL PATH OSB1: PUSH H ;SAVE PATH PTR CALL FNDFILE ;LOOK FOR FILE ALONG PATH AND SAY IF IT IS FOUND POP H ;GET PATH PTR JNZ READSB ; ; ZEX FILE NOT FOUND -- SET UP TO READ SUB FILE ; PUSH H ;SAVE PATH PTR CALL GETUD ;RESTORE USER/DISK LXI D,DFCB+9 ;SET TYPE TO SUB LXI H,SUBNAM MVI B,3 CALL MOVE XRA A ;ZERO CR FIELD STA DFCB+32 POP H ;PT TO PATH LXI D,DFCB ;PT TO FCB CALL FNDFILE ;LOOK FOR FILE JNZ READSB RSBERR: CALL GETUD ;RESTORE USER/DISK 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 TERMINATER JMP NOSUB * * FNDFILE -- LOOK FOR FILE ALONG ZCPR2 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: SHLD PATH ;SAVE PATH BASE ADDRESS MVI C,17 ;SEARCH FOR FIRST CALL BENTRY ;LOOK FOR FILE INR A ;SET FLAG JNZ FF5 ;FOUND IT -- RETURN FOUND FLAG XCHG ;HL=FCB PTR SHLD FCBPTR ;SAVE IT LHLD PATH ;PT TO PATH FOR FAILURE POSSIBILITY MVI C,32 ;GET CURRENT USER MVI E,0FFH CALL BENTRY STA TMPUSR ;SAVE IT FOR LATER ; ; MAIN SEARCH LOOP ; FF1: MOV A,M ;GET DRIVE ANI 7FH ;MASK MSB ORA A ;0=DONE=COMMAND NOT FOUND JNZ FF2 ;NO ERROR ABORT? ; ; FILE NOT FOUND ERROR ; XRA A ;ZERO FLAG MEANS NOT FOUND RET ; ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A ; FF2: MOV E,A ;DISK IN E LDA CINDIC ;CURRENT DRIVE SPECIFIED? CMP E JNZ FF3 ;SKIP DEFAULT DRIVE SELECTION IF SO LDA BDISK ;GET DEFAULT USER/DISK ANI 0FH ;MASK FOR DEFAULT DISK INR A ;PREP FOR FOLLOWING DCR A MOV E,A ;DISK NUMBER IN E FF3: DCR E ;ADJUST PATH 1 TO 0 FOR A, ETC MVI C,14 ;SELECT DISK FCT CALL BENTRY ;SELECT DRIVE INX H ;PT TO USER NUMBER MOV A,M ;GET USER NUMBER ANI 7FH ;MASK OUT MSB INX H ;PT TO NEXT ENTRY IN PATH PUSH H ;SAVE PTR MOV E,A ;SAVE IN E LDA CINDIC ;CURRENT USER SPECIFIED? CMP E ;MATCH? JNZ FF4 ;DO NOT SELECT CURRENT USER IF SO LDA TMPUSR ;GET ORIGINAL USER NUMBER MOV E,A ;SELECT USER FF4: MVI C,32 CALL BENTRY LHLD FCBPTR ;GET PTR TO FCB XCHG ;... IN DE MVI C,17 ;SEARCH FOR FIRST CALL BENTRY ;LOOK FOR FILE POP H ;GET PTR TO NEXT PATH ENTRY INR A ;SET FLAG JZ FF1 ;CONTINUE PATH SEARCH IF SEARCH FAILED ; ; FILE FOUND -- PERFORM SYSTEM TEST AND PROCEED IF APPROVED ; FF5: MVI A,0FFH ;SET OK RETURN ORA A RET ; ; BDOS ROUTINE ; BENTRY: PUSH H ;SAVE REGS PUSH D PUSH B CALL BDOS POP B ;GET REGS POP D POP H 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: MVI E,0FFH ;GET CURRENT USER MVI C,32 ;BDOS CALL BDOS STA CUSER ;SAVE CURRENT USER AWAY MVI C,25 ;GET CURRENT DISK CALL BDOS STA CDISK RET GETUD: LDA CDISK ;GET CURRENT DISK MOV E,A ;... IN E MVI C,14 ;SELECT DISK CALL BDOS LDA CUSER ;GET CURRENT USER MOV E,A ;... IN E MVI 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: MVI C,15 ;OPEN FILE CALL BDOS ;BDOS INR A ;ERROR? JZ RSBERR ; ; READ IN AND STORE SUB FILE ; READTX: LHLD INBUF ;GET PTR TO NEXT BYTE XCHG ;SET PTR IN DE LXI H,80H ;GET SECTOR OFFSET DAD D ;HL PTS TO FOLLOWING BLOCK TO BE READ, DE PTS TO SHLD INBUF ; BLOCK TO READ; SAVE PTR TO FOLLOWING BLOCK 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 CALL GETUD ;RESTORE CURRENT USER/DISK LHLD INBUF ;MAKE SURE BUFFER'S TERMINATED LXI D,-100H ;PT TO FIRST BYTE OF LAST BLOCK READ DAD D MVI B,80H ;LOOK AT AT MOST 80H BYTES SKIP1A: MOV A,M ;GET BYTE CPI CTRLZ ;EOF? JZ SKIP1B INX H ;PT TO NEXT DCR B ;COUNT DOWN JNZ SKIP1A ; HL NOW POINTS TO AFTER LAST VALID CHAR IN FILE SKIP1B: SHLD INBUF ;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: XCHG ;BUFFER PTED TO BY DE LHLD MCADR ;GET BASE ADDRESS OF MULTIPLE COMMAND LINE MOV A,M ;GET LOW INX H MOV H,M ;GET HIGH MOV L,A ;HL PTS TO NEXT CHAR IN MULTIPLE COMMAND LINE XCHG ;DE PTS TO NEXT CHAR IN COMMAND LINE, HL PTS TO BUF END LDA MCAVAIL ;MULTIPLE COMMANDS ENABLED? ORA A ;0=NO JZ ENDSTR ;TERMINATE FILE; HL PTS TO NEXT BYTE LDAX D ;GET FIRST BYTE MOV B,A ;SAVE FIRST BYTE IN B XRA A ;A=0 STAX D ;CLEAR COMMAND LINE INX D ;PT TO NEXT BYTE MOV A,B ;GET FIRST BYTE CPI ';' ;SEPARATION CHAR? JNZ CMCMD1 ;PROCESS IF NOT ; ; LOOP TO STORE REST OF MULTIPLE COMMAND LINE INTO LOADED FILE ; CMCMD: LDAX D ;GET BYTE FROM LINE CMCMD1: ORA A ;EOL IF ZERO JZ CMEND ;READ IN FILE; HL PTS TO NEXT AVAILABLE BYTE MOV M,A ;STORE BYTE INX H ;PT TO NEXT INX D JMP CMCMD CMEND: MVI M,CR ;STORE INX H MVI M,LF INX H ;PT TO NEXT AVAILABLE BYTE ; ; MARK END OF BUFFER AND CONTINUE ; 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 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: XRA A STA IMFLG1 STA IMFLG2 STA PRTFLG STA OUTCNT LXI H,1 SHLD LINES LHLD OUTBUF ;PT TO BYTE JUST BELOW LOADED ZEX SHLD OUTLNE SHLD BUFSTR LXI D,BEGREL ;PT TO FIRST BYTE OF COMMAND BUFFER ; ; MAIN COPY LOOP TO COPY BUFFER AT BEGREL TO JUST UNDER EX WITH PROCESSING ; MOVSTR: LDAX D ;GET NEXT COMMAND BYTE INX D ;PT TO FOLLOWING ANI 7FH ;MAKE SURE NO PARITY CPI LF ;NEW LINE? JNZ MOVST0 ; ; NEW LINE -- DON'T STORE AND INCREMENT LINE COUNT ; MOVSTX: CALL INCR ;INCREMENT LINE COUNT JMP MOVSTR ;CONTINUE ; ; BEGIN CHARACTER PROCESSING ; A CONTAINS CHAR, DE PTS TO BYTE AFTER CHAR, HL PTS TO NEXT BUFFER POS ; MOVST0: CPI 1AH ;END OF INPUT? RZ ;DONE IF SO CPI '|' ;CARRIAGE RETURN? JNZ MOVST1 ;NOPE ; ; PROCESS CARRIAGE RETURN FORM (|) ; PUSH D ;SAVE OLD POINTER INX D ;LOOK FOR EOF AFTER | (PT TO LF) INX D ;PT TO POSSIBLE EOF LDAX D ;GET PRESENT LOCATION+2 POP D ;GET OLD POINTER CPI 1AH ;END OF BUFFER RZ ;END, SO NO FOLLOWING MVI A,CR ;MAKE CHAR A CALL INCR ;INCREMENT LINES FOR ERRORS JMP MOVST4 ;STORE 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: MOV C,A ;SAVE CHAR IN C LDA IMFLG1 CPI IMON ;IMMEDIATE MODE ON ? MOV A,C ;GET CHAR BACK JZ MOVST2 ;YES..SKIP EX COMMENT PROCESSING CPI ';' ;FIRST ';'? JZ EXCOMM ;PROCESS POSSIBLE EX COMMENT MOVST2: CPI '^' ;CONTROL CHAR? JZ MOVST5 ;CONVERT CONTROL CHARACTERS CPI '$' ;PARAMETER OR CONTROL CHAR? CZ GTPARM ;SUBSTITUTE COMMAND PARAMETER OR CONTROL CHAR. MOVST3: STA LCHR ;SAVE LAST CHAR ENTERED CPI CR ;=CR? JNZ MOVST4 MOV C,A ;SAVE CHAR TEMPORARILY LDA OUTCNT ;GET CHAR OUTPUT FLAG ORA A ;ANY CHAR? MOV A,C JZ 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 JMP MOVSTR ; ; PREFIX WAS AN UPARROW (^), SO PROCESS CONTROL CHARS ; MOVST5: CALL GETCMD ;VALIDATE CONTROL CHARACTERS CPI ':' JZ REXC ;RE-EXECUTE CPI '?' JZ GCRW ;CR WAIT CPI '/' JZ GCRBW ;RING BELL AND WAIT FOR CPI '"' JZ UISET ;USER INPUT CPI '*' JZ GRNG ;CONTINUALLY RING BELL WHILE WAITING FOR 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 ; GCRW: MVI A,CRWAIT ;CONVERT '^?' TO CRWAIT FLAG JMP MOVST3 ; GCRBW: MVI A,CRBWAIT ;CONVERT '^/' TO CRBWAIT FLAG JMP MOVST3 ; ; ALLOW USER INPUT FROM NOW ON, BUT FIRST SKIP OUT REST OF LINE ; UISET: LDAX D ;GET NEXT CHAR ANI 7FH ;MASK IT CPI LF ;DONE? JZ UISET1 CPI 1AH ;EOF? JZ UISET1 INX D ;PT TO NEXT CHAR JMP UISET ;CONTINUE SKIPPING UISET1: MVI A,UICH ;CONTROL CHAR JMP MOVST3 ; GRNG: MVI A,RNG ;CONVERT '^*' TO RNG 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 ; ; CHECK TO SEE IF PREVIOUS CHAR WAS ALSO A ; AND FLUSH AS ZEX COMMENT IF SO ; EXCOMM: PUSH H LXI H,LCHR ;PT TO PREVIOUS CHAR CMP M ; DOUBLE ;? MOV M,A ;STORE CURRENT CHAR AS PREVIOUS CHAR POP H JNZ MOVST3 ;NO...CONTINUE MOV C,A ;SAVE CHAR 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 RET ;RETURN TO MAIN FLOW, WITH HL PTING TO NEXT BYTE ; 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... ; ; PLACE CHAR IN BUFFER; A=CHAR, HL PTS TO BUFFER LOC ; 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 ;STORE CHAR DCX H ;PT TO NEXT LOCATION (MOVING DOWN) RET ; ; CHECK TO SEE IF ZEX IS ALREADY ACTIVE, AND ABORT IF SO ; EXACTV: LHLD BDOS+1 ;CHECK FOR EX RECURSION INX H ;SKIP JMP INX H ;SKIP LOW INX H ;SKIP HIGH MVI A,'Z' ;LOOK FOR ZEX STORED JUST ABOVE THE BDOS JMP CMP M RNZ INX H 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 ;ZEX ALREADY PRESENT ; ; ABORT AND RETURN TO ZCPR2 ; CCPRET: LHLD CCPSTK ;RESTORE STACK SPHL RET ;RETURN TO CCP ; ; ERROR EXITS ; GETERR: LXI D,CMDER ;CONTROL CHARACTER INVALID CALL PRINT JMP LINE ;PRINT LINE # AND LINE AND EXIT ; NUMERR: LXI D,NONUM ;EXCESSIVE NUMBER 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 ;RE-EXECUTE CPI '?' RZ ;CR WAIT CPI '/' RZ ;CR WAIT AND RING BELL CPI '*' RZ ;RING BELL CPI '"' RZ ;USER INPUT 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 '@' ;GET CONTROL CODE RNC JMP 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: LDAX D ;GET CHAR AFTER THE $ INX D ;PT TO NEXT CHAR CPI '$' ;IF DOUBLE $, THEN STORE AS $ RZ CPI '^' ;UP ARROW RZ CPI '|' ;CARRIAGE RETURN RZ CPI '1' ;CHECK FOR VALID DIGIT (1-9) JC PRMERR CPI '9'+1 ;RANGE ERROR? JNC PRMERR SUI '1' ;GET ACTUAL # (ZERO RELATIVE) ADD A ;DOUBLE FOR OFFSET STA PRMNUM PUSH D ;SAVE PTRS PUSH H LXI H,PRMPNT ;PT TO PARAMETER PTR TABLE CPI PRMPNL-1 ;PARAMETER NUMBER WITHIN RANGE? JNC NOPARM ;> HIGHEST # MOV E,A MVI D,0 DAD D MOV E,M ;GET PARAMETER POINTER INX H MOV D,M POP H ;RESTORE PTR TO NEXT BYTE IN OUTPUT BUFFER BELOW ZEX MOV A,E ;ANY PARAM? ORA D JZ NOPARM ;NO PARAMETER PRESENT, TRY DEFAULTS ; ; MOVE PARAMETER PTED TO BY DE INTO BUFFER BELOW ZEX, 1ST BYTE PTED TO BY HL ; MOVPRM: LDAX D ;GET PARAMETER CHAR INX D ;PT TO NEXT ORA A ;DONE? JZ ENDPAR MOV M,A ;STORE IN BUFFER DCX H ;MOVE DOWN JMP MOVPRM ; ; PARAMETER PLACED IN MEMORY -- CONTINUE ; ENDPAR: POP D ;GET PTR TO NEXT CHAR IN LINE INX H ;PT TO LAST CHAR AND GET IT MOV A,M ;UPON RETURN, LAST CHAR STORED NORMALLY SO THAT RET ; OVERFLOW CHECK MAY BE DONE ; ; NO PARAMETER PTED TO ; NOPARM: PUSH H LXI H,PRMDFP ;TRY DEFAULT PARAMETERS LDA PRMNUM CPI PRMDFL-1 JNC NUMERR ;> 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 ; ; INCREMENT LINE COUNT, AND AFFECT ONLY HL (MUST NOT AFFECT A) ; 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.. CPI UICH ;USER INPUT CHAR? JZ CNTIN1 ANI 80H ;SPECIAL CONTROL? RNZ ;YES.. LDA PRTFLG CPI PSUP ;PRINT SUPPRESS FLAG? RZ ;YES.. LDA IMFLG1 CPI IMON ;IMMEDIATE MODE? RZ ;YES.. CNTIN1: LDA OUTCNT INR A STA OUTCNT 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 BEGGING 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' ZEXNAM: DB 'ZEX' LINEM: DB ' Error Line # $' EXACT: 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 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 ; ; INSURE 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 ; HL PTS TO TOP OF AVAILABLE MEMORY, DE PTS TO START OF ; TEXT BUFFER TO BE PROCESSED, BC PTS TO MULTIPLE COMMAND BUFFER ; OR BC=0 IF NO MULTIPLE COMMANDS ; ORG REL ; ZEX: STA NUICH ;SAVE END OF USER INPUT CHAR SHLD MEMTOP ;SAVE PTR TO TOP OF MEMORY XCHG ;PT TO START OF BUFFER SHLD REVBUF ;PTR TO FIRST CHAR SHLD SAVBUF PUSH H ;SAVE MULTIPLE COMMAND BUFFER LOCATION MOV H,B MOV L,C SHLD EXMBASE POP H MOV A,M ;GET 1ST CHAR 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 BDOS+1 ;GET WARM JUMP FOR STANDARD CCP MOV A,H SUI 8 MOV H,A MVI L,3 ;SET UP FOR WARM CCP JUMP SHLD CCPJMP LHLD WARM+1 ;SAVE WARM BOOT ADDRESS SHLD WARMPT LXI D,BSWARM ;SAVE OLD BIOS JUMPS MVI B,12 CALL MOVE ;MOVE BIOS JUMPS LHLD WARMPT XCHG LXI H,LOCJMP ;STORE NEW BIOS JUMPS 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 ;WARM RETURN XRA A ;A=0 STA UIFLG ;SET NO USER INPUT LHLD WARMPT ;SET WARM BOOT ADDRESS SHLD WARM+1 LHLD MEMTOP ;SET BDOS ENTRY ADDRESS SHLD BDOS+1 LXI D,BUFF ;DMA ADDRESS MVI C,26 ;SET DMA CALL BDOS LXI H,STARTM ;TELL USER WE'RE STILL HERE CALL PMSG LDA BDISK MOV C,A LHLD CCPJMP PCHL ;GOTO CONSOLE PROCESSOR ; ; JMP TABLE TO OVERLAY BIOS WITH NEW ZEX-BASED JUMPS ; LOCJMP: JMP NWARM ;WARM JMP BCONST ;CONST JMP NCONIN ;CONIN JMP NCONOT ;CONOT ; ; CONSOLE INPUT INTERCEPT ROUTINE ; NCONIN: LDA UIFLG ;USER INPUT ACTIVE? ORA A ;0=NO JNZ BCONIN ;GET INPUT VIA BIOS IF USER INPUT ACTIVE LXI H,0 DAD SP ;SAVE RETURN STACK LEVEL SHLD CONSTK LXI SP,MEMTOP ;SET USER STACK NCONNL: CALL BCONST ;GET CONSOLE STATUS ORA A JZ GETBUF ;GET CHARACTER FROM BUFFER CALL BCONIN ;GET CHARACTER CPI 'C'-'@' ;SEE IF TERMINATE CHARACTER JZ ZEXABRT CPI 'S'-'@' ;13H JNZ NCONEX CALL BCONIN ;WAIT FOR NEXT CHARACTER ANI 7FH LHLD REVBUF INX H MOV M,A SHLD REVBUF MVI A,'S'-'@' ;13H NCONEX: LHLD CONSTK ;RESTORE CALLER'S STACK SPHL RET ; ; RETURN NEXT CHAR FROM INPUT BUFFER ; GETBUF: LDA PSUPFL ;SET PRINT SUPPRESS FLAG FOR NCONOT STA OUTFLG GBUF1: CALL GETCHR ;GET NEXT CHARACTER CPI UICH ;USER INPUT? JZ UISTRT ;YES..SET USER INPUT PENDING FLAG CPI REXEC ;RE-EXECUTE? JZ REXECR ;YES..RESET BUFFER PTR CPI CRWAIT ;CR WAIT? JZ CRWRTN ;YES..WAIT FOR CR CPI CRBWAIT ;CR WAIT WITH RING BELL? JZ CRBWRTN ;YES..WAIT FOR CR AND RING BELL CPI RNG ;RING BELL? JZ RNGBELL ;YES..JUST RING THE BELL 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 ; ; ^" COMMAND ; UISTRT: MVI A,0FFH ;TURN ON FLAG STA UIFLG ;SET USER INPUT PENDING LHLD CONSTK ;RESTORE CALLER'S STACK SPHL JMP NCONIN ;GET CHAR FROM USER FOR NOW ; ; ^: COMMAND ; REXECR: LHLD SAVBUF ;START AT TOP OF BUFFER AGAIN SHLD REVBUF XRA A STA IMFLG ;RESET ALL FLAGS STA PSUPFL STA MSUPFL STA UIFLG JMP NCONNL ;...LOOP UNTIL ^C ; ; ^? COMMAND ; CRWRTN: CALL BCONIN ;GET INPUT CHAR CPI 'C'-'@' JZ ZEXABRT ;=^C CPI CR JZ CRWRTX ;= CPI ' ' JZ CRWRTX ;= MVI C,BELL CALL BCONOT ;<>CR JMP CRWRTN ; ; ^/ COMMAND ; CRBWRTN: LXI H,DELAY ;SET COUNTER CRBWR1: PUSH H ;SAVE COUNTER CALL BCONST ;CHECK STATUS POP H ;GET COUNTER ORA A ;SET FLAGS JNZ CRBWR2 DCX H ;COUNT DOWN MOV A,H ;DONE? ORA L JNZ CRBWR1 MVI C,BELL ;RING BELL CALL BCONOT JMP CRBWRTN CRBWR2: CALL BCONIN ;GET CHAR CPI 'C'-'@' ;ABORT? JZ ZEXABRT CPI CR ;CONT IF JNZ CRBWRTN ; ; ^| COMMAND ; CRWRTX: MOV C,A ;ECHO CR/LF CALL NCONOT MVI C,LF CALL NCONOT JMP GETBUF ; ; ^* COMMAND ; RNGBELL: MVI C,BELL ;RING BELL CALL NCONOT JMP GETBUF ; ; ^. COMMAND ; 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) ; ; ^# COMMAND ; 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 ; ; ^< AND ^> COMMANDS ; IMFLGS: STA IMFLG ;SET/RESET IMMEDIATE MODE FLAG JMP GETBUF ;GET NEXT CHARACTER ; ; CONSOLE OUTPUT INTERCEPT ROUTINE ; NCONOT: LDA OUTFLG ;PRINT SUPPRESSION? ORA A RNZ ;YES...IGNORE ECHO MOV A,C STA PMCHR LDA NUICH ;END OF USER INPUT? CMP C JNZ BCONOT XRA A ;A=0 STA UIFLG ;CLEAR USER INPUT JMP BCONOT ; ; GET NEXT CHAR FROM BUFFER AND TERMINATE ZEX IF END OF BUFFER ; 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 CALL BDOSRST ;RESTORE BDOS ADDRESS CALL PMCHRS ;RESTORE PROMPT LXI H,DONEM ;TELL USER WE'RE DONE CALL PMSG LHLD CONSTK ;GET OLD STACK SPHL JMP BCONIN ; ; RESTORE BDOS JMP IF NECESSARY ; BDOSRST: LHLD MEMTOP ;SEE IF BDOS+1=MEMTOP XCHG LHLD BDOS+1 MOV A,E SUB L MOV A,D SBB H RNZ ;DON'T REPLACE BDOS JUMP INX D ;PT TO BDOS JUMP LDAX D ;GET LOW ADDRESS MOV L,A ;... IN L INX D LDAX D ;GET HIGH ADDRESS MOV H,A ;... IN H SHLD BDOS+1 ;RESET BDOS JUMP RET ; ; ^C ABORT EXIT ; ZEXABRT: LXI SP,MEMTOP ;^C ABORTS EX LXI H,ABORTD ;ABORT CALL PMSG JMP WARMX ; WARMR: CALL PMCHRS ;RESTORE PROMPT LXI H,DONEM ;END MESSAGE CALL PMSG ; ; ABORT ZEX AND RETURN TO ZCPR2 ; WARMX: LXI H,DONEC ;CLASSIC FINISH CALL PMSG CALL MOVBAK ;MOVE JUMPS BACK LHLD EXMBASE ;MULTIPLE COMMAND LINES ENABLED? MOV A,H ;ANY ON? ORA L JZ WARM ;NONE ON IF ADDRESS IS ZERO, SO JUST WARM BOOT ; ; THIS SECTION OF CODE CLEARS THE MULTIPLE COMMAND LINE BUFFER ; MOV D,H ;DE PTS TO MULTIPLE COMMAND BUFFER ALSO MOV E,L PUSH H ;SAVE PTR LXI H,4 ;PT TO FIRST CHAR OF LINE DAD D MVI M,0 ;SET FIRST CHAR OF LINE TO ZERO FOR EOL XCHG ;DE PTS TO FIRST CHAR OF LINE POP H ;GET PTR MOV M,E ;STORE ADDRESS OF EMPTY COMMAND (EOL) INX H MOV M,D JMP WARM ; ; SUBROUTINES ; MOVBAK: LHLD WARMPT ;MOVE OLD JUMP TABLE BACK TO BIOS XCHG LXI H,BSWARM MVI B,12 CALL MOVE JMP F121 ;CALL 1.2.1 FIX FOR MBASIC 1.1.2 ; 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 DONEC1 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 ; ; REPLACE ZEX ROUTINE JUMPS WITH BIOS JUMPS ; F121: LXI H,BSWARM ; INSURE 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 JMP MOVE ; 1.1.2 ; ; WORKING STORAGE AREA ; ABORTD: DB CR,LF,'(ZEX Aborted)',CR,LF,'$' STARTM: DB CR,LF,'(ZEX Active)$' DONEM: DB CR,LF,'(ZEX Completed)',CR,LF DONEC: DB 'By Your Command ' DONEC1: DB '>$' ; REPT 12 DW 0 ENDM MEMTOP: DW 0 EXMBASE: DW 0 REVBUF: DW 0 SAVBUF: DW 0 CCPJMP: DW 0 WARMPT: DW 0 ; ; ORIGINAL BIOS JMP TABLE ; BSWARM: JMP $ BCONST: JMP $ BCONIN: JMP $ BCONOT: JMP $ ; PMCHR: DB 0 PSUPFL: DB 0 OUTFLG: DB 0 NUICH: DB 0 IMFLG: DB 0 MSUPFL: DB 0 UIFLG: DB 0 CONSTK: 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