;___ROM_MONITOR_PROGRAM_______________________________________________________ ; ; ORIGINAL CODE BY: ANDREW LYNCH (LYNCHAJ@YAHOO COM) 13 FEB 2007 ; ; MODIFIED BY : DAN WERNER 03 09.2009 ; ;__REFERENCES_________________________________________________________________ ; THOMAS SCHERRER BASIC HARDWARE TEST ASSEMBLER SOURCES FROM THE Z80 INFO PAGE ; INCLUDING ORIGINAL SCHEMATIC CONCEPT ; HTTP://Z80.INFO/Z80SOURC.TXT ; CODE SAMPLES FROM BRUCE JONES PUBLIC DOMAIN ROM MONITOR FOR THE SBC-200C ; HTTP://WWW.RETROTECHNOLOGY.COM/HERBS_STUFF/SD_BRUCE_CODE.ZIP ; INSPIRATION FROM JOEL OWENS "Z-80 SPACE-TIME PRODUCTIONS SINGLE BOARD COMPUTER" ; HTTP://WWW.JOELOWENS.ORG/Z80/Z80INDEX.HTML ; GREAT HELP AND TECHNICAL ADVICE FROM ALLISON AT ALPACA_DESIGNERS ; HTTP://GROUPS.YAHOO.COM/GROUP/ALPACA_DESIGNERS ; INTEL SDK-85 ROM DEBUG MONITOR ;_____________________________________________________________________________ ; #INCLUDE "std.asm" ; BUFLEN .EQU 40 ; INPUT LINE LENGTH ; ;__MAIN_PROGRAM_______________________________________________________________ ; ; ORG 00100h ; FOR DEBUG IN CP/M (AS .COM) .ORG MON_LOC ; ;__ENTRY JUMP TABLE___________________________________________________________ ; JP DSKY_ENTRY JP UART_ENTRY ; ENA_XM .EQU TRUE ; INCLUDE XMODEM ; ENA_MBC6502 .EQU FALSE ; ENABLE OR DISABLE MBC6502 OPTION ; ;__UART_ENTRY_________________________________________________________________ ; ; SERIAL MONITOR STARTUP ;_____________________________________________________________________________ ; UART_ENTRY: LD SP,MON_STACK ; SET THE STACK POINTER ;EI ; INTS OK NOW LD HL,UART_ENTRY ; RESTART ADDRESS CALL INITIALIZE ; INITIALIZE SYSTEM LD HL,TXT_READY ; POINT AT TEXT CALL PRTSTRH ; SHOW WE'RE HERE ; ;__SERIAL_MONITOR_COMMANDS____________________________________________________ ; ; B - BOOT SYSTEM ; D XXXX YYYY - DUMP MEMORY IN RANGE XXXX-YYYY ; F XXXX YYYY ZZ - FILL MEMORY IN RANGE XXXX-YYYY WITH ZZ ; H - HALT SYSTEM ; I XXXX - SHOW VALUE AT PORT XXXX ; K - ECHO KEYBOARD INPUT ; L - LOAD INTEL HEX FORMAT DATA ; M XXXX YYYY ZZZZ - MOVE MEMORY BLOCK XXXX-YYYY TO ZZZZ ; O XXXX YY - OUTPUT VALUE YY TO PORT XX ; P XXXX - PROGRAM RAM STARTING AT XXXX, PROMPT FOR VALUES ; R XXXX - RUN A PROGRAM AT ADDRESS XXXX ; S XX - SET ACTIVE BANK TO XX ; T XXXX - X-MODEM TRANSFER TO MEMORY LOCATION XXXX ; U - SET BANK TO PREVIOUS BANK ; 6 XX - TRANSFER CONTROL TO MBC6502 UNIT XX ; X - EXIT MONITOR ; ;__COMMAND_PARSE______________________________________________________________ ; ; PROMPT USER FOR COMMANDS, THEN PARSE THEM ;_____________________________________________________________________________ ; SERIALCMDLOOP: LD SP,MON_STACK ; RESET STACK CALL NEWLINE #IF (BIOS == BIOS_WBW) LD A,($FFE0) ; DISPLAY CURRENTLY ACTIVE CALL PRTHEXBYTE ; BANK IN LOW MEMORY #ENDIF LD A,'>' CALL COUT LD HL,KEYBUF ; SET POINTER TO KEYBUF AREA CALL GETLN ; GET A LINE OF INPUT FROM THE USER LD HL,KEYBUF ; RESET POINTER TO START OF KEYBUF LD A,C ; GET LINE LENGTH ENTERED OR A ; ZERO? JR Z,SERIALCMDLOOP ; NOTHING ENTERED, LOOP LD A,(HL) ; LOAD FIRST CHAR INTO A (THIS SHOULD BE THE COMMAND) INC HL ; INC POINTER CP 'B' ; IS IT "B" (Y/N) JP Z,BOOT ; IF YES BOOT CP 'R' ; IS IT "R" (Y/N) JP Z,RUN ; IF YES GO RUN ROUTINE CP 'P' ; IS IT "P" (Y/N) JP Z,PROGRM ; IF YES GO PROGRAM ROUTINE CP 'O' ; IS IT AN "O" (Y/N) JP Z,POUT ; PORT OUTPUT #IF (ENA_XM) CP 'T' ; IS IT A "T" (Y/N) JP Z,XMLOAD ; XMODEM TRANSFER #ENDIF CP 'L' ; IS IT A "L" (Y/N) JP Z,HXLOAD ; INTEL HEX FORMAT LOAD DATA CP 'I' ; IS IT AN "I" (Y/N) JP Z,PIN ; PORT INPUT CP 'D' ; IS IT A "D" (Y/N) JP Z,DUMPMEM ; DUMP MEMORY CP 'K' ; IS IT A "K" (Y/N) JP Z,KLOP ; LOOP ON KEYBOARD CP 'M' ; IS IT A "M" (Y/N) JP Z,MOVEMEM ; MOVE MEMORY COMMAND CP 'F' ; IS IT A "F" (Y/N) JP Z,FILLMEM ; FILL MEMORY COMMAND CP '?' ; IS IT A "?" (Y/N) JP Z,HELP ; HELP COMMAND CP 'H' ; IS IT A "H" (Y/N) JP Z,HALT ; HALT COMMAND #IF (BIOS == BIOS_WBW) CP 'S' ; IS IT A "S" (Y/N) JP Z,SETBNK ; SET BANK COMMAND CP 'U' ; IS IT A "U" (Y/N) JP Z,UNSETBNK ; UNSET (REVERT) BANK COMMAND #IF ((PLATFORM = PLT_MBC) & ENA_MBC6502) CP '6' ; IS IT A "6" (Y/N) JP Z,MBC6502 ; TRANSFER TO MBC6502 COMMAND #ENDIF #ENDIF CP 'X' ; IS IT A "X" (Y/N) JP Z,EXIT ; EXIT COMMAND LD HL,TXT_COMMAND ; POINT AT ERROR TEXT CALL PRTSTRH ; PRINT COMMAND LABEL JR SERIALCMDLOOP ; ;__INITIALIZE_________________________________________________________________ ; ; INITIALIZE SYSTEM ; AT ENTRY, HL SHOULD HAVE ADDRESS OF DESIRED RESTART ADDRESS ;_____________________________________________________________________________ ; INITIALIZE: ; #IF (BIOS == BIOS_UNA) ; INSTALL UNA INVOCATION VECTOR FOR RST 08 LD A,$C3 ; JP INSTRUCTION LD (8),A ; STORE AT 0x0008 LD HL,($FFFE) ; UNA ENTRY VECTOR LD (9),HL ; STORE AT 0x0009 #ENDIF ; RET ; ;__BOOT_______________________________________________________________________ ; ; PERFORM BOOT ACTION ;_____________________________________________________________________________ ; BOOT: #IF (BIOS == BIOS_UNA) LD BC,$01FB ; UNA FUNC = SET BANK LD DE,0 ; ROM BANK 0 CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE) JP 0 ; JUMP TO RESTART ADDRESS #ELSE ;LD A,BID_BOOT ; BOOT BANK ;LD HL,0 ; ADDRESS ZERO ;CALL HB_BNKCALL ; DOES NOT RETURN LD B,BF_SYSRESET ; SYSTEM RESTART LD C,BF_SYSRES_COLD ; COLD START CALL $FFF0 ; CALL HBIOS #ENDIF ; ;__EXIT_______________________________________________________________________ ; ; PERFORM EXIT ACTION ;_____________________________________________________________________________ ; EXIT: #IF (BIOS == BIOS_UNA) JR BOOT #ELSE LD B,BF_SYSRESET ; SYSTEM RESTART LD C,BF_SYSRES_WARM ; WARM START CALL $FFF0 ; CALL HBIOS #ENDIF ; ;__HALT_______________________________________________________________________ ; ; PERFORM HALT ACTION ;_____________________________________________________________________________ ; HALT: DI HALT ; ;__SETBNK_____________________________________________________________________ ; ; PERFORM SET BANK ACTION ;_____________________________________________________________________________ ; #IF (BIOS == BIOS_WBW) ; SETBNK: #IF (INTMODE == 1) LD HL,TXT_IMERR CALL PRTSTR #ELSE LD A,($FFE0) ; GET AND SAVE LD (BNKSAV),A ; CURRENT BANK CALL BYTEPARM ; GET BANK NUMBER JP C,ERR ; HANDLE DATA ENTRY ERROR LD C,A ; PUT IN C FOR FOR FUNC CALL LD B,BF_SYSSETBNK ; SET BANK FUNCTION CALL $FFF0 ; C HAS BANK, DO IT #ENDIF JP SERIALCMDLOOP ; NEXT COMMAND ; ;__UNSETBNK___________________________________________________________________ ; ; PERFORM UNSET BANK ACTION - REVERT TO BANK BEFORE PREVIOUS SET ;_____________________________________________________________________________ ; UNSETBNK: #IF (INTMODE == 1) LD HL,TXT_IMERR CALL PRTSTR #ELSE LD A,(BNKSAV) LD C,A ; PUT IN C FOR FOR FUNC CALL LD B,BF_SYSSETBNK ; SET BANK FUNCTION CALL $FFF0 ; C HAS BANK, DO IT #ENDIF JP SERIALCMDLOOP ; NEXT COMMAND ; BNKSAV .DB 00H ; OLD BANK FROM BEFORE SET ; #ENDIF ; ;__RUN________________________________________________________________________ ; ; TRANSFER OUT OF MONITOR, USER OPTION "R" ; SYNTAX: R [ []] ;_____________________________________________________________________________ ; RUN: CALL WORDPARM ; GET START ADDRESS JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE VALUE CALL BYTEPARM ; GET OPTIONAL PUSH AF ; A REGISTER VALUE CALL WORDPARM ; GET OPTIONAL PUSH DE ; BC REGISTER VALUE CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP BC ; RECOVER BC REGISTER VALUE TO PASS POP AF ; RECOVER A REGISTER VALUE TO PASS POP HL ; RECOVER START ADDRESS ; LD DE,PREG1 ; SETUP A RETURN PUSH DE ; ADDRESS ; JP (HL) ; GO ; PREG1: PUSH BC ; SAVE PUSH DE ; REGISTERS PUSH HL ; FOR DISPLAY ; CALL NEWLINE CALL PRTHEXBYTE ; DISPLAY A CALL PC_SPACE ; REGISTER ; LD B,3 PREG2: POP HL ; DISPLAY CALL PHL ; HL DE BC CALL PC_SPACE ; REGISTER DJNZ PREG2 JP SERIALCMDLOOP ; ;__PROGRM_____________________________________________________________________ ; ; PROGRAM RAM LOCATIONS, USER OPTION "P" ;_____________________________________________________________________________ ; PROGRM: CALL WORDPARM ; GET STARTING LOCATION JP C,ERR ; HANDLE SYNTAX ERRORS PUSH DE ; SAVE VALUE CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL PROGRM1: CALL NEWLINE POP HL PUSH HL CALL PHL CALL PC_COLON ; DISPLAY CALL PC_SPACE ; CURRENT POP HL ; VALUE PUSH HL LD A,(HL) CALL PRTHEXBYTE CALL PC_SPACE LD HL,KEYBUF ; GET AND CALL GETLN ; SAVE NEW LD HL,KEYBUF ; VALUE CALL NONBLANK CP 0 JP Z,SERIALCMDLOOP CALL BYTEPARM JR C,PROGRM2 ; SYNTAX ERROR POP DE LD (DE),A INC DE PUSH DE JR PROGRM1 PROGRM2: LD HL,TXT_BADNUM CALL PRTSTR JR PROGRM1 ; ;__KLOP_______________________________________________________________________ ; ; READ FROM THE SERIAL PORT AND ECHO, MONITOR COMMAND "K" ;_____________________________________________________________________________ ; KLOP: CALL NEWLINE ; KLOP1: CALL KIN ; GET A KEY CP CHR_ESC ; IS ? JP Z,SERIALCMDLOOP ; IF SO, ALL DONE CALL COUT ; OUTPUT KEY TO SCREEN JR KLOP1 ; LOOP ; #IF (ENA_XM) ; ;__XMLOAD_____________________________________________________________________ ; ; LOAD A FILE INTO MEMORY FROM THE SERIAL PORT USING X-MODEM PROTOCOL ; SOH: .EQU 'A'-40h ; ^A CTRL-A EOT: .EQU 'D'-40h ; ^D = End of Transmission ACK: .EQU 'F'-40h ; ^F = Positive Acknowledgement NAK: .EQU 'U'-40h ; ^U = Negative Acknowledgement CAN: .EQU 'X'-40h ; ^X = Cancel ; CPKTN .DB 0 ; CALCULATED PACKET NUMBER CPKTN1C .DB 0 ; CALCULATED PACKET NUMBER COMPLEMENT RETRYC .DB 0 ; RETRY COUNT RPKTN: .DB 0 ; RECEIVED PACKET NUMBER RPKTN1C:.DB 0 ; RECEIVED PACKET NUMBER COMPLEMENT PKTCS .DB 0 ; CHECKSUM ; PSADDR: .DW 0 ; START OF PACKET ADDR ; XMLOAD: CALL WORDPARM ; GET STARTING LOCATION JP C,ERR ; HANDLE SYNTAX ERRORS PUSH DE ; SAVE VALUE CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL ; LD HL,TXT_READY ; READY FOR CALL PRTSTR ; TRANSFER CALL NEWLINE ; LD BC,$F8F0 ; GET CPU SPEED CALL $FFF0 ; CALL HBIOS ; RST 08 ; AND MULTIPLY LD A,L ; BY 4 PUSH AF ADD A,A ; TO CREATE ADD A,A ; TIMEOUT DELAY LD (TMOFCT),A ; FACTOR POP AF ; LD BC,$FE01 ; SET FIRST NUMBER TO 1 LD (CPKTN),BC ; ALSO STORE THE 1-COMPLEMENT ; POP DE ; POINT TO WHERE TO SAVE THE PACKET LD (PSADDR),DE ; SAVE IF FOR THE CHECKSUM CALCULATION ; GETNP: LD HL,RETRYC ; WE RETRY 20 TIMES BEFORE GIVING UP LD (HL),20 ; NPLOOP: LD B,6 ; 6 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK CALL GCTO JP NC,NOTOUT ; NO TIMEOUT ? ; DEC (HL) ; REACHED MAX NUMBER OF RETRIES? JP Z,FAILRT ; YES, PRINT MESSAGE AND EXIT ; LD A,NAK ; SEND A NAK TO THE UPLOADER CALL COUT JR NPLOOP ; LOOP UNTIL WE GET A GET A CHARACTOR OR TIMEOUT ; NOTOUT: CP EOT ; DID UPLOADER SAY WE'RE FINISHED? JP Z,XMDONE ; YES, THEN WE'RE DONE CP CAN ; UPLOADER WANTS TO FAIL TRANSFER? JP Z,FAILCN ; YES, THEN WE'RE ALSO DONE CP SOH ; DID WE GET A START-OF-NEW-PACKET? JR NZ,NPLOOP ; NO, GO BACK AND TRY AGAIN ; LD HL,RPKTN ; WE SAVE PACKET NUMBER HERE ; CALL GCTO1 ; WAIT ONE SECOND FOR A CHARACTER LD (HL),A ; SHOULD BE PACKET NUMBER INC HL JR C,FAILTO ; TIMOUT ERROR? ; CALL GCTO1 ; WAIT ONE SECOND FOR A CHARACTER LD (HL),A ; SHOULD BE PACKET NUMBER COMPLEMENT JR C,FAILTO ; TIMOUT ERROR? LD C,128 ; GET 128 MORE CHARACTERS FOR A FULL PACKET PCKRCV: CALL GCTO1 ; WAIT ONE SECOND FOR A CHARACTER JR C,FAILTO ; TIMOUT ERROR? LD (DE),A ; SAVE THE RECEIVED CHAR INC DE DEC C JP NZ,PCKRCV ; CALL GCTO1 ; WAIT ONE SECOND FOR A CHARACTER JR C,FAILTO ; TIMOUT ERROR? LD (PKTCS),A ; SHOULD BE CHECKSUM ; LD HL,(PSADDR) ; CALCULATE CHECKSUM FROM 128 BYTES OF DATA LD B,128 XOR A CSLOOP: ADD A,(HL) ; JUST ADD UP THE BYTES INC HL DJNZ CSLOOP ; LD (PSADDR),DE ; SAVE THE NEW PACKET START ADDRESS ; LD HL,PKTCS XOR (HL) ; HL POINTS TO THE RECEIVED CHECKSUM SO JR NZ,FAILCS ; BY XORING IT TO OUR SUM WE CHECK FOR EQUALITY ; LD HL,(CPKTN) ; CHECK LD BC,(RPKTN) ; AGREEMENT ; XOR A ; PACKET SBC HL,BC ; NUMBERS JR NZ,FAILPN ; LD HL,CPKTN ; UPDATE THE PACKET COUNTERS INC (HL) INC HL DEC (HL) ; LD A,ACK ; TELL UPLOADER THAT WE'RE HAPPY WITH WITH CALL COUT ; PACKET AND GO BACK AND FETCH SOME MORE JP GETNP ; FAILRT: LD HL,TXT_RETRYERR ; FAILED ON RETRY JR XMERR FAILCN: LD HL,TXT_CANCLERR ; TRANSFER CANCELLED JR XMERR FAILCS: LD HL,TXT_CKSUMERR ; CHECKSUM ERROR JR XMERR FAILPN: LD HL,TXT_PKNUMERR ; PACKET NUMBER ERROR JR XMERR FAILTO: LD HL,TXT_TMOUTERR ; TIMEOUT ERROR JR XMERR ; XMDONE: LD A,ACK ; TELL REMOTE CALL COUT ; WE'RE DONE LD HL,TXT_LOADED ; TELL USER XMERR: CALL PRTSTR ; WE'RE DONE JP SERIALCMDLOOP ; BACK TO MENU ; ; WAITS FOR UP TO B SECONDS FOR A CHARACTER TO BECOME AVAILABLE AND ; RETURNS IT IN A WITHOUT ECHO AND CARRY CLEAR. IF TIMEOUT THEN CARRY ; IT SET. ; ; 4MHZ 20 SECONDS TMOFCT = 16 ; 10MHZ 20 SECONDS TMOFCT = 39 ; GCTO1: LD B,1 ; WAIT 1 SECOND FOR SERIAL INPUT GCTO: CALL CST ; IF THERE IS A OR A ; CHARACTER AVAILABLE JR NZ,GETCHRX ; EXIT NOW OTHERWISE POLL GCTOA: PUSH BC LD BC,255 ; C=CONSTANT (255) FOR INNER TIMING LOOP TMOFCT: .EQU $-1 ; B=SPEED FACTOR WHICH GETS UPDATED AT START GCTOB: PUSH BC LD B,C GCTOC: PUSH BC CALL CST OR A ; A CHAR AVAILABLE? JR NZ,GETCHR ; YES, GET OUT OF LOOP POP BC DJNZ GCTOC POP BC DJNZ GCTOB POP BC DJNZ GCTO SCF ; SET CARRY SIGNALS RET ; TIMEOUT OCCURRED GETCHR: POP BC POP BC POP BC GETCHRX:CALL CIN ; GET THE CHARACTER OR A ; CLEAR CARRY RET ; SIGNALS SUCCESS TXT_PKNUMERR .TEXT "\r\nPacket Number Error$" TXT_TMOUTERR .TEXT "\r\nTimeout Error$" TXT_RETRYERR .TEXT "\r\nRetry Error$" TXT_CANCLERR .TEXT "\r\nTransfer Cancelled$" #ENDIF ; ;__HXLOAD_____________________________________________________________________ ; ; LOAD INTEL HEX FORMAT FILE FROM THE SERIAL PORT, USER OPTION "H" ; ; [INTEL HEX FORMAT IS: ; 1) COLON (FRAME 0) ; 2) RECORD LENGTH FIELD (FRAMES 1 AND 2) ; 3) LOAD ADDRESS FIELD (FRAMES 3,4,5,6) ; 4) RECORD TYPE FIELD (FRAMES 7 AND 8) ; 5) DATA FIELD (FRAMES 9 TO 9+2*(RECORD LENGTH)-1 ; 6) CHECKSUM FIELD - SUM OF ALL BYTE VALUES FROM RECORD LENGTH TO AND ; INCLUDING CHECKSUM FIELD = 0 ] ; ; EXAMPLE OF INTEL HEX FORMAT FILE ; EACH LINE CONTAINS A CARRIAGE RETURN AS THE LAST CHARACTER ; :18F900002048454C4C4F20574F524C4420FF0D0AFF0D0A3EFF0D0A54BF ; :18F918006573742050726F746F7479706520524F4D204D6F6E69746FF1 ; :18F9300072205265616479200D0AFF0D0A434F4D4D414E4420524543F2 ; :18F948004549564544203AFF0D0A434845434B53554D204552524F52CD ; :16F96000FF0A0D20202D454E442D4F462D46494C452D20200A0DA4 ; :00000001FF ;_____________________________________________________________________________ ; HXLOAD: CALL NEWLINE ; SHOW READY HXLOADLINE: CALL CIN ; GET THE FIRST CHARACTER, EXPECTING A ':' CP ':' ; IS IT COLON ':'? WAIT FOR START OF NEXT LINE OF INTEL HEX FILE JR NZ,HXLOADLINE ; IF NOT, GO BACK TO WAIT LD E,0 ; RESET THE CHECKSUM BYTE CALL HEXINS ; FIRST TWO CHARACTERS IS THE RECORD LENGTH FIELD LD D,A ; LOAD RECORD LENGTH COUNT INTO D CALL HEXINS ; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS LD H,A ; PUT VALUE IN H REGISTER CALL HEXINS ; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS LD L,A ; PUT VALUE IN L REGISTER CALL HEXINS ; GET NEXT TWO CHARACTERS, RECORD FIELD TYPE DEC A ; RECORD FIELD TYPE 01 IS END OF FILE JR Z,HXLOADEXIT ; MUST BE THE END OF THAT FILE INC A ; RECORD FIELD TYPE 00 IS DATA JR NZ,HXLOADTYPERR ; RECORD TYPE IS INCORRECT, ERROR OUT HXLOADDATA: CALL HEXINS ; GET NEXT TWO CHARACTERS, ASSEMBLE INTO BYTE LD (HL),A ; MOVE CONVERTED BYTE IN A TO MEMORY LOCATION INC HL ; INCREMENT POINTER TO NEXT MEMORY LOCATION DEC D ; DECREMENT LINE CHARACTER COUNTER JR NZ,HXLOADDATA ; AND KEEP LOADING INTO MEMORY UNTIL LINE IS COMPLETE CALL HEXINS ; GET NEXT TWO CHARACTERS, ASSEMBLE INTO CHECKSUM BYTE LD A,E ; RECALL THE CHECKSUM BYTE OR A ; IT SHOULD BE ZERO JR Z,HXLOADLINE ; ZERO, SO WE HAVE NO ERROR, GO GET ANOTHER LINE HXLOADCHKERR: LD HL,TXT_CKSUMERR ; GET "CHECKSUM ERROR" MESSAGE CALL PRTSTR ; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD JP SERIALCMDLOOP ; RETURN TO PROMPT HXLOADTYPERR: LD HL,TXT_RECORDERR ; GET "RECORD TYPE ERROR" MESSAGE CALL PRTSTR ; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD JP SERIALCMDLOOP ; RETURN TO PROMPT HXLOADEXIT: CALL HEXINS ; GET LAST TWO CHARACTERS, ASSEMBLE INTO CHECKSUM BYTE LD A,E ; RECALL THE CHECKSUM BYTE OR A ; IT SHOULD BE ZERO JR NZ,HXLOADCHKERR ; CHECKUM IS INCORRECT, ERROR OUT LD HL,TXT_LOADED ; GET "LOADED" MESSAGE CALL PRTSTR ; PRINT MESSAGE FROM (HL) JP SERIALCMDLOOP ; RETURN TO PROMPT ; ;__POUT_______________________________________________________________________ ; ; OUTPUT TO AN I/O PORT, MONITOR COMMAND "O" ; SYNTAX: O ; NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE ; Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING ; THE B AND C REGISTERS WITH AN "OUT (C),A" INSTRUCTION ;_____________________________________________________________________________ ; POUT: CALL WORDPARM ; GET PORT NUMBER JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT FOR NOW CALL BYTEPARM ; GET VALUE TO WRITE JP C,ERR ; HANDLE ERRORS POP BC ; RESTORE PORT NUMBER TO BC OUT (C),A ; SEND VALUE TO PORT JP SERIALCMDLOOP ; DONE, BACK TO COMMAND LOOP ; ;__PIN________________________________________________________________________ ; ; INPUT FROM AN I/O PORT, MONITOR COMMAND "I" ; SYNTAX: I ; NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE ; Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING ; THE B AND C REGISTERS WITH AN "IN A,(C)" INSTRUCTION ;_____________________________________________________________________________ ; PIN: CALL WORDPARM ; GET PORT NUMBER JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT CALL NEWLINE ; POP BC ; RESTORE TO BC IN A,(C) ; GET PORT VALUE CALL PRTHEXBYTE ; DISPLAY IT JP SERIALCMDLOOP ; DONE, BACK TO COMMAND LOOP ; ;__DUMPMEM____________________________________________________________________ ; ; PRINT A MEMORY DUMP, USER OPTION "D" ; SYNTAX: D [END ADR] ; IF NO END ADDRESS, DUMP 100H BYTES ;_____________________________________________________________________________ ; DUMPMEM: CALL WORDPARM ; GET START ADDRESS JP C,ERR ; HANDLE ERRORS PUSH DE ; SAVE IT CALL WORDPARM ; GET END ADDRESS POP HL ; RECOVER START JR NC,GDATA ; ; LD D,H ; DEFAULT TO 100H LD E,L ; BYTES IF NO INC D ; END ADDRESS DEC DE ; IS GIVEN ; GDATA: INC DE ; BUMP DE FOR LATER COMPARE CALL NEWLINE ; BLKRD: CALL PHL ; PRINT START LOCATION CALL PC_COLON CALL PC_SPACE LD C,16 ; SET FOR 16 LOCS PUSH HL ; SAVE STARTING HL NXTONE: EXX ; LD C,E ; IN A,(C) ; EXX ; AND 7FH ; CP CHR_ESC ; JP Z,SERIALCMDLOOP ; CP 19 ; JR Z,NXTONE ; LD A,(HL) ; GET BYTE CALL PRTHEXBYTE ; DISPLAY IT CALL PC_SPACE ; UPDH: INC HL ; POINT NEXT DEC C ; DEC LOC COUNT JR NZ,NXTONE ; IF LINE NOT DONE ; NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP PCRLF: CALL PC_SPACE ; SPACE IT LD C,16 ; SET FOR 16 CHARS POP HL ; GET BACK START PCRLF0: LD A,(HL) ; GET BYTE TO PRINT CP $20 ; CONTROL CHAR (UNPRINTABLE)? JR C,PDOT ; IF SO, PRINT A DOT CP $7F ; 127 OR MORE (UNPRINTABLE)? JR NC,PDOT ; IF SO, PRINT A DOT JR PCHAR ; PRINT ACTUAL CHAR PDOT: LD A,2EH ; OTHERWISE SUBSTITUTE A DOT PCHAR: CALL COUT ; PRINT IT INC HL ; LD A,D ; CP H ; JR NZ,UPDH1 ; LD A,E ; CP L ; JP Z,SERIALCMDLOOP ; ; ;IF BLOCK NOT DUMPED, DO NEXT CHARACTER OR LINE UPDH1: DEC C ; DEC CHAR COUNT JR NZ,PCRLF0 ; DO NEXT CONTD: CALL NEWLINE ; JR BLKRD ; ; ;__MOVEMEM____________________________________________________________________ ; ; MOVE MEMORY, USER OPTION "M" ; SYNTAX: M ;_____________________________________________________________________________ ; MOVEMEM: CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE SRC START ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE SRC END ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (MOVE TGT ADR) JP C,ERR ; SYNTAX ERROR IF HEXBYTE FAILED PUSH DE ; SAVE IT CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP DE ; TGT ADR TO DE POP BC ; SRC END ADR TO BC POP HL ; SRC START ADR TO HL DEC HL ; PRE-DECREMENT DEC DE ; PRE-DECREMENT MOVEMEM1: INC HL ; BUMP CUR SRC ADR INC DE ; BUMP CUR TGT ADR LD A,(HL) ; GET SOURCE VAUEE LD (DE),A ; WRITE TO TARGET LOC LD A,H ; CHECK MSB OF END ADR CP B ; JR NZ,MOVEMEM1 ; NO MATCH, LOOP LD A,L ; CHECK LSB OF END ADR CP C ; JR NZ,MOVEMEM1 ; NO MATCH, LOOP JP SERIALCMDLOOP ; LSB AND MSB MATCH, ALL DONE ; ;__FILLMEM____________________________________________________________________ ; ; FILL MEMORY, USER OPTION "M" ; SYNTAX: F ;_____________________________________________________________________________ ; FILLMEM: CALL WORDPARM ; GET WORD VALUE INTO DE (FILL START ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL WORDPARM ; GET WORD VALUE INTO DE (FILL END ADR) JP C,ERR ; SYNTAX ERROR IF HEXWORD FAILED PUSH DE ; SAVE IT CALL BYTEPARM ; GET BYTE VALUE (FILL VALUE) INTO A JP C,ERR ; SYNTAX ERROR IF HEXBYTE FAILED LD C,A ; FILL VALUE TO C CALL NONBLANK ; LOOK FOR EXTRANEOUS PARAMETERS CP 0 ; TEST FOR TERMINATING NULL JP NZ,ERR ; ERROR IF NOT TERMINATING NULL POP DE ; END ADR TO DE POP HL ; START ADR TO HL DEC HL ; PRE-DECREMENT FILLMEM1: INC HL ; BUMP CUR ADR LD A,C ; FILL VALUE TO A LD (HL),A ; WRITE FILL VALUE TO CUR ADR (HL) LD A,H ; CHECK MSB OF END ADR CP D ; JR NZ,FILLMEM1 ; NO MATCH, LOOP LD A,L ; CHECK LSB OF END ADR CP E ; JR NZ,FILLMEM1 ; NO MATCH, LOOP JP SERIALCMDLOOP ; LSB AND MSB MATCH, ALL DONE ; ;__HELP_______________________________________________________________________ ; ; SYNTAX HELP, USER OPTION "H" ;_____________________________________________________________________________ ; HELP: LD HL,TXT_HELP ; POINT AT SYNTAX HELP TEXT CALL PRTSTR ; DISPLAY IT JP SERIALCMDLOOP ; AND BACK TO COMMAND LOOP ; ;__MBC6502____________________________________________________________________ ; ; TRANSFER CONTROL TO MBC6502 ;_____________________________________________________________________________ ; ; #IF (BIOS == BIOS_WBW) #IF ((PLATFORM = PLT_MBC) & ENA_MBC6502) MBC6502: CALL BYTEPARM ; GET BYTE VALUE (FILL VALUE) INTO A CPL ; UNIT 0 = FFH, 1 = FEH ETC LD C,A ; IN A,(C) ; EXECUTE NOP ; TRANSFER ; LD A,($FFE0) ; GET PREVIOUS BANK OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR ; JP SERIALCMDLOOP ; AND BACK TO COMMAND LOOP #ENDIF #ENDIF ; ;__ERR________________________________________________________________________ ; ; SYNTAX ERROR ;_____________________________________________________________________________ ; ERR: LD HL,TXT_ERR ; POINT AT ERROR TEXT CALL PRTSTRH ; DISPLAY IT JP SERIALCMDLOOP ; AND BACK TO COMMAND LOOP ; ;__BYTEPARM___________________________________________________________________ ; ; ATTEMPT TO GET A BYTE PARM, VALUE RETURNED IN A ; CF SET ON ERROR ;_____________________________________________________________________________ ; BYTEPARM: CALL NONBLANK ; SKIP LEADING BLANKS JP Z,ERR ; SYNTAX ERROR IF PARM NOT FOUND CALL ISHEX ; HEX CHAR? JR NZ,BYTEPARM1 ; IF NOT, ERR JP HEXBYTE ; RETURN VIA HEXBYTE BYTEPARM1: SCF ; SIGNAL ERROR RET ; RETURN ; ;__WORDPARM___________________________________________________________________ ; ; ATTEMPT TO GET A WORD PARM, VALUE RETURNED IN DE ; CF SET ON ERROR ;_____________________________________________________________________________ ; WORDPARM: CALL NONBLANK ; SKIP LEADING BLANKS JP Z,ERR ; SYNTAX ERROR IF PARM NOT FOUND CALL ISHEX ; HEX CHAR? JR NZ,BYTEPARM1 ; IF NOT, ERR JP HEXWORD ; RETURN VIA HEXWORD ; ;__GETLN______________________________________________________________________ ; ; READ A LINE OF TEXT FROM THE SERIAL PORT, HANDLE , TERM ON ; EXIT IF TOO MANY CHARS STORE RESULT IN HL. CHAR COUNT IN C. ;_____________________________________________________________________________ ; GETLN: LD C,0 ; ZERO CHAR COUNTER PUSH DE ; SAVE DE GETLNLOP: ; ENTRY LOOP CALL KIN ; GET A KEY CP CHR_CR ; IS ? JR Z,GETLNDONE ; YES, EXIT CP CHR_BS ; IS ? JR Z,GETLNBS ; IF SO, HANDLE IT CP CHR_DEL ; IS ? JR Z,GETLNBS ; IF SO, HANDLE AS CP ' ' ; UNEXPECTED CONTROL CHAR? JR C,GETLNLOP ; IF SO, IGNORE IT AND GET NEXT LD B,A ; SAVE CHAR IN B FOR NOW LD A,C ; GET COUNTER CP BUFLEN - 1 ; MAX OF BUFLEN CHARS LESS SPACE FOR TERM NULL JR Z,GETLNOVF ; IF AT MAX, HANDLE OVERFLOW LD A,B ; GET INPUT CHAR BACK CALL COUT ; OUTPUT KEY TO SCREEN LD (HL),A ; STORE CHAR IN BUFFER INC HL ; INC POINTER INC C ; INC CHAR COUNTER JR GETLNLOP ; GET NEXT CHAR GETLNOVF: ; OVERFLOW LD A,CHR_BEL ; BELL CHARACTER CALL COUT ; SEND IT TO CONSOLE JR GETLNLOP ; LOOP GETLNBS: ; BACKSPACE LD A,C ; A=C OR A ; ZERO? JR Z,GETLNLOP ; IF EMPTY LINE, IGNORE BS & LOOP DEC HL ; BACKUP BUF PTR 1 CHAR DEC C ; DECREMENT CHAR COUNTER LD A,CHR_BS ; BACKSPACE CALL COUT ; TO CONSOLE LD A,20H ; BLANK OUT CHAR ON TERM CALL COUT ; TO CONSOLE LD A,CHR_BS ; BACKSPACE CALL COUT ; TO CONSOLE JR GETLNLOP ; GET NEXT KEY ; DONE GETLNDONE: LD (HL),00H ; STORE NULL IN BUFFER POP DE ; RESTORE DE RET ; ; ;__KIN________________________________________________________________________ ; ; READ FROM THE SERIAL PORT AND ECHO & CONVERT INPUT TO UCASE ;_____________________________________________________________________________ ; KIN: CALL CIN AND 7FH ; STRIP HI BIT CP 'A' ; KEEP NUMBERS, CONTROLS RET C ; AND UPPER CASE CP 7BH ; SEE IF NOT LOWER CASE RET NC AND 5FH ; MAKE UPPER CASE RET ; ;__NONBLANK___________________________________________________________________ ; ; FIND NEXT NONBLANK CHARACTER IN BUFFER AT (HL) ;_____________________________________________________________________________ ; NONBLANK: LD A,(HL) ; GET NEXT CHAR CP ' ' ; COMPARE TO BLANK RET NZ ; DONE IF NOT BLANK INC HL ; BUMP TO NEXT CHAR JR NONBLANK ; AND LOOP ; ;__ISHEX______________________________________________________________________ ; ; CHECK BYTE AT (HL) FOR HEX CHAR, RET Z IF SO, ELSE NZ ;_____________________________________________________________________________ ; ISHEX: LD A,(HL) ; CHAR TO AS CP '0' ; < '0'? JR C,ISHEX1 ; YES, NOT 0-9, CHECK A-F CP '9' + 1 ; > '9' JR NC,ISHEX1 ; YES, NOT 0-9, CHECK A-F XOR A ; MUST BE 0-9, SET ZF RET ; AND DONE ISHEX1: CP 'A' ; < 'A'? JR C,ISHEX2 ; YES, NOT A-F, FAIL CP 'F' + 1 ; > 'F' JR NC,ISHEX2 ; YES, NOT A-F, FAIL XOR A ; MUST BE A-F, SET ZF RET ; AND DONE ISHEX2: OR $FF ; CLEAR ZF RET ; AND DONE ; ;__HEXBYTE____________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A ;_____________________________________________________________________________ ; HEXBYTE: LD C,0 ; INIT WORKING VALUE HEXBYTE1: CALL ISHEX ; DO WE HAVE A HEX CHAR? JR NZ,HEXBYTE3 ; IF NOT, WE ARE DONE LD B,4 ; SHIFT WORKING VALUE (C := C * 16) HEXBYTE2: SLA C ; SHIFT ONE BIT RET C ; RETURN W/ CF SET INDICATING OVERFLOW ERROR DJNZ HEXBYTE2 ; LOOP FOR 4 BITS CALL NIBL ; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL OR C ; COMBINE WITH WORKING VALUE LD C,A ; AND PUT BACK IN WORKING VALUE JR HEXBYTE1 ; DO ANOTHER CHARACTER HEXBYTE3: LD A,C ; WORKING VALUE TO A OR A ; CLEAR CARRY RET ; AND DONE ; ;__HEXWORD____________________________________________________________________ ; ; GET ONE WORD OF HEX DATA FROM BUFFER IN HL, RETURN IN DE ;_____________________________________________________________________________ ; HEXWORD: LD DE,0 ; INIT WORKING VALUE HEXWORD1: CALL ISHEX ; DO WE HAVE A HEX CHAR? JR NZ,HEXWORD3 ; IF NOT, WE ARE DONE LD B,4 ; SHIFT WORKING VALUE (DE := DE * 16) HEXWORD2: SLA E ; SHIFT LSB ONE BIT RL D ; SHIFT MSB ONE BIT RET C ; RETURN W/ CF SET INDICATING OVERFLOW ERROR DJNZ HEXWORD2 ; LOOP FOR 4 BITS CALL NIBL ; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL OR E ; COMBINE WITH LSB LD E,A ; AND PUT BACK IN WROKING VALUE JR HEXWORD1 ; DO ANOTHER CHARACTER HEXWORD3: OR A ; CLEAR CARRY RET ; AND DONE ; ;__NIBL_______________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A ;_____________________________________________________________________________ ; NIBL: LD A,(HL) ; GET K B. DATA INC HL ; INC KB POINTER CP 40H ; TEST FOR ALPHA JR NC,ALPH AND 0FH ; GET THE BITS RET ALPH: AND 0FH ; GET THE BITS ADD A,09H ; MAKE IT HEX A-F RET ; ;__HEXINS_____________________________________________________________________ ; ; GET ONE BYTE OF HEX DATA FROM SERIAL PORT, CHECKSUM IN E, RETURN IN A ;_____________________________________________________________________________ ; HEXINS: CALL NIBLS ; DO A NIBBLE RLCA ; MOVE FIRST BYTE UPPER NIBBLE RLCA ; RLCA ; RLCA ; LD B,A ; SAVE ROTATED NIBBLE CALL NIBLS ; DO NEXT NIBBLE OR B ; COMBINE NIBBLES IN ACC TO BYTE LD B,A ; SAVE BYTE ADD A,E ; ADD TO CHECKSUM LD E,A ; SAVE CHECKSUM LD A,B ; RECOVER BYTE RET ; DONE NIBLS: CALL CIN ; GET K B. DATA SUB '0' CP 10 ; TEST FOR ALPHA RET C ; IF A<10 JUST RETURN SUB 7 ; ELSE SUBTRACT 'A'-'0' (17) AND ADD 10 RET ; ;__PHL________________________________________________________________________ ; ; PRINT THE HL REG ON THE SERIAL PORT ;_____________________________________________________________________________ ; PHL: LD A,H ; GET HI BYTE CALL PRTHEXBYTE ; DISPLAY IT LD A,L ; GET LOW BYTE CALL PRTHEXBYTE ; DISPLAY IT RET ; DONE ; ;__PRTSTRH____________________________________________________________________ ; ; PRINT STRING AT HL W/ MINI HELP SUFFIX ;_____________________________________________________________________________ ; PRTSTRH: CALL PRTSTR LD HL,TXT_MINIHELP JP PRTSTR ; #IF (BIOS == BIOS_UNA) ; ;__COUT_______________________________________________________________________ ; ; OUTPUT CHARACTER FROM A ;_____________________________________________________________________________ ; COUT: ; SAVE ALL INCOMING REGISTERS PUSH AF PUSH BC PUSH DE PUSH HL ; ; OUTPUT CHARACTER TO CONSOLE VIA UBIOS LD E,A LD BC,$12 CALL $FFFD ; ; RESTORE ALL REGISTERS POP HL POP DE POP BC POP AF RET ; ;__CIN________________________________________________________________________ ; ; INPUT CHARACTER TO A ;_____________________________________________________________________________ ; CIN: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; INPUT CHARACTER FROM CONSOLE VIA UBIOS LD BC,$11 CALL $FFFD LD A,E ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; ;__CST________________________________________________________________________ ; ; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) ;_____________________________________________________________________________ ; CST: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; GET CONSOLE INPUT STATUS VIA UBIOS LD BC,$13 CALL $FFFD LD A,E ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; #ELSE ; ;__COUT_______________________________________________________________________ ; ; OUTPUT CHARACTER FROM A ;_____________________________________________________________________________ ; COUT: ; SAVE ALL INCOMING REGISTERS PUSH AF PUSH BC PUSH DE PUSH HL ; ; OUTPUT CHARACTER TO CONSOLE VIA HBIOS LD E,A ; OUTPUT CHAR TO E LD C,CIO_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR CALL $FFF0 ; HBIOS OUTPUTS CHARACTER ; ; RESTORE ALL REGISTERS POP HL POP DE POP BC POP AF RET ; ;__CIN________________________________________________________________________ ; ; INPUT CHARACTER TO A ;_____________________________________________________________________________ ; CIN: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; INPUT CHARACTER FROM CONSOLE VIA HBIOS LD C,CIO_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR CALL $FFF0 ; HBIOS READS CHARACTER LD A,E ; MOVE CHARACTER TO A FOR RETURN ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; ;__CST________________________________________________________________________ ; ; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING) ;_____________________________________________________________________________ ; CST: ; SAVE INCOMING REGISTERS (AF IS OUTPUT) PUSH BC PUSH DE PUSH HL ; ; GET CONSOLE INPUT STATUS VIA HBIOS LD C,CIO_CONSOLE ; CONSOLE UNIT TO C LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS CALL $FFF0 ; HBIOS RETURNS STATUS IN A ; ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; #ENDIF ; ;__WORK_AREA__________________________________________________________________ ; ; RESERVED RAM FOR MONITOR WORKING AREA ;_____________________________________________________________________________ ; KEYBUF: .FILL BUFLEN,0 ; ;__TEXT_STRINGS_______________________________________________________________ ; ; SYSTEM TEXT STRINGS ;_____________________________________________________________________________ ; ;TXT_PROMPT .TEXT "\r\n>$" TXT_READY .TEXT "\r\n\r\nMonitor Ready$" TXT_COMMAND .TEXT "\r\nUnknown Command$" TXT_ERR .TEXT "\r\nSyntax Error$" TXT_IMERR .TEXT "\r\nCommand not available under interrupt mode 1$" TXT_CKSUMERR .TEXT "\r\nChecksum Error$" TXT_RECORDERR .TEXT "\r\nRecord Type Error$" TXT_LOADED .TEXT "\r\nLoaded$" TXT_BADNUM .TEXT " *Invalid Hex Byte Value*$" TXT_MINIHELP .TEXT " (? for Help)$" TXT_HELP .TEXT "\r\nMonitor Commands (all values in hex):" .TEXT "\r\nB - Boot system" .TEXT "\r\nD xxxx [yyyy] - Dump memory from xxxx to yyyy" .TEXT "\r\nF xxxx yyyy zz - Fill memory from xxxx to yyyy with zz" .TEXT "\r\nH - Halt system" .TEXT "\r\nI xxxx - Input from port xxxx" .TEXT "\r\nK - Keyboard echo" .TEXT "\r\nL - Load Intel hex data" .TEXT "\r\nM xxxx yyyy zzzz - Move memory block xxxx-yyyy to zzzz" .TEXT "\r\nO xxxx yy - Output value yy to port xxxx" .TEXT "\r\nP xxxx - Program RAM at address xxxx" .TEXT "\r\nR xxxx [[yy] [zzzz]] - Run code at address xxxx" .TEXT "\r\n Pass yy and zzzz to register A and BC" #IF (BIOS == BIOS_WBW) .TEXT "\r\nS xx - Set bank to xx" .TEXT "\r\nU - Set bank to previous bank" #ENDIF #IF (ENA_XM) .TEXT "\r\nT xxxx - X-modem transfer to memory location xxxx" #ENDIF #IF (BIOS == BIOS_WBW) #IF ((PLATFORM == PLT_MBC) & ENA_MBC6502) .TEXT "\r\n6 xx - Transfer control to MBC6502 unit xx" #ENDIF #ENDIF .TEXT "\r\nX - Exit monitor" .TEXT "$" ; #IF DSKYENABLE ; KY_PR .EQU KY_FW ; USE [FW] FOR [PR] (PORT READ) KY_PW .EQU KY_BK ; USE [BW] FOR [PW] (PORT WRITE) ; ;__DSKY_ENTRY_________________________________________________________________ ; ; DSKY FRONT PANEL STARTUP ;_____________________________________________________________________________ ; DSKY_ENTRY: ; SHOULD WE DO SOMETHING HERE TO CONFIRM THAT A DSKY ; IS ACTUALLY OPERATING??? LD SP,MON_STACK ; SET THE STACK POINTER LD HL,DSKY_ENTRY ; RESTART ADDRESS CALL INITIALIZE ; ;__FRONT_PANEL_STARTUP________________________________________________________ ; ; START UP THE SYSTEM WITH THE FRONT PANEL INTERFACE ;_____________________________________________________________________________ ; CALL DSKY_BEEP ; ;__COMMAND_PARSE______________________________________________________________ ; ; PROMPT USER FOR COMMANDS, THEN PARSE THEM ;_____________________________________________________________________________ ; FRONTPANELLOOP: LD HL,CPUUP ; SET POINTER TO CPU UP MSG CALL DSKY_SHOW ; DISPLAY UNENCODED CALL DSKY_HIGHLIGHTCMDKEYS CALL DSKY_L1ON CALL KB_GET ; GET KEY FROM DSKY PUSH AF CALL DSKY_L1OFF POP AF FRONTPANELLOOP1: CP KY_PR ; IS PORT READ? JP Z,DOPORTREAD ; YES, JUMP CP KY_PW ; IS PORT WRITE? JP Z,DOPORTWRITE ; YES, JUMP CP KY_DE ; IS DEPOSIT? JP Z,DODEPOSIT ; YES, JUMP CP KY_EX ; IS EXAMINE? JP Z,DOEXAMINE ; YES, JUMP CP KY_GO ; IS GO? JP Z,DOGO ; YES, JUMP CP KY_BO ; IS BOOT? JP Z,DOBOOT ; YES, JUMP JR FRONTPANELLOOP ; LOOP ; ;__DOBOOT_____________________________________________________________________ ; ; PERFORM BOOT FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOBOOT: LD HL,MSGBOOT ; SET POINTER TO BOOT MESSAGE CALL DSKY_SHOW ; DISPLAY UNENCODED JP BOOT ; DO BOOT ; ;__DOPORTREAD_________________________________________________________________ ; ; PERFORM PORT READ FRONT PANEL ACTION ; PANEL TEMPLATE "Po88 88" ; POS 01234567 ;_____________________________________________________________________________ ; DOPORTREAD: CALL DSKY_HIGHLIGHTNUMKEYS CALL GETPORT ; GET PORT INTO A PORTREADLOOP: LD C,A ; STORE PORT IN "C" LD DE,DISPLAYBUF+2 ; POINT TO POS 2 IN BUF CALL PUTVALUE ; DISPLAY PORT NUM IN A,(C) ; GET PORT VALUE FROM PORT IN "C" INC DE ; ADVANCE BUF PTR INC DE ; ... TO LAST TWO POSITIONS CALL PUTVALUE ; DISPLAY PORT VALUE CALL ENCDISPLAY ; DISPLAY BUFFER CONTENTS PORTREADGETKEY: CALL KB_GET ; GET KEY FROM KB JR PORTREADGETKEY ; NO VALID KEY, LOOP ; ;__DOPORTWRITE________________________________________________________________ ; ; PERFORM PORT WRITE FRONT PANEL ACTION ; PANEL TEMPLATE "Po88 88" ; POS 01234567 ;_____________________________________________________________________________ ; DOPORTWRITE: CALL DSKY_HIGHLIGHTNUMKEYS CALL GETPORT ; GET PORT INTO A PORTWRITELOOP: LD L,A ; SAVE PORT NUM LD DE,DISPLAYBUF+2 ; POINT TO POS 2 IN BUF CALL PUTVALUE ; DISPLAY PORT NUM CALL GETVALUE ; INPUT A BYTE VALUE, RETURN IN "A" LD C,L ; RESTORE PORT NUM OUT (C),A ; OUTPUT VALUE TO PORT STORED IN "C" LD DE,DISPLAYBUF+6 ; DISPLAY WRITTEN PORT VALUE CALL PUTVALUE ; ... WITHOUT DP'S CALL ENCDISPLAY ; DISPLAY BUFFER CONTENTS PORTWRITEGETKEY: CALL KB_GET ; GET KEY FROM KB JR PORTWRITEGETKEY ; NO VALID KEY, LOOP ; ;__DOGO_______________________________________________________________________ ; ; PERFORM GO FRONT PANEL ACTION ;_____________________________________________________________________________ ; DOGO: CALL DSKY_HIGHLIGHTNUMKEYS CALL GETADDR ; GET ADDRESS INTO HL PUSH HL CALL DSKY_HIGHLIGHTKEYSOFF LD HL,GOTO ; POINT TO "GO" MSG CALL INITBUF POP HL LD DE,DISPLAYBUF+4 LD A,H CALL PUTVALUE LD A,L CALL PUTVALUE CALL ENCDISPLAY ; DISPLAY JP (HL) ; AND RUN ; ;__DOEXAMINE__________________________________________________________________ ; ; PERFORM EXAMINE FRONT PANEL ACTION ; PANEL TEMPLATE "8888 88" ; POS 01234567 ;_____________________________________________________________________________ ; DOEXAMINE: CALL DSKY_HIGHLIGHTNUMKEYS CALL GETADDR ; GET ADDRESS INTO HL EXAMINELOOP: LD DE,DISPLAYBUF+0 LD A,H CALL PUTVALUE LD A,L CALL PUTVALUE LD A,$10 LD (DE),A INC DE LD (DE),A INC DE LD A,(HL) ; GET VALUE FROM ADDRESS IN HL CALL PUTVALUE CALL ENCDISPLAY ; DISPLAY BUFFER ON DISPLAYS CALL DSKY_HIGHLIGHTFWDKEYS EXAMINEGETKEY: CALL KB_GET ; GET KEY FROM KB CP KY_EN ; [EN] PRESSED, INC ADDRESS AND LOOP JR Z,EXAMINEFW ; JR EXAMINEGETKEY ; NO VALID KEY, LOOP EXAMINEFW: INC HL ; HL++ JR EXAMINELOOP ; ; ;__DODEPOSIT__________________________________________________________________ ; ; PERFORM DEPOSIT FRONT PANEL ACTION ; PANEL TEMPLATE "8888 88" ; POS 01234567 ;_____________________________________________________________________________ ; DODEPOSIT: CALL DSKY_HIGHLIGHTNUMKEYS CALL GETADDR ; GET ADDRESS INTO HL DEPOSITLOOP: LD DE,DISPLAYBUF+0 LD A,H CALL PUTVALUE LD A,L CALL PUTVALUE LD A,$10 LD (DE),A INC DE LD (DE),A CALL GETVALUE ; LD (HL),A ; LD DE,DISPLAYBUF+6 ; DISPLAY WRITTEN MEM VALUE CALL PUTVALUE ; ... WITHOUT DP'S CALL ENCDISPLAY ; DISPLAY BUFFER CONTENTS CALL DSKY_HIGHLIGHTFWDKEYS DEPOSITGETKEY: CALL KB_GET ; GET KEY FROM KB CP KY_EN ; [EN] PRESSED, INC ADDRESS AND LOOP JR Z,DEPOSITFW ; JR DEPOSITGETKEY ; NO VALID KEY, LOOP DEPOSITFW: INC HL ; JR DEPOSITLOOP ; ; ;__GETADDR____________________________________________________________________ ; ; GET ADDRESS FROM FRONT PANEL ; PANEL TEMPLATE "Adr 8888" ; POS 01234567 ;_____________________________________________________________________________ ; GETADDR: LD HL,ADDR ; INITIALIZE DISPLAYBUF CALL INITBUF JR GETVALW ; ;__GETVAL16___________________________________________________________________ ; ; GET 16 BIT VALUE FROM FRONT PANEL ; PANEL TEMPLATE "????8888" ; POS 01234567 ;_____________________________________________________________________________ ; GETVALW: LD A,$80 ; LD (DISPLAYBUF+4),A ; LD (DISPLAYBUF+5),A ; LD (DISPLAYBUF+6),A ; LD (DISPLAYBUF+7),A ; GETVALW1: CALL ENCDISPLAY ; GETVALWLOOP: CALL KB_GET ; CP $10 ; JP M,GETVALWNUM ; NUMBER PRESSED, STORE IT CP KY_EN ; [EN] PRESSED, DONE JR Z,GETVALWDONE ; JR GETVALWLOOP ; INVALID KEY, LOOP GETVALWNUM: OR $80 ; SET DP LD C,A ; LD A,(DISPLAYBUF+5) ; SHIFT BYTES IN DISPLAY BUF TO THE LEFT LD (DISPLAYBUF+4),A ; LD A,(DISPLAYBUF+6) ; LD (DISPLAYBUF+5),A ; LD A,(DISPLAYBUF+7) ; LD (DISPLAYBUF+6),A ; LD A,C ; DISPLAY KEYSTROKE IN RIGHT MOST DISPLAY (0) LD (DISPLAYBUF+7),A ; JR GETVALW1 ; GETVALWDONE: LD A,(DISPLAYBUF+6) ; GET DIGIT IN DISPLAY 6 AND $0F SLA A ; ROTATE IT TO HIGH NIBBLE SLA A ; SLA A ; SLA A ; LD C,A ; STORE IT IN "C" LD A,(DISPLAYBUF+7) ; GET DIGIT IN DISPLAY 7 AND $0F OR C ; ADD IN NIBBLE STORED IN C LD L,A ; STORE IT IN LOW BYTE OF ADDRESS POINTER LD A,(DISPLAYBUF+4) ; GET DIGIT IN DISPLAY 4 AND $0F SLA A ; ROTATE IT TO HIGH NIBBLE SLA A ; SLA A ; SLA A ; LD C,A ; STORE IT IN "C" LD A,(DISPLAYBUF+5) ; GET DIGIT IN DISPLAY 5 AND $0F OR C ; ADD IN NIBBLE STORED IN "C" LD H,A ; STORE BYTE IN HIGH BYTE OF ADDRESS POINTER RET ; ;__GETPORT____________________________________________________________________ ; ; GET PORT FROM FRONT PANEL ; PANEL TEMPLATE "Port 88" ; POS 01234567 ;_____________________________________________________________________________ ; GETPORT: LD HL,PORT ; INITIALIZE DISPLAYBUF CALL INITBUF JR GETVALUE ; ;__GETVALUE___________________________________________________________________ ; ; GET 8 BIT VALUE FROM FRONT PANEL ; PANEL TEMPLATE "??????88" ; POS 01234567 ;_____________________________________________________________________________ ; GETVALUE: LD A,$80 ; LD (DISPLAYBUF+6),A ; LD (DISPLAYBUF+7),A ; GETVALUE1: CALL ENCDISPLAY ; GETVALUELOOP: CALL KB_GET ; CP $10 ; JP M,GETVALUENUM ; NUMBER PRESSED, STORE IT CP KY_EN ; [EN] PRESSED, DONE JR Z,GETVALUEDONE ; JR GETVALUELOOP ; INVALID KEY, LOOP GETVALUENUM: OR $80 ; SET DP LD C,A ; LD A,(DISPLAYBUF+7) ; LD (DISPLAYBUF+6),A ; LD A,C ; LD (DISPLAYBUF+7),A ; JR GETVALUE1 ; GETVALUEDONE: LD A,(DISPLAYBUF+6) ; AND $0F RLCA ; RLCA ; RLCA ; RLCA ; LD C,A ; LD A,(DISPLAYBUF+7) ; AND $0F OR C ; RET ; ;__PUTVALUE___________________________________________________________________ ; ; INSERT HEX DIGITS OF A INTO AN ENCODED DSKY DISPLAY BUFFER ; AT POSTION SPECIFIED BY DE. ON RETURN, DE POINTS TO NEXT ; POSITION IN DISPLAY BUFFER. ;_____________________________________________________________________________ ; PUTVALUE: PUSH AF ; SAVE INCOMING VALUE RLCA ; HIGH NIBBLE -> LOW NIBBLE RLCA ; ... RLCA ; ... RLCA ; ... AND $0F ; ISOLATE LOW NIBBLE LD (DE),A ; PLACE DIGIT VALUE IN BUFFER INC DE ; NEXT BUFFER POSITION POP AF ; RECOVER ORIGINAL VALUE AND $0F ; ISOLATE LOW NIBBLE LD (DE),A ; PLACE DIGIT VALUE IN BUFFER INC DE ; NEXT BUFFER POSITION RET ; DONE ; ;__KB_GET_____________________________________________________________________ ; ; GET A SINGLE KEY AND DECODE ; ;_____________________________________________________________________________ ; KB_GET: PUSH BC PUSH DE PUSH HL ; SAVE HL CALL DSKY_GETKEY ; GET A KEY LD A,E ; PUT KEY CODE IN A CP KY_EN ; ENTER? JR Z,KB_GET1 ; IF YES, RET TO CALLER CP $10 ; HEX DIGIT? JR C,KB_GET1 ; IF YES, RET TO CALLER ; NOT A DIGIT OR [EN], BAIL OUT TO MAIN LOOP TO HANDLE IT LD SP,MON_STACK ; CLEAR STACK JP FRONTPANELLOOP1 ; RESTART AT MAIN LOOP KB_GET1: POP HL ; RESTORE HL POP DE POP BC RET ; ;__INITBUF____________________________________________________________________ ; ; INITIALIZE DISPLAY BUFFER FROM VALUE AT ADDRESS IN HL ;_____________________________________________________________________________ ; INITBUF: LD DE,DISPLAYBUF LD BC,8 LDIR RET ; ;__ENCDISPLAY_________________________________________________________________ ; ; DISPLAY CONTENTS OF DISPLAYBUF ENCODED PER SEGDECODE TABLE ;_____________________________________________________________________________ ; ENCDISPLAY: PUSH HL LD HL,DISPLAYBUF JR ENCBUF0 ; ;__ENCBUF_____________________________________________________________________ ; ; DISPLAY CONTENTS OF BUFFER AT HL ENCODED PER SEGDECODE TABLE ;_____________________________________________________________________________ ; ENCBUF: PUSH HL ; SAVE HL ENCBUF0: PUSH AF ; SAVE AF PUSH BC ; SAVE BC PUSH DE ; SAVE DE LD DE,DSKY_BUF ; DESTINATION FOR DECODED BYTES LD B,8 ; NUMBER OF BYTES TO DECODE ENCBUF1: LD A,(HL) ; GET SOURCE BYTE INC HL ; BUMP TO NEXT BYTE FOR NEXT PASS PUSH AF ; SAVE IT AND $80 ; ISOLATE HI BIT (DP) LD C,A ; SAVE IN C POP AF ; RECOVER ORIGINAL AND $7F ; REMOVE HI BIT (DP) PUSH HL ; SAVE POINTER LD HL,SEGDECODE ; POINT TO DECODE TABLE CALL ADDHLA ; OFFSET BY INCOMING VALUE LD A,(HL) ; GET DECODED VALUE OR C ; RECOMBINE WITH DP VALUE LD (DE),A ; SAVE IN DEST BUF INC DE ; INC DEST BUF PTR POP HL ; RESTORE POINTER DJNZ ENCBUF1 ; LOOP THRU ALL BUF POSITIONS LD HL,DSKY_BUF ; POINT TO DECODED BUFFER CALL DSKY_SHOW ; DISPLAY IT POP DE ; RESTORE DE POP BC ; RESTORE BC POP AF ; RESTORE AF POP HL ; RESTORE HL RET ; ;_____________________________________________________________________________ ; ; DSKY INTERFACE ROUTINES ;_____________________________________________________________________________ ; DSKY_GETKEY: LD B,BF_DSKYGETKEY RST 08 RET ; DSKY_SHOW: LD B,BF_DSKYSHOWSEG RST 08 RET ; DSKY_BEEP: LD B,BF_DSKYBEEP RST 08 RET ; DSKY_L1ON: LD E,1 JR DSKY_STATLED DSKY_L1OFF: LD E,0 DSKY_STATLED: LD B,BF_DSKYSTATLED LD D,0 RST 08 RET ; DSKY_PUTLED: LD B,BF_DSKYKEYLEDS RST 08 RET ; DSKY_HIGHLIGHTFWDKEYS: LD HL,DSKY_HIGHLIGHTFWDKEYLEDS JR DSKY_PUTLED ; DSKY_HIGHLIGHTCMDKEYS: LD HL,DSKY_HIGHLIGHTCMDKEYLEDS JR DSKY_PUTLED ; DSKY_HIGHLIGHTNUMKEYS: LD HL,DSKY_HIGHLIGHTNUMKEYLEDS JR DSKY_PUTLED ; DSKY_HIGHLIGHTKEYSOFF: LD HL,DSKY_HIGHLIGHTKEYLEDSOFF JR DSKY_PUTLED ; DSKY_HIGHLIGHTFWDKEYLEDS .DB $00,$00,$00,$30,$00,$00,$00,$00 DSKY_HIGHLIGHTCMDKEYLEDS .DB $20,$00,$20,$3F,$00,$00,$00,$00 DSKY_HIGHLIGHTNUMKEYLEDS .DB $1F,$3F,$1F,$30,$00,$00,$00,$00 DSKY_HIGHLIGHTKEYLEDSOFF .DB $00,$00,$00,$00,$00,$00,$00,$00 ; CPUUP .DB $40,$39,$73,$3E,$00,$3E,$73,$40 ; "-CPU UP-" (RAW SEG) MSGBOOT .DB $7F,$5C,$5C,$78,$82,$00,$00,$00 ; "Boot! " (RAW SEG) ADDR .DB $17,$18,$19,$10,$00,$00,$00,$00 ; "Adr 0000" (ENCODED) PORT .DB $13,$14,$15,$16,$10,$10,$00,$00 ; "Port 00" (ENCODED) GOTO .DB $1A,$14,$10,$10,$00,$00,$00,$00 ; "Go 0000" (ENCODED) ; ;_HEX_7_SEG_DECODE_TABLE______________________________________________________ ; ; SET BIT 7 TO DISPLAY W/ DECIMAL POINT ;_____________________________________________________________________________ ; SEGDECODE: ; ; POS $00 $01 $02 $03 $04 $05 $06 $07 ; GLYPH '0' '1' '2' '3' '4' '5' '6' '7' .DB $3F, $06, $5B, $4F, $66, $6D, $7D, $07 ; ; POS $08 $09 $0A $0B $0C $0D $0E $0F ; GLYPH '8' '9' 'A' 'B' 'C' 'D' 'E' 'F' .DB $7F, $67, $77, $7C, $39, $5E, $79, $71 ; ; POS $10 $11 $12 $13 $14 $15 $16 $17 $18 $19 $1A ; GLYPH ' ' '-' '.' 'P' 'o' 'r' 't' 'A' 'd' 'r' 'G' .DB $00, $40, $00, $73, $5C, $50, $78, $77, $5E, $50, $3D ; DISPLAYBUF: .FILL 8,0 DSKY_BUF .FILL 8,0 ; #ELSE ; DSKY_ENTRY: JP EXIT ; #ENDIF ; ;================================================================================================== ; UTILITY FUNCTIONS ;================================================================================================== ; ; CHR_BEL .EQU 07H CHR_CR .EQU 0DH CHR_LF .EQU 0AH CHR_BS .EQU 08H CHR_ESC .EQU 1BH CHR_DEL .EQU 7FH ; ;__________________________________________________________________________________________________ ; ; UTILITY PROCS TO PRINT SINGLE CHARACTERS WITHOUT TRASHING ANY REGISTERS ; PC_SPACE: PUSH AF LD A,' ' JR PC_PRTCHR PC_COLON: PUSH AF LD A,':' JR PC_PRTCHR PC_CR: PUSH AF LD A,CHR_CR JR PC_PRTCHR PC_LF: PUSH AF LD A,CHR_LF JR PC_PRTCHR PC_PRTCHR: CALL COUT POP AF RET NEWLINE2: CALL NEWLINE NEWLINE: CALL PC_CR CALL PC_LF RET PRTSTR: LD A,(HL) INC HL CP '$' RET Z CALL COUT JR PRTSTR ; ; PRINT THE HEX BYTE VALUE IN A ; PRTHEXBYTE: PUSH AF PUSH DE CALL HEXASCII LD A,D CALL COUT LD A,E CALL COUT POP DE POP AF RET ; ; CONVERT BINARY VALUE IN A TO ASCII HEX CHARACTERS IN DE ; HEXASCII: LD D,A CALL HEXCONV LD E,A LD A,D RLCA RLCA RLCA RLCA CALL HEXCONV LD D,A RET ; ; CONVERT LOW NIBBLE OF A TO ASCII HEX ; HEXCONV: AND 0FH ;LOW NIBBLE ONLY ADD A,90H DAA ADC A,40H DAA RET ; ; ADD HL,A ; ; A REGISTER IS DESTROYED! ; ADDHLA: ADD A,L LD L,A RET NC INC H RET ; ; ; .FILL 16,0 ; SET MINIMUM STACK DEPTH SLACK .EQU (MON_END - $) .FILL SLACK,00H ; MON_STACK .EQU $ ; .ECHO "DBGMON space remaining: " .ECHO SLACK .ECHO " bytes.\n" ; .END