;########################################## ;CONSTANTS SIOCRA EQU 040h SIODRA EQU 041h INPUT_LINE_BUFFER EQU 0CB00h JP MAIN ;########################################## ; these 2 methods should be updated for specific hardware being used PUTCH: ; output the char in A OUT (SIODRA), A RET GETCH: ; wait for input, return it in A WAITD: IN A,(SIOCRA) RRA JR NC,WAITD ;was bit 0 on? if not, there was no data IN A,(SIODRA) RET ;######################################### BEEP: LD A,07h ;BEL CALL PUTCH RET ;########################################## PUTS: ;output the string pointed at by HL ;string should be terminated by NUL PUSH HL PUSH AF PUTS_LOOP: LD A,(HL) CP 00h JR Z, EXIT_PUTS CALL PUTCH INC HL JR PUTS_LOOP EXIT_PUTS: POP AF POP HL RET ;########################################## GET_LINE: ;read a line (i.e. up until a CR) into the buffer pointed at by HL ;string will be terminated by NUL PUSH HL PUSH AF PUSH BC LD B,1 GET_LINE_LOOP: CALL GETCH CP 0Dh ;is it a CR? if so, exit JR Z, EXIT_GET_LINE CP 0Ah ;is it a LF? if so, ignore it JR Z,GET_LINE_LOOP CP 08h ;is it a backspare? JR Z,BACK_SPACE CALL PUTCH ;echo it back LD (HL),A INC HL INC B LD (HL),0 JR GET_LINE_LOOP EXIT_GET_LINE: POP BC POP AF POP HL RET BACK_SPACE: DJNZ NOT_FIRST_LINE INC B ;set B back to 1 JR GET_LINE_LOOP NOT_FIRST_LINE: DEC HL CALL PUTCH LD A,' ' CALL PUTCH LD A,08h CALL PUTCH LD (HL),0 JR GET_LINE_LOOP ;########################################## PUT_BYTE: RRCA RRCA RRCA RRCA CALL PUT_NIBBLE RRCA RRCA RRCA RRCA CALL PUT_NIBBLE RET ;########################################## PUT_NIBBLE ;write out the low 4 bits in A PUSH AF PUSH BC PUSH HL AND 0Fh ;mask out top 4 bits (in case they weren't zero already) LD B,0h LD C,A LD HL,HEX_DIGITS ADD HL,BC LD A,(HL) CALL PUTCH POP HL POP BC POP AF RET ;########################################## PARSE_NUMBER: ;ENTRY: HL points at up to 4 hex digits ;EXIT: ; IX set to number ; B=00 means no error ; B=FF means error LD IX,0000h LD BC,0000h PARSE_NEXT_NUMBER: LD A,(HL) ;next digit CP 00h RET Z ADD IX,IX ADD IX,IX ADD IX,IX ADD IX,IX CALL PARSE_NIBBLE CP 0FFh JR Z,PARSE_ERROR LD C,A ADD IX,BC INC HL JP PARSE_NEXT_NUMBER CP 00h RET Z PARSE_ERROR: LD B,0FFh RET ;########################################## PARSE_NIBBLE: ;if A is ASCII for a valid digit, return the value of that digit ;else return FF PUSH BC PUSH HL CP 'Z' ;is it more than 'Z' JR C,DONT_CONVERT_CASE AND 11011111b ;turns LOWER into UPPER DONT_CONVERT_CASE: LD BC,10h LD HL,LAST_HEX_DIGIT CPDR JR NZ,NIBBLE_ERROR LD A,C JR EXIT_GET_NIBBLE NIBBLE_ERROR: LD A,0ffH EXIT_GET_NIBBLE POP HL POP BC RET HEX_DIGITS: DB '0123456789ABCDE' LAST_HEX_DIGIT: DB 'F' ;########################################## LINE_FEED: PUSH HL LD HL,LINE_FEED_MSG CALL PUTS POP HL RET ;########################################## SKIP_SPACES: ;skip over any spaces left in the line INC HL LD A,(HL) CP ' ' JR Z,SKIP_SPACES RET ;########################################## MAIN: LD HL,STARTUP_MSG CALL PUTS CALL BEEP MAIN_PROMPT_LOOP: LD HL,PROMPT_MSG CALL PUTS LD HL,INPUT_LINE_BUFFER CALL GET_LINE DEC HL ;since SKIP_SPACES will INC it CALL SKIP_SPACES LD A,(HL) OR 00100000b ;turns UPPER into LOWER CP 'q' JR Z,QUIT CP 'd' JR Z,DUMP_DATA CP 'g' JR Z,GOTO_ADDRESS CP 'h' JR Z,USAGE CP '?' JR Z,USAGE CP 'e' JP Z,ENTER_DATA JR MAIN_PROMPT_LOOP QUIT: LD HL,HALTING_MSG CALL PUTS HALT USAGE: LD HL,USAGE_MSG CALL PUTS JR MAIN_PROMPT_LOOP GOTO_ADDRESS: CALL SKIP_SPACES CALL PARSE_NUMBER LD A,B CP 00h JR NZ,DISPLAY_PARSE_ERROR_MESSAGE LD HL,MAIN_PROMPT_LOOP PUSH HL ; so a RET from the code being jumped to will jump back to the monitor PUSH IX RET DUMP_DATA: CALL SKIP_SPACES CP 00h JR Z,START_OF_DUMP ;parse the number pointed at by HL CALL PARSE_NUMBER LD A,B CP 00h JR Z,NO_PARSE_ERROR DISPLAY_PARSE_ERROR_MESSAGE: LD HL,ERROR_MESSAGE CALL PUTS JR MAIN_PROMPT_LOOP NO_PARSE_ERROR: LD (CURRENT_MEM_LOC),IX START_OF_DUMP: LD C,10h DUMP_ROW_LOOP: LD B, 10h CALL LINE_FEED LD HL,(CURRENT_MEM_LOC) LD A,H CALL PUT_BYTE LD A,L CALL PUT_BYTE LD A,':' CALL PUTCH LD A,' ' CALL PUTCH DUMP_DATA_AS_HEX_LOOP: LD A,(HL) CALL PUT_BYTE LD A,' ' CALL PUTCH INC HL DJNZ DUMP_DATA_AS_HEX_LOOP LD HL,(CURRENT_MEM_LOC) LD B, 10h DUMP_DATA_AS_TEXT_LOOP: LD A,(HL) CP 1Fh JR NC,PRINTABLE_CHAR LD A,'.' PRINTABLE_CHAR: CALL PUTCH INC HL DJNZ DUMP_DATA_AS_TEXT_LOOP LD (CURRENT_MEM_LOC),HL DEC C LD B,C DJNZ DUMP_ROW_LOOP JP MAIN_PROMPT_LOOP ENTER_DATA: CALL LINE_FEED CALL SKIP_SPACES CP 00h JR Z,ENTER_ONE_BYTE CALL PARSE_NUMBER LD A,B CP 00h JR NZ,DISPLAY_PARSE_ERROR_MESSAGE LD (CURRENT_MEM_LOC),IX ENTER_ONE_BYTE: LD HL,(CURRENT_MEM_LOC) LD A,H CALL PUT_BYTE LD A,L CALL PUT_BYTE LD A,':' CALL PUTCH LD A,' ' CALL PUTCH LD A,(HL) CALL PUT_BYTE LD A,'.' CALL PUTCH GET_FIRST_DIGIT: CALL GETCH CP 0Dh JR Z,EXIT_ENTER_DATA CALL PARSE_NIBBLE CP 0FFh JR Z,GET_FIRST_DIGIT CALL PUT_NIBBLE LD B,A GET_SECOND_DIGIT: CALL GETCH CP 0Dh JR Z,SAVE_DATA CP 08h JR NZ,NOT_BACKSPACE CALL PUTCH LD A,' ' CALL PUTCH LD A,08h CALL PUTCH JR GET_FIRST_DIGIT NOT_BACKSPACE: CALL PARSE_NIBBLE CP 0FFh JR Z,GET_SECOND_DIGIT SLA B SLA B SLA B SLA B ADD A,B LD B,A CALL PUT_NIBBLE SAVE_DATA: LD (HL),B INC HL LD (CURRENT_MEM_LOC),HL CALL LINE_FEED JP ENTER_ONE_BYTE EXIT_ENTER_DATA: JP MAIN_PROMPT_LOOP ;################################### ;CONSTANTS STARTUP_MSG: DB 'Jonno's ROM ' DB 'Monitor v0.1' DB 0Dh,0Ah DB ''?' for usage' LINE_FEED_MSG: DB 0Dh,0Ah,00h PROMPT_MSG: DB 0Dh,0Ah,'-',00h ERROR_MESSAGE: DB 0Dh,0Ah,'Input Error',0h HALTING_MSG: DB 0Dh,0Ah,'Halting.',0Dh,0Ah,00h USAGE_MSG: DB 0Dh,0Ah DB 'D [address]' DB ' - Dump data' DB 0Dh,0Ah DB 'E [address]' DB ' - Enter data' DB 0Dh,0Ah DB 'G address ' DB ' - Go to address' DB 0Dh,0Ah,00h CURRENT_MEM_LOC: x DB 00h,00h