;******************************************************** ;* * ;* BASIC HEX MONITOR FOR Z-80 PROCESSORS * ;* 3-Aug-80 * ;* * ;******************************************************** ; ; ; ; PROMPT: CALL PNEXT DEFB CR,LF DEFM '* ' DEFB EOT LD HL,LINBUF LD C,32 CALL GETLIN ;INPUT A BUFERED CONSOLE LINE JR C,WHAT-$ ;PRINT 'WHAT ?' IF INPUT ERROR XOR A LD (ESCFLG),A CALL CRLFS LD A,(LINBUF) ;GET FIRST CHARACTER IN LINE CP CR JR Z,PROMPT-$ ;JUMP IF A NULL LINE LD HL,CMDTAB ;SEARCH FOR A MATCHING CHARACTER LD BC,CMDSIZ/3 ; IN COMMAND SEARCH TABLE CALL SEARCH JR NZ,WHAT-$ ;TRY AGAIN IF SEACRH FAILS PUSH BC LD IY,LINBUF+1 CALL PARAMS ;INPUT NUMERIC PARAMETERS FROM POP IX ; LINE BUFFER AND TEST IF ERROR JR C,WHAT-$ LD HL,(PARAM1) LD DE,(PARAM2) LD BC,(PARAM3) CALL CALLX ;CALL SUBROUTINE @ IX JR NC,PROMPT-$ ;GO BACK TO PROMPT IF NO ERRORS WHAT: CALL PNEXT DEFM ' what ?' DEFB 'G'-64 ;SAY 'what ?' AND BEEP THE BELL DEFB EOT JR PROMPT-$ ; ; CALLX: JP (IX) ;CALL SUBROUTINE @ IX ; ; ; CMDTAB: DEFB 'R' DEFB 'O' DEFB 'I' DEFB 'G' DEFB 'T' DEFB 'F' DEFB 'M' DEFB 'C' DEFB 'B' DEFB 'D' DEFB 'S' DEFW SWITCH ;SWITCH CONSOLE OUTPUT VECTOR DEFW MEMDMP ;DUMP MEMORY IN HEX/ASCII DEFW BOOT ;BOOT UP CP/M DEFW BLOCK ;MEMORY BLOCK MOVE DEFW VIEW ;MEMORY EXAMINE/CHANGE DEFW FILL ;FILL MEMORY DEFW TEST ;RAM DIAGNOSTIC DEFW GOTO ;JUMP TO MEMORY LOCATION DEFW INCMD ;READ FROM INPUT PORT DEFW OUTCMD ;WRITE TO OUTPUT PORT DEFW DSKCMD ;DISPLAY DISK SECTOR DATA CMDSIZ EQU $-CMDTAB ; ; ;******************************************************** ;* * ;* MONITOR COMMAND ACTION ROUTINES PACKAGE * ;* * ;******************************************************** ; ; ; ; ; ; -- DISK BOOT LOADER COMMAND -- ; BOOT: LD C,0 ;SELECT DRIVE 0 FOR BOOT LOAD CALL SELECT JR NZ,DSKERR-$ CALL HOME ;HOME HEAD TO TRACK 0 JR NZ,DSKERR-$ ;ERROR IF NOT READY OR AT TR0 LD HL,0080H ;POINT TO CP/M READ BUFFER LD C,1 ;SELECT SECTOR 1 CALL READ ;READ TRACK 0/ SECTOR 1 JR NZ,DSKERR-$ POP AF ;CLEAN UP STACK JP 0080H ;GO EXECUTE LOADER ; ; ; -- DISK SECTOR READ COMMAND -- ; DSKCMD: CP 3 ;CHECK PARAMETER COUNT SCF RET NZ LD C,L ;USE FIRST ARG AS UNIT# CALL SELECT JR NZ,DSKERR-$ LD HL,PARAM2 LD C,(HL) ;USE SECOND ARG AS TRACK# CALL SEEK JR NZ,DSKERR-$ LD HL,PARAM3 LD C,(HL) ;USE THIRD ARG AS SECTOR# LD HL,0080H CALL READ SET 0,A ;MARK ERROR BYTE AS DUE TO READ JR NZ,DSKERR-$ LD HL,0080H LD DE,8 JP DUMP ;DUMP DISK READ BUFFER AND RETURN ; ; DSKERR: LD C,A ;SAVE 1771 STATUS CALL PNEXT DEFM 'disk error ' DEFB EOT LD B,8 ;PRINT 1771 ERROR BYTE IN BINARY DSKR2: XOR A RL C ADC A,'0' ;TRANSFORM A INTO ASCII '1' OR '0' CALL OUTPUT DJNZ DSKR2-$ ;REPEAT FOR 8 BITS OR A RET ; ; ; ; -- MEMORY DUMP COMMAND -- ; MEMDMP: DEC A ;CHECK PARAMETER COUNT JR Z,MDMP2-$ DEC A JR Z,MDMP3-$ MDMP1: LD HL,(LAST) MDMP2: LD DE,16 JR MDMP3B-$ MDMP3: EX DE,HL SBC HL,DE ;DERRIVE BYTECOUNT FOR DUMP RANGE LD B,4 MDMP3A: SRL H ;DIVIDE BYTECOUNT BY 16 RR L DJNZ MDMP3A-$ INC HL EX DE,HL MDMP3B: CALL DUMP ;DUMP DE*16 BYTES STRTING AT HL LD (LAST),HL RET ; ; DUMP: PUSH HL ;SAVE STARTING ADDRESS CALL PUT4HS ;PRINT STARTING ADDRESS IN HEX CALL SPACE LD B,16 DUMP2: LD A,(HL) ;GET A DATA BYTE @ HL INC HL CALL PUT2HS ;PRINT THE DATA IN HEX DJNZ DUMP2-$ ;REPEAT 16 TIMES POP HL ;RESTORE STARTING ADDRESS LD B,16 DUMP3: LD A,(HL) ;GET BACK DATA BYTE @ HL INC HL RES 7,A CP 20H JR C,DUMP4-$ CP 7FH JR C,DUMP5-$ DUMP4: LD A,'.' ;PRINT A DOT IF DATA < 20 OR > 7F DUMP5: CALL OUTPUT ;PRINT ASCII CHARACTER IN A DJNZ DUMP3-$ CALL CRLFS RET NZ ;EXIT IF ESCAPE REQUEST IS INDICATED DEC DE LD A,D OR E JR NZ,DUMP-$ RET ; ; ; ; ; -- MEMORY EXAMINE COMMAND -- ; VIEW: CALL MDATA CALL ECHO CP CR JR Z,VIEW4-$ CP '-' JR Z,VIEW5-$ VIEW2: CALL ASCHEX CCF RET NC RLCA RLCA RLCA RLCA LD C,A CALL ECHO CALL ASCHEX CCF RET NC OR C VIEW3: LD (HL),A CALL CHECK VIEW4: INC HL INC HL VIEW5: DEC HL JR VIEW-$ ; ; ; ; -- JUMP TO MEMORY LOCATION COMMAND -- ; GOTO: DEC A ;CHECK PARAMETER COUNT SCF RET NZ PUSH HL POP IX CALL CALLX ;CALL ADDRESS PASSED IN HL OR A RET ;RETURN IF WE GET BACK AGAIN ; ; ; ; -- MEMORY READ/WRITE DIAGNOSTIC COMMAND -- ; TEST: CP 2 ;CHECK PARAMETER COUNT SCF RET NZ INC DE LD E,D ;GET ENDING PAGE ADDRESS INTO E LD D,H ;GET STARTING PAGE ADDRESS INTO D LD B,0 ;INITIALIZE PASS COUNTER TEST1: LD H,D ;POINT HL TO START OF BLOCK LD L,0 TEST2: LD A,L XOR H ;GENERATE TEST BYTE XOR B LD (HL),A ;STORE BYTE IN RAM INC HL LD A,H CP E ;CHECK FOR END OF TEST BLOCK JR NZ,TEST2-$ ; NOW READ BACK EACH BYTE & COMPARE LD H,D LD L,0 ;POINT HL BACK TO START TEST3: LD A,L XOR H ;RE-GENERATE TEST BYTE DATA XOR B CALL CHECK ;VERIFY MEMORY DATA STILL GOOD RET NZ ;EXIT IF ESCAPE REQUEST IS INDICATED INC HL ; ELSE GO ON TO NEXT BYTE LD A,H CP E ;CHECK FOR END OF BLOCK JR NZ,TEST3-$ INC B ;BUMP PASS COUNT LD A,'+' CALL OUTPUT ;PRINT '+' AND ALLOW FOR EXIT JR Z,TEST1-$ ;DO ANOTHER PASS IF NO ESCAPE RET ; ; ; CHECK: CP (HL) RET Z ;RETURN IF (HL)=A PUSH AF CALL MDATA ;PRINT WHAT WAS ACTUALLY READ CALL PNEXT DEFM 'should=' DEFB EOT POP AF JP PUT2HS ;PRINT WHAT SHOULD HAVE BEEN READ ; ; MDATA: CALL CRLFS CALL PUT4HS LD A,(HL) JP PUT2HS ; ; ; ; -- FILL MEMORY WITH CONSTANT COMMAND -- ; FILL: CP 3 ;CHECK IF PARAMETER COUNT=3 SCF RET NZ FILL1: LD (HL),C PUSH HL OR A SBC HL,DE ;COMPARE HL TO END ADDRESS IN DE POP HL INC HL ;ADVANCE POINTER AFTER COMPARISON JR C,FILL1-$ RET ; ; ; ; ; -- MEMORY BLOCK MOVE COMMAND -- ; BLOCK: CP 3 ;CHECK IF PARAMETER COUNT=3 SCF RET NZ CALL BLOCAD LD A,C OR B RET Z ;EXIT NOW IF BC=0 LDIR RET ; ; ; BLOCAD: EX DE,HL OR A ;CLEAR CARRY SBC HL,DE ;GET DIFFRENCE BETWEEN EX DE,HL ;HL & DE FOR BYTECOUNT PUSH DE PUSH BC POP DE ;GET OLD BC INTO DE POP BC INC BC ;GET COUNT+1 INTO BC RET ; ; ; ; ; -- READ FROM INPUT PORT COMMAND -- ; INCMD: DEC A ;CHECK IF PARAMETER COUNT=1 SCF RET NZ LD C,L ;POINT C TO INPUT PORT IN1: CALL CRLFS LD A,C CALL PUT2HS IN A,(C) CALL PUT2HS CALL ECHO CP CR JR Z,IN2-$ CP '-' JR Z,IN3-$ OR A RET IN2: INC C INC C IN3: DEC C JR IN1-$ ; ; ; ; -- WRITE TO OUTPUT PORT COMMAND -- ; OUTCMD: CP 2 ;CHECK IF PARAMETER COUNT=2 SCF RET NZ LD C,L ;POINT C TO OUTPUT PORT OUT (C),E ;OUTPUT DATA PASSED IN E OR A RET ; ; ; -- SWITCH CONSOLE OUTPUT DEVICE COMMAND -- ; SWITCH: LD HL,COFLAG INC (HL) ;TOGGLE CONSOLE OUTPUT TYPE FLAG BIT 0,(HL) LD HL,SIOOUT JR Z,SWIT2-$ ;JUMP IF ZERO TO ONE TRANSITION LD HL,CRTOUT SWIT2: LD (CONOUT+1),HL ;STORE NEW CONSOLE OUTPUT ADDRESS RET ; ; ;******************************************************** ;* * ;* CONSOLE I/O PACKAGE AND UTILITY ROUTINES * ;* * ;******************************************************** ; ; ; GETLIN: LD B,C ;SAVE MAX LINE LENGTH PARAMETER IN B GLIN1: CALL ECHO ;GET A CHARACTER FROM THE CONSOLE CP CR ;CHECK FOR CARRIAGE RETURN JR Z,GLIN2-$ CP 'H'-64 ;CHECK FOR CTL-H BACKSPACE JR Z,GLIN4-$ CP ' ' RET C ;OTHER CONTROL CHARACTERS ARE ILLEGAL LD (HL),A INC HL ;STORE CHARACTER IN BUFFER DEC C JR NZ,GLIN1-$ ;GET ANOTHER IF THERE'S MORE ROOM SCF RET ;RETURN WITH CARRY=1 IF TOO ;MANY CHARACTERS ARE ENTERED GLIN2: LD (HL),A ;PUT CARRIAGE RETURN ON END OF LINE RET ;RETURN WITH CARRY BIT=0 GLIN4: DEC HL ;DELETE LAST CHARACTER FROM BUFFER CALL PNEXT DEFB ' ','H'-64 ;PRINT A SPACE TO OVERWRITE THE DEFB EOT ; LAST CHARACTER, THEN DO A BACKSPACE INC C LD A,B ;MAKE SURE YOU'RE NOT TRYING TO SUB C ;BACKSPACE PAST THE START OF THE LINE JR NC,GLIN1-$ RET ; ; ; SEARCH: CPIR ;SEARCH TABLE @HL FOR MATCH WITH A RET NZ ;EXIT NOW IF SEARCH FAILS ADD HL,BC ADD HL,BC ;ADD RESIDUE FROM CPIR BYTECOUNT ADD HL,BC ; TO HL 3 TIMES TO GET POINTER LD C,(HL) ; TO ADDRESS PART OF TABLE ENTRY INC HL LD B,(HL) RET ;EXIT WITH Z=1 TO INDICATE MATCH ; ; ; ; PARAMS: LD BC,0 LD A,(IY+0) CP CR ;CHECK IF LINE TERMINATES JR NZ,PARA2-$ ; IMMEDIATELY WITH A RETURN XOR A RET ;RETURN WITH PARAM COUNT=0 IF SO PARA1: INC C INC C BIT 3,C SCF RET NZ ;ERROR IF > 4 NUMBERS ENTERED PARA2: PUSH BC ;SAVE PARAMETER COUNT CALL GETHEX ;READ A NUMBER FROM LINE BUFFER POP BC PARA4: RET C ;ERROR IF RESULT OVER 16 BITS LD IX,PARAM1 ;POINT TO PARAMETER STORAGE AREA ADD IX,BC ;ADD PARAMETER COUNT IN BC LD (IX+0),L LD (IX+1),H ;STORE DATA RETURNED FROM 'GETHEX' CP ' ' JR Z,PARA1-$ ;GET ANOTHER ITEM IF SPACE CP ',' JR Z,PARA1-$ ;GET ANOTHER ITEM IF COMMA CP CR SCF ;ELSE CHECK FOR CARRIAGE RETURN RET NZ ; AND EXIT WITH CY=1 IF NOT PAREND: LD A,C SRL A ;A=COUNT OF NUMBERS ENTERED INC A RET ; ; GETHEX CONVERTS ASCII TO BINARY AND DOES ; HIGH LIMIT CHECKS TO LESS THAN 17 BITS. ; CARRY SET ON ILLEGAL CONVERSION RESULT ; TERMINATING CHARACTER RETURNS IN A. ; HL RETURNS WITH 16 BIT BINARY INTEGER ; GETHEX: LD HL,0 JR GNUM3-$ GNUM1: LD B,4 GNUM2: ADD HL,HL ;MULTIPLY RESULT BY 16 RET C ;RETURN IF IT OVERFLOWS 16 BITS DJNZ GNUM2-$ LD E,A ;APPEND NEW LOW ORDER DIGIT LD D,0 ;AND GET RESULT BACK INTO DE ADD HL,DE RET C ;RETURN IF OVERFLOW GNUM3: LD A,(IY+0) ;GET A CHARACTER FROM LINE INPUT INC IY ; BUFFER @ IY AND BUMP IY LD C,A CALL ASCHEX ;CONVERT ASCII TO NUMERIC JR NC,GNUM1-$ LD A,C OR A RET ; ; ASCHEX: SUB '0' RET C CP 10 CCF RET NC SUB 7 CP 10 RET C CP 16 CCF RET ; ; ; PUT4HS: LD A,H CALL PUT2HX LD A,L PUT2HS: CALL PUT2HX JP SPACE ; ; PUT2HX: PUSH AF RRA RRA RRA RRA CALL PUTNIB POP AF PUTNIB: AND 00001111B ADD A,90H DAA ADC A,40H DAA JP OUTPUT ; ; ; PMSG PRINTS THE STRING OF ASCII CHARACTERS ; POINTED TO BY THE RELATIVE ADDRESS IN DE ; UNTIL AN EOT IS ENCOUNTERED IN THE STRING. ; EOT EQU 04H CR EQU 0DH LF EQU 0AH ; PNEXT: EX (SP),HL CALL PMSG EX (SP),HL RET ; PMSG: LD A,(HL) INC HL CP EOT RET Z CALL OUTPUT JR PMSG-$ ; ; ; CRLFS OUTPUTS A RETURN-LINEFEED-SPACE ; TO THE CONSOLE DEVICE ; CRLFS: CALL PNEXT DEFB CR,LF,EOT SPACE: LD A,' ' JP OUTPUT ; ; ; ; ECHO INPUTS ONE CHARACTER FROM THE CONSOLE ; DEVICE, PRINTS IT ON THE CONSOLE OUTPUT AND ; THEN RETURNS IT IN REGISTER A WITH BIT 7 RESET ; ; OUTPUT PRINTS THE CHARACTER IN REGISTER A ON ; THE CONSOLE OUTPUT DEVICE AND THEN DOES A CHECK ; FOR CONSOLE INPUT TO FREEZE OR ABORT OUTPUT. ; ECHO: CALL CONIN ;INPUT A CHARACTER AND ECHO IT PUSH AF CALL CONOUT POP AF CP 'Z'+1 RET C SUB 32 ;CONVERT UPPER CASE TO LOWER CASE RET ; ; ; OUTPUT: CALL CONOUT CALL CONST ;SEE IF CONSOLE INPUT IS PENDING JR Z,OUTP2-$ CALL CONIN CP CR ;SEE IF CARRIAGE RETURN WAS TYPED JR Z,OUTP1-$ CALL CONIN ;WAIT FOR ANOTHER INPUT CHARACTER JR OUTP2-$ ; THEN RETURN TO CALLING ROUTINE OUTP1: LD (ESCFLG),A ;SET ESCAPE FLAG TO NON-ZERO VALUE OUTP2: LD A,(ESCFLG) OR A ;RETURN CURRENT STATUS OF ESCAPE RET ; FLAG TO CALLING ROUTINE ; ; ;