; ; Program: MU3 ; Author: Richard Conn ; Version: 1.0 ; Date: 30 June 84 ; Previous Versions: None ; vers equ 10 z3env equ 0f400h ; ; MU3 is the ZCPR3 Memory Utility. It allows the user to display ; blocks of memory, edit them, and perform general memory-oriented ; manipulation. See the file MU3.HLP for usage details. ; ; ; General Equates ; bs equ 08h cr equ 0dh lf equ 0ah fcb equ 5ch dim equ 1 ;goto standout mode bright equ 2 ;exit standout mode EOLCH EQU 0 ;END OF LINE CHAR SEPCH EQU ',' ;SEPARATOR CHAR EROW EQU 6 ;FIRST ROW OF EDITOR DISPLAY ECOL EQU 4 ;FIRST COL OF EDITOR DISPLAY ECOLC EQU ECOL+16*3+8 ;FIRST COL OF EDITOR CHAR DISPLAY ECURS EQU '>' ;EDITOR CURSOR PRROW EQU 22 ;PROMPT ROW PRCOL EQU 10 ;PROMPT COLUMN PRCOLI EQU PRCOL+15 ;PROMPT INPUT COL ERROW EQU 23 ;ERROR MESSAGE ROW ERCOL EQU 15 ;ERROR MESSAGE COLUMN ; ; SYSLIB/Z3LIB/VLIB Externals ; ext z3vinit,envptr,codend,putcl ext cls,gotoxy,ereol,at,vprint,stndout ext cout,crlf,cin,caps ext bline,sksp ext phl4hc,pa2hc,phlfdc ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3vinit ;initialize the ZCPR3 Env and the VLIB Env ; ; DEFINE FREE SPACE ; CALL CODEND ;DETERMINE ADDRESS MVI M,126 ;126 CHARS INPUT ALLOWED SHLD BUFFER ;SET PTR ; ; SET UP ARROW KEYS ; LHLD ENVPTR ;PT TO ENVIRONMENT DESCRIPTOR LXI D,80H+10H ;PT TO ARROW KEY INFO DAD D LXI D,EDCURT ;PT TO CURSOR TABLE MVI B,4 ;4 ARROW KEYS ARROW: MOV A,M ;GET CHAR STAX D ;STORE CHAR INX H ;PT TO NEXT INX D ;PT TO NEXT ENTRY INX D INX D DCR B ;COUNT DOWN JNZ ARROW ; ; Check for Command Line Parameter ; lxi h,fcb+1 ;pt to first char mov a,m ;get char cpi ' ' ;no param? jnz pcheck lhld envptr ;pt to environment descriptor jmp mu3 ; ; We have a parameter ; pcheck: cpi '/' ;help? jz help call hexin ;convert to binary xchg ;HL=value jmp mu3 ; ; Print help message ; help: call vprint db cr,lf,'Syntax:' db cr,lf,' MU3 <-- Invoke MU3 at Env Desc' db cr,lf,' MU3 <-- Invoke MU3 at Address' db 0 ret ; ; Erase to EOL ; If fct not supported, send out B spaces and B backspaces ; vereol: call ereol ;try erase rnz push b ;save B mvi a,' ' ;send spaces call vereol1 pop b ;get B mvi a,bs ;send backspaces vereol1: call cout ;send char in A dcr b jnz vereol1 ret ; ; Clear Screen ; If fct not supported, write 24 CRLFs ; vcls: call cls ;try clear rnz push b ;save B mvi b,24 ;count vcls1: call crlf dcr b jnz vcls1 pop b ret ; ; Run MU3 ; HL contains starting address ; mu3: SHLD BLOCK ;SAVE PTR TO BLOCK ; ; REFRESH EDIT SCREEN ; EDIT0: CALL VCLS ;NEW SCREEN CALL AT DB 2,26 ;ROW 2, COL 26 CALL VPRINT ;BANNER DB 'MU3 Memory Editor, Version ' DB (VERS/10)+'0','.',(VERS MOD 10)+'0' DB 0 CALL AT ;POSITION FOR VALUE TEXT DB 3,67 CALL VPRINT DB DIM,'Value',BRIGHT,0 MVI H,EROW+9 ;POSITION FOR COMMAND DISPLAY MVI L,1 CALL GOTOXY ;POSITION CURSOR CALL VPRINT ;PRINT COMMAND SUMMARY DB ' -- Movement --' DB ' -------------- Operation ---------------',CR,LF DB ' ^E ' DB 'A',DIM,' Enter Address ',BRIGHT DB ' +',DIM,' Next Block',BRIGHT,CR,LF DB ' ^ ' DB 'H',DIM,' Hex Calculator ',BRIGHT DB ' -',DIM,' Last Block',BRIGHT,CR,LF DB ' ^S <-+-> ^D ' DB 'N',DIM,' Enter Hex Numbers ',BRIGHT DB ' ^R',DIM,' Replot Screen',BRIGHT,CR,LF DB ' v ' DB 'T',DIM,' Enter Text ',BRIGHT DB ' ^C',DIM,' Exit MU3',BRIGHT,CR,LF DB ' ^X ' DB 'C',DIM,' Enter Command Line',BRIGHT DB 0 ; ; REENTER MU3 WITH PTRS RESET ; MU3R: XRA A ;A=0 STA EINDEX ;SET INDEX TO 0 (FIRST ELEMENT) STA EDERR ;SET NO PREVIOUS ERROR CALL EDPLOT ;PLOT BUFFER DATA ; ; INPUT EDITOR COMMAND ; EDITCMD: CALL EDERCL ;CLEAR EDITOR INVALID COMMAND MESSAGE EDITCMD1: CALL PRMSG ;POSITION AT PROMPT MESSAGE DB DIM,'MU3 Command?',BRIGHT,0 CALL PRINP ;POSITION AT PROMPT INPUT DB 0 CALL CIN ;GET CHAR CALL CAPS ;CAPITALIZE MOV B,A ;COMMAND IN B LXI H,EDCURT ;PROCESS CURSOR COMMANDS FIRST CALL CMD ;PROCESS COMMAND LXI H,ECMDTBL ;EDITOR COMMAND TABLE CALL CMD ;PROCESS COMMAND MVI A,0FFH ;SET ERROR FLAG STA EDERR CALL ERMSG ;ERROR MESSAGE DB 'Invalid Command',0 JMP EDITCMD1 ; ; Position at Prompt Message and Print it ; PRMSG: CALL AT ;POSITION DB PRROW,PRCOL JMP VPRINT ;PRINT IT ; ; Position at Prompt Input and Print Prompt ; PRINP: CALL AT ;POSITION DB PRROW,PRCOLI JMP VPRINT ;PRINT IT ; ; Position at Error Message and Print It ; ERMSG: CALL AT ;POSITION DB ERROW,ERCOL JMP VPRINT ;PRINT IT ; ;INPUT ERROR ; WHAT: MVI A,0FFH ;SET ERROR FLAG STA EDERR CALL ERMSG DB 'Value Error',0 JMP EDITCMD1 ; ;Command Table Search and Execute ; CMD: MOV A,M ;CHECK FOR END OF TABLE ORA A RZ ;COMMAND NOT FOUND CMP B ;MATCH? JZ CMDRUN INX H ;SKIP TO NEXT ENTRY IN TABLE INX H INX H JMP CMD ; ;RUN COMMAND ; CMDRUN: INX H ;PT TO LOW ADDRESS MOV E,M INX H ;PT TO HIGH ADDRESS MOV D,M XCHG POP PSW ;CLEAR STACK PCHL ;RUN ROUTINE ; ;PLOT BUFFER DATA ; EDPLOT: MVI H,EROW-1 ;SET ROW MVI L,ECOL ;SET COLUMN CALL GOTOXY ;POSITION CURSOR CALL VPRINT DB DIM DB ' 0 1 2 3 4 5 6 7 8 9 A B C D E F' DB BRIGHT,0 INR H ;NEXT ROW CALL GOTOXY ;POSITION CURSOR XCHG ;POSITION IN DE LHLD BLOCK ;PT TO DATA MVI B,8 ;8 LINES ; ;Print Next Line on Screen ; EDIT00: CALL STNDOUT ;GO DIM MOV A,H ;OUTPUT ADDRESS CALL PA2HC MOV A,L CALL PA2HC CALL VPRINT DB ':',BRIGHT,' ',0 MVI C,16 ;16 ELEMENTS EDIT01: MOV A,M ;GET BYTE CALL PA2HC ;PRINT AS HEX CALL SPACE ;PRINT 1 SPACE INX H ;PT TO NEXT DCR C ;COUNT DOWN JNZ EDIT01 XCHG ;POSITION AGAIN INR H ;NEXT ROW CALL GOTOXY XCHG DCR B ;COUNT DOWN JNZ EDIT00 MVI H,EROW ;RESET ROW MVI L,ECOLC ;RESET COL CALL GOTOXY ;POSITION CURSOR XCHG ;POSITION IN DE LHLD BLOCK ;PT TO DATA MVI B,8 ;8 LINES EDIT02: CALL BAR ;PRINT BAR MVI C,16 ;16 ELEMENTS EDIT03: MOV A,M ;GET BYTE ANI 7FH ;MASK MSB CPI 7FH ;DON'T PRINT 7FH JZ EDIT7F CPI ' ' ;SPACE OR MORE? JNC EDIT04 EDIT7F: MVI A,'.' ;PRINT DOT EDIT04: CALL COUT ;PRINT BYTE INX H ;PT TO NEXT DCR C ;COUNT DOWN JNZ EDIT03 CALL BAR ;PRINT ENDING BAR XCHG ;POSITION AGAIN INR H ;NEXT ROW CALL GOTOXY XCHG DCR B ;COUNT DOWN JNZ EDIT02 CALL EDCUR ;POSITION CURSOR RET ; ;EDITOR COMMAND TABLE ; ECMDTBL: DB CR ;NOP DW EDITCMD DB 'C'-'@' ;^C = EXIT MU3 DW EDCC DB 'R'-'@' ;^R = REFRESH DW EDIT0 DB 'E'-'@' ;^E=UP DW EDUP DB 'X'-'@' ;^X=DOWN DW EDDOWN DB 'D'-'@' ;^D=RIGHT DW EDRIGHT DB 'S'-'@' ;^S=LEFT DW EDLEFT DB ' ' ;NOP DW EDITCMD DB '+' ;ADVANCE DW EDITPLUS DB '-' ;BACKUP DW EDITMINUS DB 'A' ;ADDRESS DW EDITADR DB 'C' ;COMMAND LINE DW EDITCL DB 'H' ;HEX CALC DW EDITCALC DB 'N' ;CHANGE NUMBERS DW EDITHEX DB 'T' ;CHANGE TEXT DW EDITALP DB 0 ;END OF TABLE ; ; ARROW KEY DEFINITONS FROM TCAP ; EDCURT: DB 0 ;0 INDICATES NO ARROW KEYS DW EDUP DB 0 DW EDDOWN DB 0 DW EDRIGHT DB 0 DW EDLEFT DB 0 ;END OF TABLE ; ;Enter Command Line ; EDITCL: CALL EDERCL ;CLEAR ERROR LINE CALL CRLF ;NEW LINE CALL VPRINT ;PROMPT INPUT DB DIM,'Command Line? ',BRIGHT,0 CALL RDBUF ;INPUT TEXT CALL PUTCL ;STORE COMMAND LINE JMP CRLF ;NEW LINE ; ;Enter ASCII Chars ; EDITALP: CALL EDERCL ;CLEAR ERROR LINE CALL PRINP ;PROMPT INPUT DB DIM,'Enter Text ( for Hex)',BRIGHT DB CR,LF,' --> ',0 CALL RDBUF ;INPUT TEXT WITHOUT PROMPT CALL EDPRCL ;CLEAR PROMPT LINE LDA EINDEX ;PT TO POSITION XCHG LHLD BLOCK ;COMPUTE OFFSET XCHG ADD E MOV E,A MOV A,D ACI 0 MOV D,A ;DE PTS TO BYTE, HL PTS TO TEXT EDITA1: MOV A,M ;GET CHAR CPI EOLCH ;EOL? JZ EDITA2 ;REFRESH SCREEN CALL GETVAL ;GET ASCII OR VALUE STAX D ;UPDATE BYTE INX H ;PT TO NEXT INPUT CHAR INR E ;PT TO NEXT BUFFER BYTE JNZ EDITA1 EDITA2: CALL EDPLOT ;REPLOT JMP EDITCMD1 ;DONE-REFRESH SCREEN ; ;Calculate Sum and Differences ; EDITCALC: CALL EDERCL ;CLEAR ERROR LINE CALL PRINP ;PROMPT INPUT DB DIM,'Enter Two Hex Numbers - ',BRIGHT,0 CALL RDBUF ;INPUT TEXT CALL EDPRCL ;CLEAR PROMPT LINE CALL SKSP ;SKIP TO NON-SPACE MOV A,M ;ANY INPUT? ORA A ;0=NO JZ EDITCMD1 CALL HEXIN ;EVALUATE FIRST NUMBER CALL SKSP ;SKIP TO 2ND NUMBER PUSH D ;SAVE FIRST NUMBER CALL HEXIN ;EVALUATE 2ND NUMBER POP H ;GET FIRST NUMBER CALL ERMSG ;PRINT ERROR MESSAGE DB 0 CALL PHL4HC ;PRINT FIRST NUMBER CALL VPRINT DB DIM,' and ',BRIGHT,0 XCHG CALL PHL4HC ;PRINT 2ND NUMBER XCHG CALL VPRINT DB ' ',DIM,'Sum = ',BRIGHT,0 PUSH H DAD D CALL NUMOUT POP H CALL VPRINT DB ' ',DIM,'Diff = ',BRIGHT,0 MOV A,L ;HL=HL-DE SUB E MOV L,A MOV A,H SBB D MOV H,A CALL NUMOUT JMP EDITCMD1 ; ;Output number in HL in Hex and Decimal ; NUMOUT: CALL PHL4HC ;HEX CALL VPRINT DB ' (',0 CALL PHLFDC ;DECIMAL FLOATING MVI A,')' ;CLOSE PAREN JMP COUT ; ;Enter Numbers ; EDITHEX: CALL EDERCL ;CLEAR ERROR LINE CALL PRINP ;PROMPT INPUT DB DIM,'Enter Hex Numbers (#nn for Dec)' DB BRIGHT DB CR,LF,' --> ',0 CALL RDBUF ;INPUT TEXT WITHOUT PROMPT CALL EDPRCL ;CLEAR PROMPT LINE LDA EINDEX ;PT TO POSITION XCHG LHLD BLOCK ;COMPUTE OFFSET XCHG ADD E MOV E,A MOV A,D ACI 0 MOV D,A ;DE PTS TO BYTE, HL PTS TO TEXT EDITH1: MOV A,M ;GET HEX DIGIT CPI EOLCH ;EOL? JZ EDITA2 ;REFRESH SCREEN CPI ' ' ;SKIP SPACES JNZ EDITH2 INX H ;SKIP SPACE JMP EDITH1 EDITH2: PUSH D ;SAVE PTR CALL HEXIN ;GET VALUE AND POSITION HL MOV A,E ;... IN A POP D ;GET PTR STAX D ;PUT BYTE INR E ;ADVANCE TO NEXT BYTE JNZ EDITH1 JMP EDITA2 ;DONE-REFRESH ; ;Clear Editor Invalid Command Message ; EDERCL: LDA EDERR ;PREVIOUS ERROR? ORA A ;0=NO RZ XRA A ;CLEAR FLAG STA EDERR CALL ERMSG ;CLEAR ERROR MESSAGE DB 0 MVI B,40 ;40 CHARS MAX JMP VEREOL ; ;CLEAR PROMPT LINE ; EDPRCL: CALL PRINP ;PROMPT LINE DB 0 MVI B,40 ;40 POSITIONS CALL VEREOL ;CLEAR TO EOL OR 40 CHARS CALL AT ;USER INPUT DB ERROW,1 MVI B,79 ;79 POSITIONS JMP VEREOL ; ;Input Address ; EDITADR: CALL VPRINT DB 'Address? ',0 CALL RDBUF ;GET USER INPUT CALL SKSP ;SKIP LEADING SPACES MOV A,M ;EMPTY LINE? ORA A JZ MU3R CALL HEXIN ;CONVERT FROM HEX XCHG ;HL = ADDRESS SHLD BLOCK JMP MU3R ;REENTER ; ;Advance to Next Block ; EDITPLUS: LHLD BLOCK ;ADVANCE TO NEXT BLOCK LXI D,128 ;128 BYTES DAD D SHLD BLOCK CALL EDPLOT ;REPLOT DATA JMP EDITCMD ; ;Backup to Last Block ; EDITMINUS: LHLD BLOCK ;BACKUP TO LAST BLOCK LXI D,-128 ;128 BYTES DAD D SHLD BLOCK CALL EDPLOT ;REPLOT DATA JMP EDITCMD ; ;Exit MU3 ; EDCC: CALL EDERCL ;CLEAR ERROR LINE JMP CRLF ;NEW LINE ; ;EDIT MOVE: UP ; EDUP: CALL EDCCUR ;CLEAR CURSOR LDA EINDEX ;BACKUP INDEX BY 16 SUI 16 ; ;Common EDIT MOVE Routine - on input, A=new index ; EDMOVE: ANI 7FH ;MOD 128 STA EINDEX CALL EDCUR ;SET CURSOR JMP EDITCMD ; ;EDIT MOVE: DOWN ; EDDOWN: CALL EDCCUR ;CLEAR CURSOR LDA EINDEX ;INCREMENT INDEX BY 16 ADI 16 JMP EDMOVE ;COMMON ROUTINE ; ;EDIT MOVE: RIGHT ; EDRIGHT: CALL EDCCUR ;CLEAR CURSOR LDA EINDEX ;INCREMENT INDEX BY 1 INR A JMP EDMOVE ;COMMON ROUTINE ; ;EDIT MOVE: LEFT ; EDLEFT: CALL EDCCUR ;CLEAR CURSOR LDA EINDEX ;DECREMENT INDEX BY 1 DCR A JMP EDMOVE ;COMMON ROUTINE ; ;EDIT SUBROUTINE: EDCUR ; Position Editor Cursor at EINDEX ;EDIT SUBROUTINE: EDCCUR ; Clear Editor Cursor at EINDEX ; EDCUR: PUSH H ;SAVE HL MVI C,ECURS ;CURSOR CHAR CALL EDSETCUR CALL AT ;UPDATE DATA DB 3,74 LDA EINDEX ;PT TO BYTE AT CURSOR LHLD BLOCK ADD L MOV L,A MOV A,H ACI 0 MOV H,A ;HL PTS TO BYTE AT CURSOR MOV A,M ;GET BYTE CALL PA2HC ;PRINT AS HEX CALL SPACE MOV A,M ;GET BYTE POP H ;RESTORE HL ANI 7FH ;MASK CPI 7FH ;7FH AS DOT JZ EDC7F CPI ' ' ;OUTPUT CHAR OR DOT JNC COUT EDC7F: MVI A,'.' ;DOT JMP COUT EDCCUR: MVI C,' ' ;CLEAR CURSOR EDSETCUR: CALL EDROW ;COMPUTE ROW ANI 0FH ;COMPUTE COL MOD 16 MOV B,A ;RESULT IN B ADD A ;*2 ADD B ;*3 ADI ECOL+6 ;ADD IN COL DCR A ;SUBTRACT 1 MOV L,A ;COL POSITION SET CALL GOTOXY ;POSITION CURSOR MOV A,C ;OUTPUT CHAR JMP COUT ; ;Compute Row from EINDEX ; EDROW: LDA EINDEX ;GET INDEX MOV B,A ;SAVE IN B RRC ;DIVIDE BY 16 RRC RRC RRC ANI 0FH ;MASK FOR LSB ONLY ADI EROW ;COMPUTE ROW MOV H,A ;ROW SET MOV A,B ;GET INDEX RET ; ;PRINT A SPACE ; SPACE: MVI A,' ' JMP COUT ; ;PRINT AN BARISK IN REV VIDEO ; BAR: CALL VPRINT DB DIM,'|',BRIGHT,0 RET ; ;Get value from input buffer ; GETVAL: MOV A,M ;GET NEXT CHAR CPI '<' ;HEX ESCAPE? RNZ ;NO, RETURN ;"<<" means one "<" INX H MOV A,M CPI '<' RZ ;Got hex PUSH D CALL HEXIN ;GET VALUE CPI '>' ;PROPER DELIM? MOV A,E ;GET VALUE POP D RZ ; ;ERROR CONDITION IN SUBROUTINE - CLEAR STACK AND FLAG ERROR ; SERR: POP PSW ;CLEAR STACK JMP WHAT ;ERROR ; ;Input Number from Command Line -- Assume it to be Hex ; Number returned in DE ; HEXIN: LXI D,0 ;INIT VALUE MOV A,M CPI '#' ;DECIMAL? JZ HDIN ;MAKE DECIMAL ; HINLP: MOV A,M ;GET CHAR CALL CAPS ;CAPITALIZE CPI CR ;EOL? RZ CPI EOLCH ;EOL? RZ CPI SEPCH RZ CPI ' ' ;SPACE? RZ CPI '-' ;'THRU'? RZ CPI '>' RZ INX H ;PT TO NEXT CHAR CPI '0' ;RANGE? JC SERR CPI '9'+1 ;RANGE? JC HINNUM CPI 'A' ;RANGE? JC SERR CPI 'F'+1 ;RANGE? JNC SERR SUI 7 ;ADJUST FROM A-F TO 10-15 ; HINNUM: SUI '0' ;CONVERT FROM ASCII TO BINARY XCHG DAD H ;MULT PREVIOUS VALUE BY 16 DAD H DAD H DAD H ADD L ;ADD IN NEW DIGIT MOV L,A XCHG JMP HINLP ; HDIN: INX H ;SKIP '#' ; ;Input Number in Command Line as Decimal ; Number is returned in DE ; DECIN: LXI D,0 MOV A,M ; GET 1ST CHAR CPI '#' ; HEX? JNZ DINLP INX H ; PT TO DIGIT JMP HINLP ; DO HEX PROCESSING ; DINLP: MOV A,M ;GET DIGIT CALL CAPS ;CAPITALIZE CPI '0' ;RANGE? RC CPI '9'+1 ;RANGE? RNC SUI '0' ;CONVERT TO BINARY INX H ;PT TO NEXT PUSH H MOV H,D MOV L,E DAD H ;X2 DAD H ;X4 DAD D ;X5 DAD H ;X10 ADD L ;ADD IN DIGIT MOV L,A MOV A,H ACI 0 MOV H,A XCHG ;RESULT IN DE POP H JMP DINLP ; ; READ LINE FROM USER INTO INPUT LINE BUFFER ; RDBUF: LHLD BUFFER ;PT TO BUFFER XRA A ;DON'T CAPITALIZE JMP BLINE ;INPUT LINE ROUTINE ; ;EDITOR BUFFERS ; BLOCK: DS 2 ;ADDRESS OF CURRENT BLOCK BUFFER: DS 2 ;PTR TO FREE SPACE EINDEX: DS 1 ;INDEX ENTRY EDERR: DS 1 ;ERROR FLAG EDRUN: DS 1 ;FLAG SAYING THAT EDITOR IS RUNNING end