# File standalone-ROM-5.asm 0000 ;Oct 18, 2020 0000 ;standalone-ROM-5.asm 0000 ;ROM monitor for video display system with keyboard (standalone system) 0000 ;Same as standalone-ROM-4.asm with menus for ROM basic 0000 ;Tiny BASIC not included in assembly language here because it is in 8080 code 0000 ;Instead, room made for putting Tiny BASIC binary at basic label 0000 ; 0000 org 0000h 0000 c3 08 04 jp monitor_cold_start 0003 0003 ;The subroutines for the serial port use these variables in RAM: 0003 0003 ;Need to have stack in upper RAM, but not in area of CP/M or RAM monitor. 0003 ROM_monitor_stack: equ 0x7fff ;at top of RAM1 0003 0003 ;Video RAM area 0003 vram_start: equ 0x8000 0003 vram_end: equ 0xa57f 0003 ; 0003 ;Subroutine to initialize serial port UART 0003 ;Needs to be called only once after computer comes out of reset. 0003 ;If called while port is active will cause port to fail. 0003 ;16x = 9600 baud 0003 ;call commented out in RAM monitor 0003 3e 4e initialize_port: ld a,04eh ;1 stop bit, no parity, 8-bit char, 16x baud 0005 d3 03 out (3),a ;write to control port 0007 3e 37 ld a,037h ;enable receive and transmit 0009 d3 03 out (3),a ;write to control port 000b c9 ret 000c 000c ;write_char subroutine 000c ;calls put_char after setting registers with the character, line and position values 000c ;Does newline and backspace 000c ;ASCII character to write in A reg 000c fe 0d write_char: cp 0x0d ;carriage return? 000e c2 15 00 jp nz,wc_next1 ;no, go on 0011 cd 5a 08 call newline ;yes, newline 0014 c9 ret 0015 fe 08 wc_next1: cp 0x08 ;ctrl-h (backspace) 0017 c2 1e 00 jp nz,wc_next2 001a cd b2 08 call backspace 001d c9 ret 001e d6 20 wc_next2: sub a,0x20 ;adjust ASCII value to location in char table 0020 d8 ret c ;non-printing character ASCII < 20h 0021 cb 27 sla a ;multiply by two 0023 57 ld d,a 0024 3a 02 20 ld a,(test_line) 0027 47 ld b,a 0028 3a 03 20 ld a,(test_pos) 002b 4f ld c,a 002c 7a ld a,d 002d cd 7d 05 call put_char 0030 3a 03 20 ld a,(test_pos) 0033 fe 33 cp 51 ;last place in line? 0035 ca 3d 00 jp z,wc_next3 ;yes, do not inc position, make newline 0038 3c inc a ;no, inc position 0039 32 03 20 ld (test_pos),a 003c c9 ret 003d cd 5a 08 wc_next3: call newline 0040 c9 ret 0041 0041 ;write_string for system with display 0041 ;Writes a zero-terminated string to the display at current cursor location 0041 ;Uses calls to write_char, which calls put_char 0041 ;So all registers will be used -- need pointer in RAM 0041 ;Address of string to write passed in HL 0041 22 17 20 write_string: ld (string_pointer),hl 0044 7e ld a,(hl) 0045 fe 00 cp 0 0047 ca 57 00 jp z,ws_quit 004a cd 0c 00 call write_char 004d 2a 17 20 ld hl,(string_pointer) 0050 23 inc hl 0051 22 17 20 ld (string_pointer),hl 0054 c3 41 00 jp write_string 0057 c9 ws_quit: ret 0058 0x00... ds 14,0 ;to get NMI handler to 0066h 0066 0066 ;Need to put non-maskable interrupt (NMI) handler here, at 0066h 0066 f5 push af 0067 3a 2a 20 ld a,(timer_tick) 006a 3c inc a 006b 32 2a 20 ld (timer_tick),a 006e f1 pop af 006f ed 45 retn 0071 0071 ;Binary loader. Receive a binary file over serial port, place in memory. 0071 ;Target address passed in HL, length of load (= file length) in BC 0071 db 03 bload: in a,(3) ;get status 0073 e6 02 and 002h ;check RxRDY bit 0075 ca 71 00 jp z,bload ;not ready, loop 0078 db 02 in a,(2) 007a 77 ld (hl),a 007b 23 inc hl 007c 0b dec bc ;byte counter 007d 78 ld a,b ;need to test BC this way because 007e b1 or c ;dec rp instruction does not change flags 007f c2 71 00 jp nz,bload 0082 c9 ret 0083 ; 0083 ;Binary dump to port. Send a stream of binary data from memory to serial output 0083 ;Address of dump passed in HL, length of dump in BC 0083 db 03 bdump: in a,(3) ;get status 0085 e6 01 and 001h ;check TxRDY bit 0087 ca 83 00 jp z,bdump ;not ready, loop 008a 7e ld a,(hl) 008b d3 02 out (2),a 008d 23 inc hl 008e 0b dec bc 008f 78 ld a,b ;need to test this way because 0090 b1 or c ;dec rp instruction does not change flags 0091 c2 83 00 jp nz,bdump 0094 c9 ret 0095 0095 ;Subroutine to get a string from console input, place in buffer. 0095 ;Buffer address passed in HL reg. 0095 ;Uses A,BC,DE,HL registers (including calls to other subroutines). 0095 ;Line entry ends by hitting return key. Return char not included in string (replaced by zero). 0095 ;Backspace editing OK. No error checking. 0095 ; 0095 22 19 20 get_line: ld (buffer_pointer),hl ;put buffer address in variable 0098 3e ff ld a,0FFh 009a 32 2b 20 ld (blink_flag),a ;blink cursor while waiting for input 009d d3 05 out (5),a ;clear shift reg (get_char mode 0) 009f cd cb 06 get_line_next_char: call get_char 00a2 fe 0d cp 0dh ;check if return 00a4 ca e0 00 jp z,get_line_done ;yes, normal exit 00a7 fe 7f cp 07fh ;check if backspace (VT102 keys) 00a9 ca c8 00 jp z,get_line_backspace ;yes, jump to backspace routine 00ac fe 08 cp 008h ;check if backspace (ANSI keys) 00ae ca c8 00 jp z,get_line_backspace ;yes, jump to backspace 00b1 32 1b 20 ld (get_line_char),a ;store character 00b4 cd 0c 00 call write_char ;put char on screen 00b7 3a 1b 20 ld a,(get_line_char) ;get char back 00ba 2a 19 20 ld hl,(buffer_pointer) 00bd 77 ld (hl),a ;store char in buffer 00be 23 inc hl ;point to next space in buffer 00bf 22 19 20 ld (buffer_pointer),hl 00c2 3e 00 ld a,0 00c4 77 ld (hl),a ;leaves a zero-terminated string in buffer 00c5 c3 9f 00 jp get_line_next_char 00c8 3a 03 20 get_line_backspace: ld a,(test_pos) ;check if at beginning of line 00cb fe 00 cp 0 00cd ca 9f 00 jp z,get_line_next_char ;yes, ignore backspace, get next char 00d0 2a 19 20 ld hl,(buffer_pointer) ;no, erase char from buffer 00d3 3e 00 ld a,0 ;put a zero in buffer where the last char was 00d5 77 ld (hl),a 00d6 2b dec hl 00d7 22 19 20 ld (buffer_pointer),hl 00da cd b2 08 call backspace ;backspaces display, rubs out char 00dd c3 9f 00 jp get_line_next_char 00e0 3e 00 get_line_done: ld a,0 ;turn blinking off 00e2 32 2b 20 ld (blink_flag),a 00e5 c9 ret 00e6 00e6 ;byte_to_hex_string subroutine 00e6 ;Creates a two-char hex string from the byte value passed in register A 00e6 ;Location to place string passed in HL 00e6 ;String is zero-terminated, stored in 3 locations starting at HL 00e6 ;Also uses registers b,d, and e 00e6 47 byte_to_hex_string: ld b,a ;store original byte 00e7 cb 3f srl a ;shift right 4 times, putting 00e9 cb 3f srl a ;high nybble in low-nybble spot 00eb cb 3f srl a ;and zeros in high-nybble spot 00ed cb 3f srl a 00ef 16 00 ld d,000h ;prepare for 16-bit addition 00f1 5f ld e,a ;de contains offset 00f2 e5 push hl ;temporarily store string target address 00f3 21 4c 01 ld hl,hex_char_table ;use char table to get high-nybble character 00f6 19 add hl,de ;add offset to start of table 00f7 7e ld a,(hl) ;get char 00f8 e1 pop hl ;get string target address 00f9 77 ld (hl),a ;store first char of string 00fa 23 inc hl ;point to next string target address 00fb 78 ld a,b ;get original byte back from reg b 00fc e6 0f and 00fh ;mask off high-nybble 00fe 5f ld e,a ;d still has 000h, now de has offset 00ff e5 push hl ;temp store string target address 0100 21 4c 01 ld hl,hex_char_table ;start of table 0103 19 add hl,de ;add offset 0104 7e ld a,(hl) ;get char 0105 e1 pop hl ;get string target address 0106 77 ld (hl),a ;store second char of string 0107 23 inc hl ;point to third location 0108 3e 00 ld a,000h ;zero to terminate string 010a 77 ld (hl),a ;store the zero 010b c9 ret ;done 010c 010c ;hex_char_to_nybble subroutine 010c ;Converts a single ASCII hex char to a nybble value 010c ;Pass char in reg A. Letter numerals must be upper case. 010c ;Return nybble value in low-order reg A with zeros in high-order nybble if no error. 010c ;Return 0ffh in reg A if error (char not a valid hex numeral). 010c ;Also uses b, c, and hl registers. 010c 21 4c 01 hex_char_to_nybble: ld hl,hex_char_table 010f 06 0f ld b,00fh ;no. of valid characters in table - 1. 0111 0e 00 ld c,000h ;will be nybble value 0113 be hex_to_nybble_loop: cp (hl) ;character match here? 0114 ca 20 01 jp z,hex_to_nybble_ok ;match found, exit 0117 05 dec b ;no match, check if at end of table 0118 fa 22 01 jp m,hex_to_nybble_err ;table limit exceded, exit with error 011b 0c inc c ;still inside table, continue search 011c 23 inc hl 011d c3 13 01 jp hex_to_nybble_loop 0120 79 hex_to_nybble_ok: ld a,c ;put nybble value in a 0121 c9 ret 0122 3e ff hex_to_nybble_err: ld a,0ffh ;error value 0124 c9 ret 0125 0125 ;hex_to_byte subroutine 0125 ;Converts a hex character pair to a byte value 0125 ;Called with location of high-order char in HL 0125 ;If no error carry flag clear, returns with byte value in register A, and 0125 ;HL pointing to next mem location after char pair. 0125 ;If error (non-hex char) carry flag set, HL pointing to invalid char 0125 7e hex_to_byte: ld a,(hl) ;location of character pair 0126 e5 push hl ;store hl (hex_char_to_nybble uses it) 0127 cd 0c 01 call hex_char_to_nybble 012a e1 pop hl ;returns with nybble value in a reg, or 0ffh if error 012b fe ff cp 0ffh ;non-hex character? 012d ca 4a 01 jp z,hex_to_byte_err ;yes, exit with error 0130 cb 27 sla a ;no, move low order nybble to high side 0132 cb 27 sla a 0134 cb 27 sla a 0136 cb 27 sla a 0138 57 ld d,a ;store high-nybble 0139 23 inc hl ;get next character of the pair 013a 7e ld a,(hl) 013b e5 push hl ;store hl 013c cd 0c 01 call hex_char_to_nybble 013f e1 pop hl 0140 fe ff cp 0ffh ;non-hex character? 0142 ca 4a 01 jp z,hex_to_byte_err ;yes, exit with error 0145 b2 or d ;no, combine with high-nybble 0146 23 inc hl ;point to next memory location after char pair 0147 37 scf 0148 3f ccf ;no-error exit (carry = 0) 0149 c9 ret 014a 37 hex_to_byte_err: scf ;error, carry flag set 014b c9 ret 014c .. hex_char_table: defm "0123456789ABCDEF" ;ASCII hex table 015c 015c ;address_entry subroutine 015c ;Subroutine to get a two-byte address from keyboard input. 015c ;Returns with address value in HL 015c ;Uses locations in RAM for buffer and variables 015c 21 2d 20 address_entry: ld hl,buffer ;location for entered string 015f cd 95 00 call get_line ;returns with address string in buffer 0162 21 2d 20 ld hl,buffer ;location of stored address entry string 0165 cd 25 01 call hex_to_byte ;will get high-order byte first 0168 da 7e 01 jp c, address_entry_error ;if error, jump 016b 32 10 20 ld (current_location+1),a ;store high-order byte, little-endian 016e 21 2f 20 ld hl,buffer+2 ;point to low-order hex char pair 0171 cd 25 01 call hex_to_byte ;get low-order byte 0174 da 7e 01 jp c, address_entry_error ;jump if error 0177 32 0f 20 ld (current_location),a ;store low-order byte in lower memory 017a 2a 0f 20 ld hl,(current_location) ;put memory address in hl 017d c9 ret 017e 21 6b 03 address_entry_error: ld hl,address_error_msg 0181 cd 41 00 call write_string 0184 c3 5c 01 jp address_entry 0187 0187 ;decimal_entry subroutine 0187 ;Gets a decimal string from input, returns a word value 0187 ;Calls decimal_string_to_word subroutine 0187 21 2d 20 decimal_entry: ld hl,buffer 018a cd 95 00 call get_line 018d ed 5b 19 20 ld de,(buffer_pointer) ;pointer to end of string 0191 21 2d 20 ld hl,buffer 0194 cd a1 01 call decimal_string_to_word 0197 d0 ret nc ;no error, return with word in hl 0198 21 dc 03 ld hl,decimal_error_msg ;error, try again 019b cd 41 00 call write_string 019e c3 87 01 jp decimal_entry 01a1 01a1 ;decimal_string_to_word subroutine 01a1 ;Converts a decimal string to a word value 01a1 ;Call with address of string in HL, pointer to end of string in DE 01a1 ;Carry flag set if error (non-decimal char) 01a1 ;Carry flag clear, word value in HL if no error. 01a1 42 decimal_string_to_word: ld b,d 01a2 4b ld c,e ;use BC as string pointer 01a3 22 0f 20 ld (current_location),hl ;store addr. of start of buffer in RAM word variable 01a6 21 00 00 ld hl,000h ;starting value zero 01a9 22 15 20 ld (current_value),hl 01ac 21 f1 01 ld hl,decimal_place_value ;pointer to values 01af 22 13 20 ld (value_pointer),hl 01b2 0b decimal_next_char: dec bc ;next char in string (moving right to left) 01b3 2a 0f 20 ld hl,(current_location) ;check if at end of decimal string 01b6 37 scf ;get ready to subtract de from buffer addr. 01b7 3f ccf ;set carry to zero (clear) 01b8 ed 42 sbc hl,bc ;keep going if bc > or = hl (buffer address) 01ba da c6 01 jp c,decimal_continue ;borrow means bc > hl 01bd ca c6 01 jp z,decimal_continue ;z means bc = hl 01c0 2a 15 20 ld hl,(current_value) ;return if de < buffer address (no borrow) 01c3 37 scf ;get value back from RAM variable 01c4 3f ccf 01c5 c9 ret ;return with carry clear, value in hl 01c6 0a decimal_continue: ld a,(bc) ;next char in string (right to left) 01c7 d6 30 sub 030h ;ASCII value of zero char 01c9 fa ec 01 jp m,decimal_error ;error if char value less than 030h 01cc fe 0a cp 00ah ;error if byte value > or = 10 decimal 01ce f2 ec 01 jp p,decimal_error ;a reg now has value of decimal numeral 01d1 2a 13 20 ld hl,(value_pointer) ;get value to add an put in de 01d4 5e ld e,(hl) ;little-endian (low byte in low memory) 01d5 23 inc hl 01d6 56 ld d,(hl) 01d7 23 inc hl ;hl now points to next value 01d8 22 13 20 ld (value_pointer),hl 01db 2a 15 20 ld hl,(current_value) ;get back current value 01de 3d decimal_add: dec a ;add loop to increase total value 01df fa e6 01 jp m,decimal_add_done ;end of multiplication 01e2 19 add hl,de 01e3 c3 de 01 jp decimal_add 01e6 22 15 20 decimal_add_done: ld (current_value),hl 01e9 c3 b2 01 jp decimal_next_char 01ec 37 decimal_error: scf 01ed c9 ret 01ee c3 de 01 jp decimal_add 01f1 01 00 0a 00 64 00 e8 03 10 27 decimal_place_value: defw 1,10,100,1000,10000 01fb 01fb ;Memory dump subroutine 01fb ;Displays a 256-byte block of memory in 16-byte rows. 01fb ;Called with address of start of block in HL 01fb 22 0f 20 memory_dump: ld (current_location),hl ;store address of block to be displayed 01fe 3e 00 ld a,0 0200 32 12 20 ld (byte_count),a ;initialize byte count 0203 32 11 20 ld (line_count),a ;initialize line count 0206 c3 3b 02 jp dump_new_line 0209 2a 0f 20 dump_next_byte: ld hl,(current_location) ;get byte address from storage, 020c 7e ld a,(hl) ;get byte to be converted to string 020d 23 inc hl ;increment address and 020e 22 0f 20 ld (current_location),hl ;store back 0211 21 2d 20 ld hl,buffer ;location to store string 0214 cd e6 00 call byte_to_hex_string ;convert 0217 21 2d 20 ld hl,buffer ;display string 021a cd 41 00 call write_string 021d 3a 12 20 ld a,(byte_count) ;next byte 0220 3c inc a 0221 ca 68 02 jp z,dump_done ;stop when 256 bytes displayed 0224 32 12 20 ld (byte_count),a ;not finished yet, store 0227 3a 11 20 ld a,(line_count) ;end of line (16 bytes)? 022a fe 0f cp 00fh ;yes, start new line 022c ca 3b 02 jp z,dump_new_line 022f 3c inc a ;no, increment line count 0230 32 11 20 ld (line_count),a 0233 3e 20 ld a,020h ;print space 0235 cd 0c 00 call write_char 0238 c3 09 02 jp dump_next_byte ;continue 023b 3e 00 dump_new_line: ld a,0 ;reset line count to zero 023d 32 11 20 ld (line_count),a 0240 ;Original subroutine had newline here, but with display limited to 52 characters 0240 ;it is not needed because write_string subroutine produces a newline when the line is full 0240 ; call newline ;no need for newline here 0240 2a 0f 20 ld hl,(current_location) ;location of start of line 0243 7c ld a,h ;high byte of address 0244 21 2d 20 ld hl,buffer 0247 cd e6 00 call byte_to_hex_string ;convert 024a 21 2d 20 ld hl,buffer 024d cd 41 00 call write_string ;write high byte 0250 2a 0f 20 ld hl,(current_location) 0253 7d ld a,l ;low byte of address 0254 21 2d 20 ld hl,buffer 0257 cd e6 00 call byte_to_hex_string ;convert 025a 21 2d 20 ld hl,buffer 025d cd 41 00 call write_string ;write low byte 0260 3e 20 ld a,020h ;space 0262 cd 0c 00 call write_char 0265 c3 09 02 jp dump_next_byte ;now write 16 bytes 0268 3e 00 dump_done: ld a,000h 026a 21 2d 20 ld hl,buffer 026d 77 ld (hl),a ;clear buffer of last string 026e cd 5a 08 call newline 0271 c9 ret 0272 ; 0272 ;Memory load subroutine 0272 ;Loads RAM memory with bytes entered as hex characters 0272 ;Called with address to start loading in HL 0272 ;Displays entered data in 16-byte rows. 0272 22 0f 20 memory_load: ld (current_location),hl 0275 21 96 03 ld hl,data_entry_msg 0278 cd 41 00 call write_string 027b c3 c9 02 jp load_new_line 027e d3 05 load_next_char: out (5),a ;get_char mode 0 0280 cd cb 06 call get_char 0283 fe 0d cp 00dh ;return? 0285 ca de 02 jp z,load_done ;yes, quit 0288 32 2d 20 ld (buffer),a 028b d3 05 out (5),a ;get_char mode 0 028d cd cb 06 call get_char 0290 fe 0d cp 00dh ;return? 0292 ca de 02 jp z,load_done ;yes, quit 0295 32 2e 20 ld (buffer+1),a 0298 21 2d 20 ld hl,buffer 029b cd 25 01 call hex_to_byte 029e da d4 02 jp c,load_data_entry_error ;non-hex character 02a1 2a 0f 20 ld hl,(current_location) ;get byte address from storage, 02a4 77 ld (hl),a ;store byte 02a5 23 inc hl ;increment address and 02a6 22 0f 20 ld (current_location),hl ;store back 02a9 3a 2d 20 ld a,(buffer) 02ac cd 0c 00 call write_char 02af 3a 2e 20 ld a,(buffer+1) 02b2 cd 0c 00 call write_char 02b5 3a 11 20 ld a,(line_count) ;end of line (16 characters)? 02b8 fe 0f cp 00fh ;yes, start new line 02ba ca c9 02 jp z,load_new_line 02bd 3c inc a ;no, increment line count 02be 32 11 20 ld (line_count),a 02c1 3e 20 ld a,020h ;print space 02c3 cd 0c 00 call write_char 02c6 c3 7e 02 jp load_next_char ;continue 02c9 3e 00 load_new_line: ld a,000h ;reset line count to zero 02cb 32 11 20 ld (line_count),a 02ce cd 5a 08 call newline 02d1 c3 7e 02 jp load_next_char ;continue 02d4 cd 5a 08 load_data_entry_error: call newline 02d7 21 c2 03 ld hl,data_error_msg 02da cd 41 00 call write_string 02dd c9 ret 02de cd 5a 08 load_done: call newline 02e1 c9 ret 02e2 02e2 02e2 ; 02e2 ;Strings used in subroutines 02e2 .. 00 length_entry_string: defm "Enter length of file to load (decimal): ",0 030b .. 00 dump_entry_string: defm "Enter no. of bytes to dump (decimal): ",0 0332 .. 00 address_entry_msg: defm "Enter 4-digit hex address (use upper-case A through F): ",0 036b .. 00 address_error_msg: defm "\rError: invalid hex character, try again: ",0 0396 .. 00 data_entry_msg: defm "Enter hex bytes, hit return when finished.\r",0 03c2 .. 00 data_error_msg: defm "Error: invalid hex byte.\r",0 03dc .. 00 decimal_error_msg: defm "\rError: invalid decimal number, try again: ",0 0408 ; 0408 ;Simple monitor program for CPUville Z80 computer with serial interface. 0408 31 ff 7f monitor_cold_start: ld sp,ROM_monitor_stack 040b 3e 00 ld a,0 ;initialize variables 040d 32 20 20 ld (shift_down),a ;set shift down false 0410 32 21 20 ld (ctrl_down),a ;set ctrl down false 0413 32 0e 20 ld (clear_flag),a ;set clear flag false 0416 32 01 20 ld (test_char),a ;initialize cursor position 0419 32 03 20 ld (test_pos),a 041c 32 02 20 ld (test_line),a 041f 32 2c 20 ld (capslock),a ;set capslock false 0422 cd 3c 06 call clear_screen 0425 cd 1f 06 call initialize_offset_table 0428 cd 03 00 call initialize_port 042b 21 d1 08 ld hl,monitor_message 042e cd 41 00 call write_string 0431 3e 00 ld a,0 0433 32 2a 20 ld (timer_tick),a 0436 3a 2a 20 mcs_delay_loop: ld a,(timer_tick) 0439 fe 28 cp 40 ;about 5 sec delay to allow keyboard to 043b da 36 04 jp c,mcs_delay_loop ; initialize at power-on 043e cd 5a 08 monitor_warm_start: call newline ;routine program return here to avoid re-initialization of port 0441 3e 3e ld a,03eh ;prompt symbol 0443 cd 0c 00 call write_char 0446 21 2d 20 ld hl,buffer 0449 cd 95 00 call get_line ;get monitor input string (command) 044c cd 5a 08 call newline 044f cd 53 04 call parse ;interprets command, returns with address to jump to in HL 0452 e9 jp (hl) 0453 ; 0453 ;Parses an input line stored in buffer for available commands as described in parse table. 0453 ;Returns with address of jump to action for the command in HL 0453 01 60 0a parse: ld bc,parse_table ;bc is pointer to parse_table 0456 0a parse_start: ld a,(bc) ;get pointer to match string from parse table 0457 5f ld e,a 0458 03 inc bc 0459 0a ld a,(bc) 045a 57 ld d,a ;de will is pointer to strings for matching 045b 1a ld a,(de) ;get first char from match string 045c f6 00 or 000h ;zero? 045e ca 79 04 jp z,parser_exit ;yes, exit no_match 0461 21 2d 20 ld hl,buffer ;no, parse input string 0464 be match_loop: cp (hl) ;compare buffer char with match string char 0465 c2 73 04 jp nz,no_match ;no match, go to next match string 0468 f6 00 or 000h ;end of strings (zero)? 046a ca 79 04 jp z,parser_exit ;yes, matching string found 046d 13 inc de ;match so far, point to next char in match string 046e 1a ld a,(de) ;get next character from match string 046f 23 inc hl ;and point to next char in input string 0470 c3 64 04 jp match_loop ;check for match 0473 03 no_match: inc bc ;skip over jump target to 0474 03 inc bc 0475 03 inc bc ;get address of next matching string 0476 c3 56 04 jp parse_start 0479 03 parser_exit: inc bc ;skip to address of jump for match 047a 0a ld a,(bc) 047b 6f ld l,a 047c 03 inc bc 047d 0a ld a,(bc) 047e 67 ld h,a ;returns with jump address in hl 047f c9 ret 0480 ; 0480 ;Actions to be taken on match 0480 ; 0480 ;Memory dump program 0480 ;Input 4-digit hexadecimal address 0480 ;Calls memory_dump subroutine 0480 21 10 09 dump_jump: ld hl,dump_message ;Display greeting 0483 cd 41 00 call write_string 0486 21 32 03 ld hl,address_entry_msg ;get ready to get address 0489 cd 41 00 call write_string 048c cd 5c 01 call address_entry ;returns with address in HL 048f 22 0f 20 ld (current_location),hl 0492 cd 5a 08 call newline 0495 2a 0f 20 ld hl,(current_location) 0498 cd fb 01 call memory_dump 049b c3 3e 04 jp monitor_warm_start 049e ; 049e ;Hex loader, displays formatted input 049e 21 36 09 load_jump: ld hl,load_message ;Display greeting 04a1 cd 41 00 call write_string ;get address to load 04a4 21 32 03 ld hl,address_entry_msg ;get ready to get address 04a7 cd 41 00 call write_string 04aa cd 5c 01 call address_entry 04ad 22 0f 20 ld (current_location),hl 04b0 cd 5a 08 call newline 04b3 2a 0f 20 ld hl,(current_location) 04b6 cd 72 02 call memory_load 04b9 c3 3e 04 jp monitor_warm_start 04bc ; 04bc ;Jump and run do the same thing: get an address and jump to it. 04bc 21 64 09 run_jump: ld hl,run_message ;Display greeting 04bf cd 41 00 call write_string 04c2 21 32 03 ld hl,address_entry_msg ;get ready to get address 04c5 cd 41 00 call write_string 04c8 cd 5c 01 call address_entry 04cb e9 jp (hl) 04cc ; 04cc ;Help and ? do the same thing, display the available commands 04cc 21 f9 08 help_jump: ld hl,help_message 04cf cd 41 00 call write_string 04d2 21 60 0a ld hl,parse_table ;table with pointers to command strings 04d5 7e help_loop: ld a,(hl) ;displays the strings for matching commands by 04d6 4f ld c,a ; getting the string addresses from the 04d7 23 inc hl ; parse table 04d8 7e ld a,(hl) ;pass address of string to hl through a reg 04d9 47 ld b,a 04da 0a ld a,(bc) ;bc now points to start of match string 04db f6 00 or 0 ;exit if no_match string 04dd ca fb 04 jp z,help_done 04e0 22 1c 20 ld (help_table_pointer),hl 04e3 ed 43 1e 20 ld (help_string_pointer),bc 04e7 3e 20 ld a,020h ;space char 04e9 cd 0c 00 call write_char 04ec 2a 1e 20 ld hl,(help_string_pointer) 04ef cd 41 00 call write_string ;writes match string 04f2 2a 1c 20 ld hl,(help_table_pointer) 04f5 23 inc hl ;pass over jump address in table 04f6 23 inc hl 04f7 23 inc hl 04f8 c3 d5 04 jp help_loop 04fb c3 3e 04 help_done: jp monitor_warm_start 04fe ; 04fe ;Binary file load. Need both address to load and length of file 04fe 21 98 09 bload_jump: ld hl,bload_message 0501 cd 41 00 call write_string 0504 21 32 03 ld hl,address_entry_msg 0507 cd 41 00 call write_string 050a cd 5c 01 call address_entry 050d 22 24 20 ld (load_address),hl 0510 cd 5a 08 call newline 0513 21 e2 02 ld hl,length_entry_string 0516 cd 41 00 call write_string 0519 cd 87 01 call decimal_entry 051c 22 22 20 ld (load_length),hl 051f 21 ba 09 ld hl,bload_ready_message 0522 cd 41 00 call write_string 0525 ed 4b 22 20 ld bc,(load_length) 0529 2a 24 20 ld hl,(load_address) 052c cd 71 00 call bload 052f c3 3e 04 jp monitor_warm_start 0532 ; 0532 ;Binary memory dump. Need address of start of dump and no. bytes 0532 21 dd 09 bdump_jump: ld hl,bdump_message 0535 cd 41 00 call write_string 0538 21 32 03 ld hl,address_entry_msg 053b cd 41 00 call write_string 053e cd 5c 01 call address_entry 0541 22 26 20 ld (bdump_address),hl 0544 cd 5a 08 call newline 0547 21 0b 03 ld hl,dump_entry_string 054a cd 41 00 call write_string 054d cd 87 01 call decimal_entry 0550 22 28 20 ld (bdump_length),hl 0553 21 0c 0a ld hl,bdump_ready_message 0556 cd 41 00 call write_string 0559 d3 05 out (5),a ;get_char mode 0 055b cd cb 06 call get_char 055e 2a 26 20 ld hl,(bdump_address) 0561 ed 4b 28 20 ld bc,(bdump_length) 0565 cd 83 00 call bdump 0568 c3 3e 04 jp monitor_warm_start 056b 056b ;Tiny BASIC jump 056b ;Pure jump, so when done with BASIC need to reset computer 056b c3 c7 16 basic_jump: jp tiny_basic 056e 056e 056e ;Prints message for no match to entered command 056e 21 f6 08 no_match_jump: ld hl,no_match_message 0571 cd 41 00 call write_string 0574 21 2d 20 ld hl, buffer 0577 cd 41 00 call write_string 057a c3 3e 04 jp monitor_warm_start 057d 057d ;Put character subroutine 057d ;A has character location in table (ASCII value - 0x20) x 2 057d ;B has line number, from 0 to 23 057d ;C has character postion in line, from 0 to 51 057d ;Does not alter the global line and position variables 057d 32 04 20 put_char: ld (char),a 0580 78 ld a,b 0581 32 05 20 ld (char_line),a 0584 79 ld a,c 0585 32 06 20 ld (char_pos),a 0588 ;Calculate upper-left (anchor) dot location of character 0588 3a 05 20 ld a,(char_line) 058b 47 ld b,a 058c 3e 00 ld a,0 ;starting dot_y 058e 05 pc_loop1: dec b 058f fa 97 05 jp m,pc_next1 0592 c6 0a add a,10 ;width of character line = 10 display lines 0594 c3 8e 05 jp pc_loop1 0597 32 0a 20 pc_next1: ld (anchor_dot_y),a 059a 11 00 00 ld de,0 ;starting dot_x 059d 3a 06 20 ld a,(char_pos) 05a0 47 ld b,a 05a1 05 pc_loop2: dec b 05a2 fa b0 05 jp m,pc_next2 05a5 7b ld a,e 05a6 c6 06 add a,6 05a8 5f ld e,a 05a9 3e 00 ld a,0 05ab 8a adc a,d 05ac 57 ld d,a 05ad c3 a1 05 jp pc_loop2 05b0 ed 53 08 20 pc_next2: ld (anchor_dot_x),de 05b4 05b4 ;Put each dot of the character on the screen 05b4 ;Get dot_x and dot_y offsets from character offset table 05b4 ;Offsets added to anchor dot x and y values 05b4 ;When byte in character offset table = 0xFF, done 05b4 3e 00 ld a,0 05b6 32 00 20 ld (dot_count),a 05b9 3a 04 20 pc_loop3: ld a,(char) 05bc 21 88 0c ld hl,char_table 05bf 85 add a,l 05c0 6f ld l,a 05c1 3e 00 ld a,0 05c3 8c adc a,h 05c4 67 ld h,a 05c5 7e ld a,(hl) ;lsb of char_offsets address 05c6 5f ld e,a 05c7 23 inc hl 05c8 7e ld a,(hl) ;msb of char_offsets address 05c9 57 ld d,a 05ca 62 ld h,d 05cb 6b ld l,e 05cc 3a 00 20 ld a,(dot_count) 05cf 85 add a,l 05d0 6f ld l,a 05d1 3e 00 ld a,0 05d3 8c adc a,h 05d4 67 ld h,a 05d5 7e ld a,(hl) ;get offset value 05d6 fe ff cp 0xff ;quit if at end of offsets list 05d8 ca 1e 06 jp z,pc_done 05db 47 ld b,a ;add y offset to anchor value 05dc 3a 0a 20 ld a,(anchor_dot_y) 05df 80 add a,b 05e0 32 0d 20 ld (dot_y),a 05e3 23 inc hl 05e4 7e ld a,(hl) 05e5 ed 5b 08 20 ld de,(anchor_dot_x) 05e9 83 add a,e ;add x offset to anchor value 05ea 5f ld e,a 05eb 3e 00 ld a,0 05ed 8a adc a,d 05ee 57 ld d,a 05ef ed 53 0b 20 ld (dot_x),de 05f3 23 inc hl 05f4 3a 0e 20 ld a,(clear_flag) ;for backspacing, to erase a char 05f7 fe ff cp 0xff 05f9 ca 09 06 jp z,pc_next3 05fc 3a 0d 20 ld a,(dot_y) 05ff ed 4b 0b 20 ld bc,(dot_x) 0603 cd 52 06 call set_dot 0606 c3 13 06 jp pc_next4 0609 3a 0d 20 pc_next3: ld a,(dot_y) 060c ed 4b 0b 20 ld bc,(dot_x) 0610 cd 8e 06 call clear_dot 0613 3a 00 20 pc_next4: ld a,(dot_count) 0616 3c inc a 0617 3c inc a 0618 32 00 20 ld (dot_count),a 061b c3 b9 05 jp pc_loop3 061e c9 pc_done: ret 061f 061f ;Initialize offset table subroutine 061f ;Creates a table of addresses of the first byte in each line of display 061f ;240 lines, from 0 to 239 061f ;Each table entry is a two-byte address, in little-endian 061f ;Table size is 2 x 240 = 480 bytes 061f ;Puts data into line_offset_table, which has to be declared in global variables section 061f ;Uses hl, de, ix, and b registers 061f initialize_offset_table: 061f 21 00 80 ld hl,vram_start 0622 06 ef ld b,239 0624 11 28 00 ld de,40 0627 dd 21 ad 20 ld ix,line_offset_table 062b dd 75 00 iot_loop1: ld (ix+0),l 062e dd 23 inc ix 0630 dd 74 00 ld (ix+0),h 0633 dd 23 inc ix 0635 10 01 djnz iot_next1 ;uses b as counter 0637 c9 ret 0638 19 iot_next1: add hl,de ;step address by 40 0639 c3 2b 06 jp iot_loop1 063c 063c ;Clear screen subroutine 063c 3e 00 clear_screen: ld a,0x00 063e 47 ld b,a 063f 21 00 80 ld hl,vram_start 0642 78 cs_loop: ld a,b 0643 77 ld (hl),a 0644 7c ld a,h 0645 fe a5 cp 0xa5 0647 c2 4e 06 jp nz,cs_next 064a 7d ld a,l 064b fe 7f cp 0x7f 064d c8 ret z ;done 064e 23 cs_next: inc hl 064f c3 42 06 jp cs_loop 0652 0652 ;set_dot subroutine 0652 ;Places (sets) a dot at co-ordinates (dot number:line number) 0652 ;dot number is x, line number is y 0652 ;Line number between 0 (top line) and 239 (bottom line) 0652 ;Dot number between 0 (left edge) and 319 (right edge) 0652 ;line number passed in A register 0652 ;dot number passed in BC register 0652 ;Uses registers a, b, c, d, e, h, l 0652 21 ad 20 set_dot: ld hl,line_offset_table 0655 57 ld d,a ;temp store line number 0656 85 add a,l 0657 6f ld l,a ;start 16-bit addition of 2x line number 0658 3e 00 ld a,0 065a 8c adc a,h 065b 67 ld h,a 065c 7a ld a,d ;get line number back 065d 85 add a,l ;add again 065e 6f ld l,a 065f 3e 00 ld a,0 0661 8c adc a,h 0662 67 ld h,a ;hl has pointer to address in table 0663 5e ld e,(hl) 0664 23 inc hl 0665 56 ld d,(hl) ;de has address of start of line in vram 0666 79 sd_next1: ld a,c ;divide dot number by 8 to get byte address 0667 cb 3f srl a ;shift lsb of dot number 0669 cb 3f srl a 066b cb 3f srl a ;lop off right 3 bits (bit number in byte) 066d cb 38 srl b ;test if bit number 256 or greater 066f d2 74 06 jp nc,sd_next2 ;no, finish address 0672 c6 20 add a,32 ;yes, add 32 to offset 0674 83 sd_next2: add a,e ;add offset to line address in de 0675 5f ld e,a ;by 16-bit addition 0676 3e 00 ld a,0 0678 8a adc a,d 0679 57 ld d,a ;de has address of byte 067a 79 ld a,c ;get lsb of dot number 067b e6 07 and 0x07 ;mask off all but bit number 067d 21 bf 16 ld hl,dot_table ;table with bit masks 0680 85 add a,l 0681 6f ld l,a 0682 3e 00 ld a,0 0684 8c adc a,h 0685 67 ld h,a 0686 7e ld a,(hl) ;a now has bit mask 0687 47 ld b,a ;put the mask in b 0688 62 ld h,d ;put byte address in hl 0689 6b ld l,e 068a 7e ld a,(hl) ;get the byte from VRAM 068b b0 or b ;set the bit 068c 77 ld (hl),a ;store back 068d c9 ret 068e 068e ;clear_dot subroutine 068e ;Clears (unsets) a dot at co-ordinates (dot number:line number) 068e ;dot number is x, line number is y 068e ;Line number between 0 (top line) and 239 (bottom line) 068e ;Dot number between 0 (left edge) and 319 (right edge) 068e ;line number passed in A register 068e ;dot number passed in BC register 068e ;Uses registers a, b, c, d, e, h, l 068e 21 ad 20 clear_dot: ld hl,line_offset_table 0691 57 ld d,a ;temp store line number 0692 85 add a,l 0693 6f ld l,a ;start 16-bit addition of 2x line number 0694 3e 00 ld a,0 0696 8c adc a,h 0697 67 ld h,a 0698 7a ld a,d ;get line number back 0699 85 add a,l ;add again 069a 6f ld l,a 069b 3e 00 ld a,0 069d 8c adc a,h 069e 67 ld h,a ;hl has pointer to address in table 069f 5e ld e,(hl) 06a0 23 inc hl 06a1 56 ld d,(hl) ;de has address of start of line in vram 06a2 79 cd_next1: ld a,c ;divide dot number by 8 to get byte address 06a3 cb 3f srl a ;shift lsb of dot number 06a5 cb 3f srl a 06a7 cb 3f srl a ;lop off right 3 bits (bit number in byte) 06a9 cb 38 srl b ;test if bit number 256 or greater 06ab d2 b0 06 jp nc,cd_next2 ;no, finish address 06ae c6 20 add a,32 ;yes, add 32 to offset 06b0 83 cd_next2: add a,e ;add offset to line address in de 06b1 5f ld e,a ;by 16-bit addition 06b2 3e 00 ld a,0 06b4 8a adc a,d 06b5 57 ld d,a ;de has address of byte 06b6 79 ld a,c ;get lsb of dot number 06b7 e6 07 and 0x07 ;mask off all but bit number 06b9 21 bf 16 ld hl,dot_table ;table with bit masks 06bc 85 add a,l 06bd 6f ld l,a 06be 3e 00 ld a,0 06c0 8c adc a,h 06c1 67 ld h,a 06c2 7e ld a,(hl) ;a now has bit mask 06c3 2f cpl ;invert it 06c4 47 ld b,a ;put the mask in b 06c5 62 ld h,d ;put byte address in hl 06c6 6b ld l,e 06c7 7e ld a,(hl) ;get the byte from VRAM 06c8 a0 and b ;clear the bit 06c9 77 ld (hl),a ;store back 06ca c9 ret 06cb 06cb ;get_char subroutine, adapted from keyboard-input.asm 06cb ;Program for video display system keyboard interface 06cb ;Gets keyboard scan code from keypress, converts to ASCII character if possible 06cb ;Two modes: 06cb ;Mode 0, call to get_char preceded by out (5),a to clear shift reg 06cb ;Mode 1, call has no precedent 06cb ;In mode 0, get_char will wait for a keypress 06cb ;In mode 1, get_char may or may not wait for a keypress 06cb ;In mode 1, if a keycode is already present, it will return without waiting for a keypress 06cb ;In mode 1, if a keycode is not present, it will wait 06cb ;Uses get_keycode subroutine 06cb ;Uses A, B, and HL registers 06cb ;Returns ASCII in register A, or 0 if no character comes from keypress (i.e. shift) 06cb cd e9 07 get_char: call get_keycode 06ce fe f0 cp 0F0h ;key break 06d0 ca 8f 07 jp z,ki_break 06d3 fe e0 cp 0E0h ;long keycodes 06d5 ca a4 07 jp z,ki_long_keycodes 06d8 fe 12 cp 12h ;left shift key 06da ca c3 07 jp z,ki_shift_make 06dd fe 59 cp 59h ;right shift key 06df ca c3 07 jp z,ki_shift_make 06e2 fe 14 cp 14h ;left ctrl key 06e4 ca bb 07 jp z,ki_ctrl_make 06e7 fe 58 cp 58h ;caps lock 06e9 ca db 07 jp z,ki_capslock_make 06ec ;Check if ctrl key is down 06ec ;If so, return ctrl-characters 06ec 47 ld b,a ;temp store keycode 06ed 3a 21 20 ld a,(ctrl_down) 06f0 fe ff cp 0FFh ;is ctrl- key down? 06f2 ca f8 06 jp z,ki_ctrl_char ;yes, create ctrl-char 06f5 c3 2b 07 jp ki_next_1 ;no, skip to regular ASCII 06f8 78 ki_ctrl_char: ld a,b ;get keycode back 06f9 fe 1a cp 1ah ;Z key 06fb c2 03 07 jp nz,ki_ctrl_next1 06fe 3e 1a ld a,1ah ;ctrl-Z 0700 c3 e8 07 jp ki_output 0703 fe 1c ki_ctrl_next1: cp 1ch ;A key 0705 c2 0d 07 jp nz,ki_ctrl_next2 0708 3e 01 ld a,01h ;ctrl-A 070a c3 e8 07 jp ki_output 070d fe 21 ki_ctrl_next2: cp 21h ;C key 070f c2 17 07 jp nz,ki_ctrl_next3 0712 3e 03 ld a,03h ;ctrl-C 0714 c3 e8 07 jp ki_output 0717 fe 22 ki_ctrl_next3: cp 22h ;X key 0719 c2 21 07 jp nz,ki_ctrl_next4 071c 3e 18 ld a,18h ;ctrl-X 071e c3 e8 07 jp ki_output 0721 fe 44 ki_ctrl_next4: cp 44h ;O key 0723 c2 e5 07 jp nz,ki_null_output ;control char currently undefined 0726 3e 0f ld a,0Fh ;ctrl-O 0728 c3 e8 07 jp ki_output 072b 072b 072b 072b ;See if shift key is down or caps lock or both and use appropriate table 072b 3a 20 20 ki_next_1: ld a,(shift_down) 072e fe ff cp 0FFh ;is shift key down? 0730 ca 4e 07 jp z,ki_shifted ;yes, use shifted table 0733 3a 2c 20 ld a,(capslock) ;is capslock? 0736 fe ff cp 0FFh 0738 ca 69 07 jp z,ki_capslock ;yes, use capslock table 073b 073b ;unshifted ASCII 073b 78 ld a,b ;no, use unshifted table 073c fe 80 cp 80h ;check if keycode out of bounds 073e d2 e5 07 jp nc,ki_null_output 0741 21 88 0a ld hl,unshifted_ascii_table 0744 85 add a,l 0745 6f ld l,a 0746 3e 00 ld a,0 0748 8c adc a,h 0749 67 ld h,a 074a 7e ld a,(hl) 074b c3 e8 07 jp ki_output 074e 074e 3a 2c 20 ki_shifted: ld a,(capslock) 0751 fe ff cp 0FFh ;is caps lock? 0753 ca 7c 07 jp z,ki_shiftcapslock ;yes, use shift + capslock table 0756 78 ld a,b ;get keycode back 0757 fe 80 cp 80h ;check if keycode out of bounds 0759 d2 e5 07 jp nc,ki_null_output 075c 21 08 0b ld hl,shifted_ascii_table 075f 85 add a,l 0760 6f ld l,a 0761 3e 00 ld a,0 0763 8c adc a,h 0764 67 ld h,a 0765 7e ld a,(hl) 0766 c3 e8 07 jp ki_output 0769 0769 78 ki_capslock: ld a,b ;get keycode back 076a fe 80 cp 80h ;check if keycode out of bounds 076c d2 e5 07 jp nc,ki_null_output 076f 21 88 0b ld hl,capslock_ascii_table 0772 85 add a,l 0773 6f ld l,a 0774 3e 00 ld a,0 0776 8c adc a,h 0777 67 ld h,a 0778 7e ld a,(hl) 0779 c3 e8 07 jp ki_output 077c 077c 78 ki_shiftcapslock: ld a,b ;get keycode back 077d fe 80 cp 80h ;check if keycode out of bounds 077f d2 e5 07 jp nc,ki_null_output 0782 21 08 0c ld hl,shiftcapslock_ascii_table 0785 85 add a,l 0786 6f ld l,a 0787 3e 00 ld a,0 0789 8c adc a,h 078a 67 ld h,a 078b 7e ld a,(hl) 078c c3 e8 07 jp ki_output 078f 078f cd e9 07 ki_break: call get_keycode ;get identity of key that caused break 0792 fe 12 cp 12h ;left shift key 0794 ca d3 07 jp z,ki_shift_break 0797 fe 59 cp 59h ;right shift key 0799 ca d3 07 jp z,ki_shift_break 079c fe 14 cp 14h ;ctrl key (either -- can come from long keycodes too) 079e ca cb 07 jp z,ki_ctrl_break 07a1 c3 e5 07 jp ki_null_output ;ignore other breaks 07a4 07a4 cd e9 07 ki_long_keycodes: call get_keycode ;get next keycode value 07a7 fe f0 cp 0F0h ;long keycode break 07a9 ca 8f 07 jp z,ki_break 07ac fe 14 cp 14h ;E0 14 is right ctrl key 07ae ca bb 07 jp z,ki_ctrl_make 07b1 fe 71 cp 71h 07b3 3e 7f ld a,7Fh ;delete 07b5 ca e8 07 jp z,ki_output 07b8 c3 e5 07 jp ki_null_output ;ignore other long keycodes for now 07bb 07bb 3e ff ki_ctrl_make: ld a,0ffh 07bd 32 21 20 ld (ctrl_down),a 07c0 c3 e5 07 jp ki_null_output 07c3 07c3 3e ff ki_shift_make: ld a,0ffh 07c5 32 20 20 ld (shift_down),a 07c8 c3 e5 07 jp ki_null_output 07cb 07cb 3e 00 ki_ctrl_break: ld a,00h 07cd 32 21 20 ld (ctrl_down),a 07d0 c3 e5 07 jp ki_null_output 07d3 07d3 3e 00 ki_shift_break: ld a,00h 07d5 32 20 20 ld (shift_down),a 07d8 c3 e5 07 jp ki_null_output 07db 07db 3a 2c 20 ki_capslock_make: ld a,(capslock) 07de 2f cpl 07df 32 2c 20 ld (capslock),a 07e2 c3 e5 07 jp ki_null_output ;no need to wait for another keycode 07e5 07e5 c3 cb 06 ki_null_output: jp get_char ;exit only when have ASCII 07e8 c9 ki_output: ret ;exit here when have ASCII 07e9 07e9 ;get_keycode subroutine 07e9 ;Keyboard output is 11 serial bits, inverted 07e9 ;Output goes through two shift registers in a row 07e9 ;Shift registers configured as input ports 4 and 5 07e9 ;Once 11 bits received and complemented they are: 07e9 ;Read port 4 returns: 07e9 ; D7 = Stop bit 07e9 ; D6 = Parity bit 07e9 ; D5 to D0 = keycode bits D7 to D2 07e9 ;Read port 5 returns: 07e9 ; D7 = keycode bit D1 07e9 ; D6 = keycode bit D0 07e9 ; D5 = Start bit 07e9 ; D4 to D0 = 0 07e9 ;Write port 5 clears both shift registers 07e9 ;Polls port 5 for D5 = 1 (start bit of 11-bit keyboard output) 07e9 ;Code in central loop to blink cursor while awaiting input 07e9 ;Returns keycode in A register 07e9 3e 04 get_keycode: ld a,4 07eb 32 2a 20 ld (timer_tick),a ;set initial count for blinking 07ee 3a 2b 20 gk_loop1: ld a,(blink_flag) 07f1 fe ff cp 0FFh 07f3 c2 17 08 jp nz,gk_next1 ;don't blink cursor 07f6 3a 2a 20 ld a,(timer_tick) 07f9 fe 08 cp 08h ;blink every 8 ticks 07fb c2 17 08 jp nz,gk_next1 ;don't blink yet 07fe ;code to blink character at cursor location 07fe ;clear_flag used by put_char to determine if character is to be written or erased 07fe 3e 00 ld a,0 ;OK, blink 0800 32 2a 20 ld (timer_tick),a ;reset timer 0803 3a 0e 20 ld a,(clear_flag) ;flip clear flag 0806 2f cpl 0807 32 0e 20 ld (clear_flag),a 080a 3a 03 20 ld a,(test_pos) ;write or erase underline char 080d 4f ld c,a 080e 3a 02 20 ld a,(test_line) 0811 47 ld b,a 0812 3e 7e ld a,7Eh ;underline char in table 0814 cd 7d 05 call put_char 0817 db 05 gk_next1: in a,(5) ;polling loop for start bit 0819 e6 20 and 20h ;check for start bit = 1 081b ca ee 07 jp z,gk_loop1 ;no, keep looking 081e db 04 in a,(4) ;yes, get shift register contents 0820 2f cpl 0821 cb 27 sla a ;shift left twice 0823 cb 27 sla a 0825 47 ld b,a ;temp storage 0826 db 05 in a,(5) ;get shift register contents 0828 d3 05 out (5),a ;clear shift registers 082a 2f cpl 082b cb 3f srl a ;logical shift right 6 times 082d cb 3f srl a 082f cb 3f srl a 0831 cb 3f srl a 0833 cb 3f srl a 0835 cb 3f srl a 0837 b0 or b ;combine with upper part 0838 f5 push af ;keycode in a reg, store keycode 0839 3a 2b 20 ld a,(blink_flag) ;if blinking, need to clear underline char 083c fe ff cp 0FFh ;was blink flag true? 083e c2 58 08 jp nz,gk_done ;no, not blinking, done 0841 3e ff ld a,0FFh ;yes, make clear flag true 0843 32 0e 20 ld (clear_flag),a 0846 3a 03 20 ld a,(test_pos) ;erase underline char 0849 4f ld c,a 084a 3a 02 20 ld a,(test_line) 084d 47 ld b,a 084e 3e 7e ld a,7Eh ;underline char in table 0850 cd 7d 05 call put_char 0853 3e 00 ld a,0 ;make clear flag false 0855 32 0e 20 ld (clear_flag),a 0858 f1 gk_done: pop af ;get keycode back 0859 c9 ret ;keycode will be in A reg 085a 085a ;newline subroutine 085a ;increases line number by one 085a ;if line off screen, scrolls 085a ;puts cursor back to beginning of next line 085a 3e 00 newline: ld a,0 085c 32 03 20 ld (test_pos),a ;cursor to start of line 085f 3a 02 20 ld a,(test_line) 0862 3c inc a 0863 fe 18 cp 24 ;off bottom of screen 0865 c2 6c 08 jp nz,nl_next1 0868 cd 70 08 call scroll 086b c9 ret 086c 32 02 20 nl_next1: ld (test_line),a 086f c9 ret 0870 0870 ;scroll subroutine 0870 ;called if line = 24 (off screen) 0870 ;copies vram bytes from location to location-400 (ten scan lines above) 0870 ;starts at vram + 400 (first byte in line 1) 0870 ;copies 9600 - 400 bytes = 9200 bytes, counter in de 0870 ;when finished, blanks line 23 and puts cursor at beginning of line 0870 11 f0 23 scroll: ld de,9200 ;no. bytes to copy 0873 21 90 81 ld hl,vram_start + 400 ;source 0876 01 00 80 ld bc,vram_start ;target 0879 7e scroll_loop1: ld a,(hl) 087a 02 ld (bc),a 087b 1b dec de ;zero flag not affected so 087c 7a ld a,d ;check for zero this way 087d b3 or e 087e ca 86 08 jp z,scroll_done 0881 23 inc hl 0882 03 inc bc 0883 c3 79 08 jp scroll_loop1 0886 ;done moving, clear bottom line 0886 3e 17 scroll_done: ld a,23 0888 32 02 20 ld (test_line),a ;last line of display 088b cd 8f 08 call clear_line 088e c9 ret 088f 088f ;clear_line subroutine 088f ;clears the line given by test_line 088f ;does not alter test_line 088f ;sets cursor at start of line 088f 21 00 80 clear_line: ld hl,vram_start 0892 01 90 01 ld bc,400 ;index value 0895 3a 02 20 ld a,(test_line) 0898 ;adjust address to first byte in line to be cleared 0898 fe 00 cl_loop1: cp 0 ;done, go on 089a ca a2 08 jp z,cl_loop2 089d 09 add hl,bc 089e 3d dec a 089f c3 98 08 jp cl_loop1 08a2 3e 00 cl_loop2: ld a,0 08a4 77 ld (hl),a 08a5 23 inc hl 08a6 0b dec bc ;bc starts with 400, from above 08a7 78 ld a,b 08a8 b1 or c ;check for zero this way 08a9 c2 a2 08 jp nz,cl_loop2 08ac 3e 00 ld a,0 ;set cursor to start of line 08ae 32 03 20 ld (test_pos),a 08b1 c9 ret 08b2 08b2 ;backspace subroutine 08b2 ;moves cursor back one space, erases character 08b2 ;Stops if at beginning of line 08b2 3a 03 20 backspace: ld a,(test_pos) 08b5 fe 00 cp 0 ;at start of line, can't backspace 08b7 c8 ret z 08b8 3d dec a 08b9 32 03 20 ld (test_pos),a 08bc 4f ld c,a 08bd 3a 02 20 ld a,(test_line) 08c0 47 ld b,a 08c1 3e ff ld a,0xff 08c3 32 0e 20 ld (clear_flag),a ;causes put_char to clear instead of set dots 08c6 3e be ld a,190 ;block character in table 08c8 cd 7d 05 call put_char 08cb 3e 00 ld a,0 08cd 32 0e 20 ld (clear_flag),a 08d0 c9 ret 08d1 08d1 ;Monitor data structures: 08d1 .. 00 monitor_message: defm "\rStandalone Z80 computer ROM ver. 1\r",0 08f6 .. 00 no_match_message: defm "? ",0 08f9 .. 00 help_message: defm "Commands implemented:\r",0 0910 .. 00 dump_message: defm "Displays a 256-byte block of memory.\r",0 0936 .. 00 load_message: defm "Enter hex bytes starting at memory location.\r",0 0964 .. 00 run_message: defm "Will jump to (execute) program at address entered.\r",0 0998 .. 00 bload_message: defm "Loads a binary file into memory.\r",0 09ba .. 00 bload_ready_message: defm "\rReady to receive, start transfer.",0 09dd .. 00 bdump_message: defm "Dumps binary data from memory to serial port.\r",0 0a0c .. 00 bdump_ready_message: defm "\rReady to send, hit any key to start.",0 0a32 0a32 ;Strings for matching: 0a32 .. 00 dump_string: defm "dump",0 0a37 .. 00 load_string: defm "load",0 0a3c .. 00 jump_string: defm "jump",0 0a41 .. 00 run_string: defm "run",0 0a45 .. 00 question_string: defm "?",0 0a47 .. 00 help_string: defm "help",0 0a4c .. 00 bload_string: defm "bload",0 0a52 .. 00 bdump_string: defm "bdump",0 0a58 .. 00 basic_string: defm "basic",0 0a5e 00 00 no_match_string: defm 0,0 0a60 0a60 ;Table for matching strings to jumps 0a60 32 0a 80 04 37 0a 9e 04 parse_table: defw dump_string,dump_jump,load_string,load_jump 0a68 3c 0a bc 04 41 0a bc 04 defw jump_string,run_jump,run_string,run_jump 0a70 45 0a cc 04 47 0a cc 04 defw question_string,help_jump,help_string,help_jump 0a78 4c 0a fe 04 52 0a 32 05 defw bload_string,bload_jump,bdump_string,bdump_jump 0a80 58 0a 6b 05 5e 0a 6e 05 defw basic_string,basic_jump,no_match_string,no_match_jump 0a88 ;ASCII tables 0a88 ;Add keycode value to address to retrieve ASCII equivalent 0a88 ;Tables for unshifted, shifted, capslock, and shift+capslock characters 0a88 0a88 unshifted_ascii_table: 0a88 00 00 00 00 00 00 00 00 00 00 00 00 00 09 60 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,09h,60h,0 0a98 00 00 00 00 00 71 31 00 00 00 7a 73 61 77 32 00 db 0,0,0,0,0,71h,31h,0,0,0,7Ah,73h,61h,77h,32h,0 0aa8 00 63 78 64 65 34 33 00 00 20 76 66 74 72 35 00 db 0,63h,78h,64h,65h,34h,33h,0,0,20h,76h,66h,74h,72h,35h,0 0ab8 00 6e 62 68 67 79 36 00 00 00 6d 6a 75 37 38 00 db 0,6Eh,62h,68h,67h,79h,36h,0,0,0,6Dh,6Ah,75h,37h,38h,0 0ac8 00 2c 6b 69 6f 30 39 00 00 2e 2f 6c 3b 70 2d 00 db 0,2Ch,6Bh,69h,6Fh,30h,39h,0,0,2Eh,2Fh,6Ch,3Bh,70h,2Dh,0 0ad8 00 00 27 00 5b 3d 00 00 00 00 0d 5d 00 5c 00 00 db 0,0,27h,0,5Bh,3Dh,0,0,0,0,0Dh,5Dh,0,5Ch,0,0 0ae8 00 00 00 00 00 00 08 00 00 31 00 34 37 00 00 00 db 0,0,0,0,0,0,08h,0,0,31h,0,34h,37h,0,0,0 0af8 30 2e 32 35 36 38 1b 00 00 2b 33 2d 2a 39 00 00 db 30h,2Eh,32h,35h,36h,38h,1Bh,0,0,2Bh,33h,2Dh,2Ah,39h,0,0 0b08 0b08 shifted_ascii_table: 0b08 00 00 00 00 00 00 00 00 00 00 00 00 00 09 7e 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,09h,7Eh,0 0b18 00 00 00 00 00 51 21 00 00 00 5a 53 41 57 40 00 db 0,0,0,0,0,51h,21h,0,0,0,5Ah,53h,41h,57h,40h,0 0b28 00 43 58 44 45 24 23 00 00 20 56 46 54 52 25 00 db 0,43h,58h,44h,45h,24h,23h,0,0,20h,56h,46h,54h,52h,25h,0 0b38 00 4e 42 48 47 59 5e 00 00 00 4d 4a 55 26 2a 00 db 0,4Eh,42h,48h,47h,59h,5Eh,0,0,0,4Dh,4Ah,55h,26h,2Ah,0 0b48 00 3c 4b 49 4f 29 28 00 00 3e 3f 4c 3a 50 5f 00 db 0,3Ch,4Bh,49h,4Fh,29h,28h,0,0,3Eh,3Fh,4Ch,3Ah,50h,5Fh,0 0b58 00 00 22 00 7b 2b 00 00 00 00 0d 7d 00 7c 00 00 db 0,0,22h,0,7Bh,2Bh,0,0,0,0,0Dh,7Dh,0,7Ch,0,0 0b68 00 00 00 00 00 00 08 00 00 31 00 34 37 00 00 00 db 0,0,0,0,0,0,08h,0,0,31h,0,34h,37h,0,0,0 0b78 30 2e 32 35 36 38 1b 00 00 2b 33 2d 2a 39 00 00 db 30h,2Eh,32h,35h,36h,38h,1Bh,0,0,2Bh,33h,2Dh,2Ah,39h,0,0 0b88 0b88 capslock_ascii_table: 0b88 00 00 00 00 00 00 00 00 00 00 00 00 00 09 60 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,09h,60h,0 0b98 00 00 00 00 00 51 31 00 00 00 5a 53 41 57 32 00 db 0,0,0,0,0,51h,31h,0,0,0,5Ah,53h,41h,57h,32h,0 0ba8 00 43 58 44 45 34 33 00 00 20 56 46 54 52 35 00 db 0,43h,58h,44h,45h,34h,33h,0,0,20h,56h,46h,54h,52h,35h,0 0bb8 00 4e 42 48 47 59 36 00 00 00 4d 4a 55 37 38 00 db 0,4Eh,42h,48h,47h,59h,36h,0,0,0,4Dh,4Ah,55h,37h,38h,0 0bc8 00 2c 4b 49 4f 30 39 00 00 2e 2f 4c 3b 50 2d 00 db 0,2Ch,4Bh,49h,4Fh,30h,39h,0,0,2Eh,2Fh,4Ch,3Bh,50h,2Dh,0 0bd8 00 00 60 00 5b 3d 00 00 00 00 0d 5d 00 5c 00 00 db 0,0,60h,0,5Bh,3Dh,0,0,0,0,0Dh,5Dh,0,5Ch,0,0 0be8 00 00 00 00 00 00 08 00 00 31 00 34 37 00 00 00 db 0,0,0,0,0,0,08h,0,0,31h,0,34h,37h,0,0,0 0bf8 30 2e 32 35 36 38 1b 00 00 2b 33 2d 2a 39 00 00 db 30h,2Eh,32h,35h,36h,38h,1Bh,0,0,2Bh,33h,2Dh,2Ah,39h,0,0 0c08 0c08 0c08 shiftcapslock_ascii_table: 0c08 00 00 00 00 00 00 00 00 00 00 00 00 00 09 7e 00 db 0,0,0,0,0,0,0,0,0,0,0,0,0,09h,7Eh,0 0c18 00 00 00 00 00 71 21 00 00 00 7a 73 61 77 40 00 db 0,0,0,0,0,71h,21h,0,0,0,7Ah,73h,61h,77h,40h,0 0c28 00 63 78 64 65 24 23 00 00 20 76 66 74 72 25 00 db 0,63h,78h,64h,65h,24h,23h,0,0,20h,76h,66h,74h,72h,25h,0 0c38 00 6e 62 68 67 79 5e 00 00 00 6d 6a 75 26 2a 00 db 0,6Eh,62h,68h,67h,79h,5Eh,0,0,0,6Dh,6Ah,75h,26h,2Ah,0 0c48 00 3c 6b 69 6f 29 28 00 00 3e 3f 6c 3a 70 5f 00 db 0,3Ch,6Bh,69h,6Fh,29h,28h,0,0,3Eh,3Fh,6Ch,3Ah,70h,5Fh,0 0c58 00 00 22 00 7b 2b 00 00 00 00 0d 7d 00 7c 00 00 db 0,0,22h,0,7Bh,2Bh,0,0,0,0,0Dh,7Dh,0,7Ch,0,0 0c68 00 00 00 00 00 00 08 00 00 31 00 34 37 00 00 00 db 0,0,0,0,0,0,08h,0,0,31h,0,34h,37h,0,0,0 0c78 30 2e 32 35 36 38 1b 00 00 2b 33 2d 2a 39 00 00 db 30h,2Eh,32h,35h,36h,38h,1Bh,0,0,2Bh,33h,2Dh,2Ah,39h,0,0 0c88 0c88 0c88 ;Tables used by character-creating subroutines 0c88 0c88 aa 11 70 12 dd 11 char_table: defw space_char_offsets,exclam_char_offsets,quote_char_offsets 0c8e 11 15 36 15 59 15 defw hash_char_offsets,dollar_char_offsets,percent_char_offsets 0c94 78 15 95 15 9a 15 defw ampersand_char_offsets,apost_char_offsets,L_paren_char_offsets 0c9a a9 15 b8 15 ba 11 defw R_paren_char_offsets,asterix_char_offsets,plus_char_offsets 0ca0 b3 11 cd 11 b0 11 defw comma_char_offsets,minus_char_offsets,period_char_offsets 0ca6 61 12 74 10 97 10 defw forslash_char_offsets,zero_char_offsets,one_char_offsets 0cac ac 10 cb 10 e8 10 07 11 defw two_char_offsets,three_char_offsets,four_char_offsets,five_char_offsets 0cb4 2a 11 4d 11 64 11 87 11 defw six_char_offsets,seven_char_offsets,eight_char_offsets,nine_char_offsets 0cbc ab 11 d4 11 e6 11 defw colon_char_offsets,semicolon_char_offsets,less_char_offsets 0cc2 04 12 f5 11 11 12 defw equal_char_offsets,greater_char_offsets,question_char_offsets 0cc8 c3 15 defw at_char_offsets 0cca 4a 0d 6f 0d 98 0d b3 0d defw A_char_offsets,B_char_offsets,C_char_offsets,D_char_offsets 0cd2 d8 0d fd 0d 1a 0e 3b 0e defw E_char_offsets,F_char_offsets,G_char_offsets,H_char_offsets 0cda 5e 0e 75 0e 8c 0e a9 0e defw I_char_offsets,J_char_offsets,K_char_offsets,L_char_offsets 0ce2 c0 0e e3 0e 06 0f 27 0f defw M_char_offsets,N_char_offsets,O_char_offsets,P_char_offsets 0cea 46 0f 6d 0f 92 0f b1 0f defw Q_char_offsets,R_char_offsets,S_char_offsets,T_char_offsets 0cf2 c8 0f e7 0f 02 10 25 10 defw U_char_offsets,V_char_offsets,W_char_offsets,X_char_offsets 0cfa 40 10 55 10 24 12 defw Y_char_offsets,Z_char_offsets,L_bracket_char_offsets 0d00 52 12 3b 12 30 16 defw backslash_char_offsets,R_bracket_char_offsets,carat_char_offsets 0d06 ea 15 f5 15 defw under_char_offsets,accent_char_offsets 0d0a 7d 12 9a 12 bb 12 ce 12 defw a_char_offsets,b_char_offsets,c_char_offsets,d_char_offsets 0d12 ef 12 0e 13 25 13 48 13 defw e_char_offsets,f_char_offsets,g_char_offsets,h_char_offsets 0d1a 63 13 6e 13 81 13 9a 13 defw i_char_offsets,j_char_offsets,k_char_offsets,l_char_offsets 0d22 a9 13 c4 13 db 13 f4 13 defw m_char_offsets,n_char_offsets,o_char_offsets,p_char_offsets 0d2a 15 14 36 14 49 14 64 14 defw q_char_offsets,r_char_offsets,s_char_offsets,t_char_offsets 0d32 7b 14 94 14 a7 14 c2 14 defw u_char_offsets,v_char_offsets,w_char_offsets,x_char_offsets 0d3a d5 14 f6 14 fa 15 18 16 defw y_char_offsets,z_char_offsets,L_curly_char_offsets,pipe_char_offsets 0d42 09 16 25 16 3b 16 defw R_curly_char_offsets,tilde_char_offsets,block_char_offsets 0d48 96 16 defw square_char_offsets 0d4a 0d4a 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 01 03 02 03 03 03 04 04 00 04 04 05 00 05 04 06 00 06 04 ff A_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,1,3,2,3,3,3,4,4,0,4,4,5,0,5,4,6,0,6,4,0xFF 0d6f 00 00 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 01 03 02 03 03 04 00 04 04 05 00 05 04 06 00 06 01 06 02 06 03 ff B_char_offsets: defb 0,0,0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,1,3,2,3,3,4,0,4,4,5,0,5,4,6,0,6,1,6,2,6,3,0xFF 0d98 00 01 00 02 00 03 01 00 01 04 02 00 03 00 04 00 05 00 05 04 06 01 06 02 06 03 ff C_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,3,0,4,0,5,0,5,4,6,1,6,2,6,3,0xFF 0db3 00 00 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 00 06 01 06 02 06 03 ff D_char_offsets: defb 0,0,0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,0,6,1,6,2,6,3,0xFF 0dd8 00 00 00 01 00 02 00 03 00 04 01 00 02 00 03 00 03 01 03 02 03 03 04 00 05 00 06 00 06 01 06 02 06 03 06 04 ff E_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,0,2,0,3,0,3,1,3,2,3,3,4,0,5,0,6,0,6,1,6,2,6,3,6,4,0xFF 0dfd 00 00 00 01 00 02 00 03 00 04 01 00 02 00 03 00 03 01 03 02 03 03 04 00 05 00 06 00 ff F_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,0,2,0,3,0,3,1,3,2,3,3,4,0,5,0,6,0,0xFF 0e1a 00 01 00 02 00 03 01 00 01 04 02 00 03 00 03 02 03 03 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff G_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,3,0,3,2,3,3,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 0e3b 00 00 00 04 01 00 01 04 02 00 02 04 03 00 03 01 03 02 03 03 03 04 04 00 04 04 05 00 05 04 06 00 06 04 ff H_char_offsets: defb 0,0,0,4,1,0,1,4,2,0,2,4,3,0,3,1,3,2,3,3,3,4,4,0,4,4,5,0,5,4,6,0,6,4,0xFF 0e5e 00 02 00 03 00 04 01 03 02 03 03 03 04 03 05 03 06 02 06 03 06 04 ff I_char_offsets: defb 0,2,0,3,0,4,1,3,2,3,3,3,4,3,5,3,6,2,6,3,6,4,0xFF 0e75 00 02 00 03 00 04 01 03 02 03 03 03 04 03 05 00 05 03 06 01 06 02 ff J_char_offsets: defb 0,2,0,3,0,4,1,3,2,3,3,3,4,3,5,0,5,3,6,1,6,2,0xFF 0e8c 00 00 00 04 01 00 01 03 02 00 02 02 03 00 03 01 04 00 04 02 05 00 05 03 06 00 06 04 ff K_char_offsets: defb 0,0,0,4,1,0,1,3,2,0,2,2,3,0,3,1,4,0,4,2,5,0,5,3,6,0,6,4,0xFF 0ea9 00 00 01 00 02 00 03 00 04 00 05 00 06 00 06 01 06 02 06 03 06 04 ff L_char_offsets: defb 0,0,1,0,2,0,3,0,4,0,5,0,6,0,6,1,6,2,6,3,6,4,0xFF 0ec0 00 00 00 04 01 00 01 01 01 03 01 04 02 00 02 02 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 00 06 04 ff M_char_offsets: defb 0,0,0,4,1,0,1,1,1,3,1,4,2,0,2,2,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,0,6,4,0xFF 0ee3 00 00 00 04 01 00 01 04 02 00 02 01 02 04 03 00 03 02 03 04 04 00 04 03 04 04 05 00 05 04 06 00 06 04 ff N_char_offsets: defb 0,0,0,4,1,0,1,4,2,0,2,1,2,4,3,0,3,2,3,4,4,0,4,3,4,4,5,0,5,4,6,0,6,4,0xFF 0f06 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff O_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 0f27 00 00 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 01 03 02 03 03 04 00 05 00 06 00 ff P_char_offsets: defb 0,0,0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,1,3,2,3,3,4,0,5,0,6,0,0xFF 0f46 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 02 04 04 05 00 05 03 05 04 06 01 06 02 06 03 06 04 ff Q_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,2,4,4,5,0,5,3,5,4,6,1,6,2,6,3,6,4,0xFF 0f6d 00 00 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 01 03 02 03 03 04 00 04 02 05 00 05 03 06 00 06 04 ff R_char_offsets: defb 0,0,0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,1,3,2,3,3,4,0,4,2,5,0,5,3,6,0,6,4,0xFF 0f92 00 01 00 02 00 03 01 00 01 04 02 00 03 01 03 02 03 03 04 04 05 00 05 04 06 01 06 02 06 03 ff S_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,3,1,3,2,3,3,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 0fb1 00 00 00 01 00 02 00 03 00 04 01 02 02 02 03 02 04 02 05 02 06 02 ff T_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,2,2,2,3,2,4,2,5,2,6,2,0xFF 0fc8 00 00 00 04 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff U_char_offsets: defb 0,0,0,4,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 0fe7 00 00 00 04 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 04 05 01 05 03 06 02 ff V_char_offsets: defb 0,0,0,4,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,4,5,1,5,3,6,2,0xFF 1002 00 00 00 04 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 02 04 04 05 00 05 01 05 03 05 04 06 00 06 04 ff W_char_offsets: defb 0,0,0,4,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,2,4,4,5,0,5,1,5,3,5,4,6,0,6,4,0xFF 1025 00 00 00 04 01 00 01 04 02 01 02 03 03 02 04 01 04 03 05 00 05 04 06 00 06 04 ff X_char_offsets: defb 0,0,0,4,1,0,1,4,2,1,2,3,3,2,4,1,4,3,5,0,5,4,6,0,6,4,0xFF 1040 00 00 00 04 01 00 01 04 02 01 02 03 03 02 04 02 05 02 06 02 ff Y_char_offsets: defb 0,0,0,4,1,0,1,4,2,1,2,3,3,2,4,2,5,2,6,2,0xFF 1055 00 00 00 01 00 02 00 03 00 04 01 04 02 03 03 02 04 01 05 00 06 00 06 01 06 02 06 03 06 04 ff Z_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,4,2,3,3,2,4,1,5,0,6,0,6,1,6,2,6,3,6,4,0xFF 1074 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 00 03 02 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff zero_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,0,3,2,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 1097 00 02 01 01 01 02 02 02 03 02 04 02 05 02 06 01 06 02 06 03 ff one_char_offsets: defb 0,2,1,1,1,2,2,2,3,2,4,2,5,2,6,1,6,2,6,3,0xFF 10ac 00 01 00 02 00 03 01 00 01 04 02 04 03 02 03 03 04 01 05 00 06 00 06 01 06 02 06 03 06 04 ff two_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,4,3,2,3,3,4,1,5,0,6,0,6,1,6,2,6,3,6,4,0xFF 10cb 00 01 00 02 00 03 01 00 01 04 02 04 03 02 03 03 04 04 05 00 05 04 06 01 06 02 06 03 ff three_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,4,3,2,3,3,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 10e8 00 02 00 03 01 01 01 03 02 00 02 03 03 00 03 03 04 00 04 01 04 02 04 03 04 04 05 03 06 03 ff four_char_offsets: defb 0,2,0,3,1,1,1,3,2,0,2,3,3,0,3,3,4,0,4,1,4,2,4,3,4,4,5,3,6,3,0xFF 1107 00 00 00 01 00 02 00 03 00 04 01 00 02 00 03 00 03 01 03 02 03 03 04 04 05 04 06 00 06 01 06 02 06 03 ff five_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,0,2,0,3,0,3,1,3,2,3,3,4,4,5,4,6,0,6,1,6,2,6,3,0xFF 112a 00 01 00 02 00 03 01 00 01 04 02 00 03 00 03 01 03 02 03 03 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff six_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,3,0,3,1,3,2,3,3,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 114d 00 00 00 01 00 02 00 03 00 04 01 04 02 03 03 02 04 02 05 01 06 01 ff seven_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,4,2,3,3,2,4,2,5,1,6,1,0xFF 1164 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 01 03 02 03 03 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff eight_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,1,3,2,3,3,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 1187 00 01 00 02 00 03 01 00 01 04 02 00 02 04 03 01 03 02 03 03 03 04 04 04 05 00 05 04 06 01 06 02 06 03 ff nine_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,4,3,1,3,2,3,3,3,4,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 11aa ff space_char_offsets: defb 0xFF 11ab 02 02 04 02 ff colon_char_offsets: defb 2,2,4,2,0xFF 11b0 06 02 ff period_char_offsets: defb 6,2,0xFF 11b3 05 02 06 02 07 01 ff comma_char_offsets: defb 5,2,6,2,7,1,0xFF 11ba 01 02 02 02 03 00 03 01 03 02 03 03 03 04 04 02 05 02 ff plus_char_offsets: defb 1,2,2,2,3,0,3,1,3,2,3,3,3,4,4,2,5,2,0xFF 11cd 03 01 03 02 03 03 ff minus_char_offsets: defb 3,1,3,2,3,3,0xFF 11d4 02 02 05 02 06 02 07 01 ff semicolon_char_offsets: defb 2,2,5,2,6,2,7,1,0xFF 11dd 00 01 00 04 01 01 01 04 ff quote_char_offsets: defb 0,1,0,4,1,1,1,4,0xFF 11e6 00 03 01 02 02 01 03 00 04 01 05 02 06 03 ff less_char_offsets: defb 0,3,1,2,2,1,3,0,4,1,5,2,6,3,0xFF 11f5 00 00 01 01 02 02 03 03 04 02 05 01 06 00 ff greater_char_offsets: defb 0,0,1,1,2,2,3,3,4,2,5,1,6,0,0xFF 1204 02 01 02 02 02 03 04 01 04 02 04 03 ff equal_char_offsets: defb 2,1,2,2,2,3,4,1,4,2,4,3,0xFF 1211 00 01 00 02 00 03 01 00 01 04 02 04 03 03 04 02 06 02 ff question_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,4,3,3,4,2,6,2,0xFF 1224 00 01 00 02 00 03 01 01 02 01 03 01 04 01 05 01 06 01 06 02 06 03 ff L_bracket_char_offsets: defb 0,1,0,2,0,3,1,1,2,1,3,1,4,1,5,1,6,1,6,2,6,3,0xFF 123b 00 01 00 02 00 03 01 03 02 03 03 03 04 03 05 03 06 01 06 02 06 03 ff R_bracket_char_offsets: defb 0,1,0,2,0,3,1,3,2,3,3,3,4,3,5,3,6,1,6,2,6,3,0xFF 1252 00 00 01 01 02 01 03 02 04 03 05 03 06 04 ff backslash_char_offsets: defb 0,0,1,1,2,1,3,2,4,3,5,3,6,4,0xFF 1261 00 04 01 03 02 03 03 02 04 01 05 01 06 00 ff forslash_char_offsets: defb 0,4,1,3,2,3,3,2,4,1,5,1,6,0,0xFF 1270 00 02 01 02 02 02 03 02 04 02 06 02 ff exclam_char_offsets: defb 0,2,1,2,2,2,3,2,4,2,6,2,0xFF 127d 02 01 02 02 02 03 03 04 04 01 04 02 04 03 04 04 05 00 05 04 06 01 06 02 06 03 06 04 ff a_char_offsets: defb 2,1,2,2,2,3,3,4,4,1,4,2,4,3,4,4,5,0,5,4,6,1,6,2,6,3,6,4,0xFF 129a 00 00 01 00 02 00 02 01 02 02 02 03 03 00 03 04 04 00 04 04 05 00 05 04 06 00 06 01 06 02 06 03 ff b_char_offsets: defb 0,0,1,0,2,0,2,1,2,2,2,3,3,0,3,4,4,0,4,4,5,0,5,4,6,0,6,1,6,2,6,3,0xFF 12bb 02 01 02 02 02 03 03 00 04 00 05 00 06 01 06 02 06 03 ff c_char_offsets: defb 2,1,2,2,2,3,3,0,4,0,5,0,6,1,6,2,6,3,0xFF 12ce 00 04 01 04 02 01 02 02 02 03 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 06 04 ff d_char_offsets: defb 0,4,1,4,2,1,2,2,2,3,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,6,4,0xFF 12ef 02 01 02 02 02 03 03 00 03 04 04 00 04 01 04 02 04 03 04 04 05 00 06 01 06 02 06 03 06 04 ff e_char_offsets: defb 2,1,2,2,2,3,3,0,3,4,4,0,4,1,4,2,4,3,4,4,5,0,6,1,6,2,6,3,6,4,0xFF 130e 00 02 00 03 01 01 01 04 02 01 03 01 03 02 03 03 04 01 05 01 06 01 ff f_char_offsets: defb 0,2,0,3,1,1,1,4,2,1,3,1,3,2,3,3,4,1,5,1,6,1,0xFF 1325 02 01 02 02 02 03 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 06 04 07 04 08 01 08 02 08 03 ff g_char_offsets: defb 2,1,2,2,2,3,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,6,4,7,4,8,1,8,2,8,3,0xFF 1348 00 00 01 00 02 00 03 00 03 01 03 02 03 03 04 00 04 04 05 00 05 04 06 00 06 04 ff h_char_offsets: defb 0,0,1,0,2,0,3,0,3,1,3,2,3,3,4,0,4,4,5,0,5,4,6,0,6,4,0xFF 1363 01 02 03 02 04 02 05 02 06 03 ff i_char_offsets: defb 1,2,3,2,4,2,5,2,6,3,0xFF 136e 01 03 03 03 04 03 05 03 06 03 07 00 07 03 08 01 08 02 ff j_char_offsets: defb 1,3,3,3,4,3,5,3,6,3,7,0,7,3,8,1,8,2,0xFF 1381 00 00 01 00 02 00 02 03 03 00 03 02 04 00 04 01 05 00 05 02 06 00 06 03 ff k_char_offsets: defb 0,0,1,0,2,0,2,3,3,0,3,2,4,0,4,1,5,0,5,2,6,0,6,3,0xFF 139a 00 01 01 01 02 01 03 01 04 01 05 01 06 02 ff l_char_offsets: defb 0,1,1,1,2,1,3,1,4,1,5,1,6,2,0xFF 13a9 02 01 02 03 03 00 03 02 03 04 04 00 04 02 04 04 05 00 05 02 05 04 06 00 06 04 ff m_char_offsets: defb 2,1,2,3,3,0,3,2,3,4,4,0,4,2,4,4,5,0,5,2,5,4,6,0,6,4,0xFF 13c4 02 00 03 00 03 01 03 02 03 03 04 00 04 04 05 00 05 04 06 00 06 04 ff n_char_offsets: defb 2,0,3,0,3,1,3,2,3,3,4,0,4,4,5,0,5,4,6,0,6,4,0xFF 13db 02 01 02 02 02 03 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 ff o_char_offsets: defb 2,1,2,2,2,3,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,0xFF 13f4 02 00 02 01 02 02 02 03 03 00 03 04 04 00 04 04 05 00 05 04 06 00 06 01 06 02 06 03 07 00 08 00 ff p_char_offsets: defb 2,0,2,1,2,2,2,3,3,0,3,4,4,0,4,4,5,0,5,4,6,0,6,1,6,2,6,3,7,0,8,0,0xFF 1415 02 01 02 02 02 03 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 06 04 07 04 08 04 ff q_char_offsets: defb 2,1,2,2,2,3,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,6,4,7,4,8,4,0xFF 1436 02 00 03 00 03 01 03 02 03 03 04 00 04 04 05 00 06 00 ff r_char_offsets: defb 2,0,3,0,3,1,3,2,3,3,4,0,4,4,5,0,6,0,0xFF 1449 02 01 02 02 02 03 02 04 03 00 04 01 04 02 04 03 05 04 06 00 06 01 06 02 06 03 ff s_char_offsets: defb 2,1,2,2,2,3,2,4,3,0,4,1,4,2,4,3,5,4,6,0,6,1,6,2,6,3,0xFF 1464 00 01 01 01 02 00 02 01 02 02 02 03 03 01 04 01 05 01 06 02 06 03 ff t_char_offsets: defb 0,1,1,1,2,0,2,1,2,2,2,3,3,1,4,1,5,1,6,2,6,3,0xFF 147b 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 06 04 ff u_char_offsets: defb 2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,6,4,0xFF 1494 02 00 02 04 03 00 03 04 04 01 04 03 05 01 05 03 06 02 ff v_char_offsets: defb 2,0,2,4,3,0,3,4,4,1,4,3,5,1,5,3,6,2,0xFF 14a7 02 00 02 04 03 00 03 02 03 04 04 00 04 02 04 04 05 00 05 02 05 04 06 01 06 03 ff w_char_offsets: defb 2,0,2,4,3,0,3,2,3,4,4,0,4,2,4,4,5,0,5,2,5,4,6,1,6,3,0xFF 14c2 02 00 02 04 03 01 03 03 04 02 05 01 05 03 06 00 06 04 ff x_char_offsets: defb 2,0,2,4,3,1,3,3,4,2,5,1,5,3,6,0,6,4,0xFF 14d5 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 01 06 02 06 03 06 04 07 04 08 01 08 02 08 03 ff y_char_offsets: defb 2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,1,6,2,6,3,6,4,7,4,8,1,8,2,8,3,0xFF 14f6 02 00 02 01 02 02 02 03 02 04 03 03 04 02 05 01 06 00 06 01 06 02 06 03 06 04 ff z_char_offsets: defb 2,0,2,1,2,2,2,3,2,4,3,3,4,2,5,1,6,0,6,1,6,2,6,3,6,4,0xFF 1511 01 02 01 04 02 00 02 01 02 02 02 03 02 04 03 01 03 03 04 01 04 03 05 00 05 01 05 02 05 03 05 04 06 00 06 02 ff hash_char_offsets: defb 1,2,1,4,2,0,2,1,2,2,2,3,2,4,3,1,3,3,4,1,4,3,5,0,5,1,5,2,5,3,5,4,6,0,6,2,0xFF 1536 00 02 01 01 01 02 01 03 01 04 02 00 02 02 03 01 03 02 03 03 04 02 04 04 05 00 05 01 05 02 05 03 06 02 ff dollar_char_offsets: defb 0,2,1,1,1,2,1,3,1,4,2,0,2,2,3,1,3,2,3,3,4,2,4,4,5,0,5,1,5,2,5,3,6,2,0xFF 1559 00 04 01 00 01 01 01 03 02 00 02 01 02 03 03 02 04 01 04 03 04 04 05 01 05 03 05 04 06 00 ff percent_char_offsets: defb 0,4,1,0,1,1,1,3,2,0,2,1,2,3,3,2,4,1,4,3,4,4,5,1,5,3,5,4,6,0,0xFF 1578 00 01 00 02 01 00 01 03 02 00 03 01 04 00 04 02 04 04 05 00 05 03 06 01 06 02 06 04 ff ampersand_char_offsets: defb 0,1,0,2,1,0,1,3,2,0,3,1,4,0,4,2,4,4,5,0,5,3,6,1,6,2,6,4,0xFF 1595 00 03 01 02 ff apost_char_offsets: defb 0,3,1,2,0xFF 159a 00 03 01 02 02 02 03 02 04 02 05 02 06 03 ff L_paren_char_offsets: defb 0,3,1,2,2,2,3,2,4,2,5,2,6,3,0xFF 15a9 00 01 01 02 02 02 03 02 04 02 05 02 06 01 ff R_paren_char_offsets: defb 0,1,1,2,2,2,3,2,4,2,5,2,6,1,0xFF 15b8 00 01 00 03 01 02 02 01 02 03 ff asterix_char_offsets: defb 0,1,0,3,1,2,2,1,2,3,0xFF 15c3 00 01 00 02 00 03 01 00 01 04 02 00 02 03 02 04 03 00 03 02 03 04 04 00 04 02 04 04 05 00 05 03 05 04 06 01 06 02 ff at_char_offsets: defb 0,1,0,2,0,3,1,0,1,4,2,0,2,3,2,4,3,0,3,2,3,4,4,0,4,2,4,4,5,0,5,3,5,4,6,1,6,2,0xFF 15ea 07 00 07 01 07 02 07 03 07 04 ff under_char_offsets: defb 7,0,7,1,7,2,7,3,7,4,0xFF 15f5 00 02 01 03 ff accent_char_offsets: defb 0,2,1,3,0xFF 15fa 00 03 01 02 02 02 03 01 04 02 05 02 06 03 ff L_curly_char_offsets: defb 0,3,1,2,2,2,3,1,4,2,5,2,6,3,0xFF 1609 00 01 01 02 02 02 03 03 04 02 05 02 06 01 ff R_curly_char_offsets: defb 0,1,1,2,2,2,3,3,4,2,5,2,6,1,0xFF 1618 00 02 01 02 02 02 04 02 05 02 06 02 ff pipe_char_offsets: defb 0,2,1,2,2,2,4,2,5,2,6,2,0xFF 1625 02 01 03 00 03 02 03 04 04 03 ff tilde_char_offsets: defb 2,1,3,0,3,2,3,4,4,3,0xFF 1630 00 02 01 01 01 03 03 00 03 04 ff carat_char_offsets: defb 0,2,1,1,1,3,3,0,3,4,0xFF 163b 00 00 00 01 00 02 00 03 00 04 01 00 01 01 01 02 01 03 01 04 02 00 02 01 02 02 02 03 02 04 03 00 03 01 03 02 03 03 03 04 block_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,0,1,1,1,2,1,3,1,4,2,0,2,1,2,2,2,3,2,4,3,0,3,1,3,2,3,3,3,4 1663 04 00 04 01 04 02 04 03 04 04 05 00 05 01 05 02 05 03 05 04 06 00 06 01 06 02 06 03 06 04 07 00 07 01 07 02 07 03 07 04 defb 4,0,4,1,4,2,4,3,4,4,5,0,5,1,5,2,5,3,5,4,6,0,6,1,6,2,6,3,6,4,7,0,7,1,7,2,7,3,7,4 168b 08 00 08 01 08 02 08 03 08 04 ff defb 8,0,8,1,8,2,8,3,8,4,0xFF 1696 00 00 00 01 00 02 00 03 00 04 01 00 01 04 02 00 02 04 03 00 03 04 04 00 04 04 05 00 05 04 06 00 06 01 06 02 06 03 06 04 ff square_char_offsets: defb 0,0,0,1,0,2,0,3,0,4,1,0,1,4,2,0,2,4,3,0,3,4,4,0,4,4,5,0,5,4,6,0,6,1,6,2,6,3,6,4,0xFF 16bf 16bf 80 40 20 10 08 04 02 01 dot_table: defb 128,64,32,16,8,4,2,1 16c7 16c7 0x00... tiny_basic: ds 2043,0 ;put Tiny BASIC binary code here 1ec2 1ec2 org 2000h ;start of RAM in system with 8K ROM 2000 ;Variables in RAM 2000 2000 00 dot_count: defb 0 2001 00 test_char: defb 0 2002 00 test_line: defb 0 2003 00 test_pos: defb 0 2004 00 char: defb 0 2005 00 char_line: defb 0 2006 00 char_pos: defb 0 2007 00 counter: defb 0 2008 00 00 anchor_dot_x: defw 0 200a 00 anchor_dot_y: defb 0 200b 00 00 dot_x: defw 0 200d 00 dot_y: defb 0 200e 00 clear_flag: defb 0 200f 00 00 current_location: defw 0 2011 00 line_count: defb 0 2012 00 byte_count: defb 0 2013 00 00 value_pointer: defw 0 2015 00 00 current_value: defw 0 2017 00 00 string_pointer: defw 0 2019 00 00 buffer_pointer: defw 0 201b 00 get_line_char: defb 0 201c 00 00 help_table_pointer: defw 0 201e 00 00 help_string_pointer: defw 0 2020 00 shift_down: db 0 2021 00 ctrl_down: db 0 2022 00 00 load_length: defw 0 2024 00 00 load_address: defw 0 2026 00 00 bdump_address: defw 0 2028 00 00 bdump_length: defw 0 202a 00 timer_tick: defb 0 202b 00 blink_flag: defb 0 202c 00 capslock: defb 0 202d 0x00... buffer: ds 128,0 ;buffer in RAM 20ad 0x00... line_offset_table: ds 480,0 228d 228d 228d 228d # End of file standalone-ROM-5.asm 228d