Converted monitor to asz80 to allow a more modular design

This commit is contained in:
Dreaded_X 2021-06-19 16:54:09 +02:00
parent ae998ec3dc
commit 789b07d893
4 changed files with 889 additions and 11 deletions

View File

@ -1,19 +1,67 @@
BUILDDIR=.build
_BIN= rom_monitor.bin ram_monitor.bin MONITOR.COM
BIN = $(patsubst %,$(BUILDDIR)/%,$(_BIN))
# BUILDDIR=.build
# _BIN= rom_monitor.bin ram_monitor.bin MONITOR.COM
# BIN = $(patsubst %,$(BUILDDIR)/%,$(_BIN))
#
# .PHONY: all clean
#
# all: $(BUILDDIR) $(BIN)
#
# $(BUILDDIR)/%.bin: src/%.z80 | $(BUILDDIR)
# @zasm -w -i $< -o $@
#
# $(BUILDDIR)/%.COM: src/%.z80 | $(BUILDDIR)
# @zasm -w -i $< -o $@
#
# $(BUILDDIR):
# @mkdir $(BUILDDIR)
#
# clean:
# @rm -df $(BUILDDIR)/*.bin $(BUILDDIR)/*.COM $(BUILDDIR)/*.lst .build
AS = sdasz80
LD = sdldz80
OBJCOPY = sdobjcopy
BUILD = .build
TARGET_ROM = rom_monitor
TARGET_COM = MONITOR
ASFLAGS = -plosff
SRC_ROM = \
src/monitor.s \
src/rom.s
SRC_COM = \
src/monitor.s \
src/cpm.s
OBJ_ROM = $(addprefix $(BUILD)/, $(notdir $(SRC_ROM:.s=.rel)))
OBJ_COM = $(addprefix $(BUILD)/, $(notdir $(SRC_COM:.s=.rel)))
vpath %.s $(sort $(dir $(SRC_ROM)))
vpath %.s $(sort $(dir $(SRC_COM)))
.PHONY: all clean
all: $(BUILDDIR) $(BIN)
all: $(BUILD) $(BUILD)/$(TARGET_ROM).bin $(BUILD)/$(TARGET_COM).COM
$(BUILDDIR)/%.bin: src/%.z80 | $(BUILDDIR)
@zasm -w -i $< -o $@
$(BUILD)/%.rel: %.s Makefile | $(BUILD)
$(AS) $(ASFLAGS) $@ $<
$(BUILDDIR)/%.COM: src/%.z80 | $(BUILDDIR)
@zasm -w -i $< -o $@
$(BUILD)/$(TARGET_ROM).ihx: $(OBJ_ROM)
$(LD) -im1 $@ $(OBJ_ROM) -b BOOT=0x0000
$(BUILDDIR):
@mkdir $(BUILDDIR)
$(BUILD)/$(TARGET_COM).ihx: $(OBJ_COM)
$(LD) -im1 $@ $(OBJ_COM) -b BOOT=0x0100 -b MAIN=0xE200
%.bin: %.ihx
$(OBJCOPY) -I ihex -O binary $< $@
%.COM: %.ihx
$(OBJCOPY) -I ihex -O binary $< $@
$(BUILD):
mkdir $@
clean:
@rm -df $(BUILDDIR)/*.bin $(BUILDDIR)/*.COM $(BUILDDIR)/*.lst .build
rm -fr $(BUILD)

25
src/cpm.s Normal file
View File

@ -0,0 +1,25 @@
bios .equ 0x0000
main .equ 0xE200
.globl monitor_start
.globl s_MAIN
.globl end
.area BOOT
ld hl, #origin ; Start of code to transfer
ld bc, #end-main+1 ; Size of code transfer
ld de, #s_MAIN ; Target of transfer
ldir ; Z80 transfer instruction
jp monitor_start
origin:
.area MAIN
system_jump:
jp bios
system_string:
.str /system\0/
.area PARSE_TABLE
.dw system_string, system_jump

756
src/monitor.s Normal file
View File

@ -0,0 +1,756 @@
; Variables
current_location .equ 0x1000
line_count .equ 0x1002
byte_count .equ 0x1003
value_pointer .equ 0x1004
current_value .equ 0x1006
; Buffer up to stack
buffer .equ 0x1008
.area BOOT
.area MAIN
; Puts a single char (byte value) on serial output
; Call with char to send in A register. Uses B register
write_char:
ld b, a
write_char_loop:
in a, (0x03) ; Check if OK to send
and #0x01
jp z, write_char_loop
ld a, b
out (0x02), a ; Send the char
ret
; Subroutine to write a zero-terminated string to serial output
; Pass address of string in HL register
; No error checking
write_string::
in a, (0x03) ; Check if OK to send
and #0x01
jp z, write_string
ld a, (hl) ; Get char from string
and a ; Check if 0
ret z ; Yes, finished
out (0x02), a ; No, write char to output
inc hl ; Next char in string
jp write_string
; Binary loader. Receive a binary file, place in memory.
; Address of load passed in HL, length of load (= file length) in BC
bload:
in a, (0x1F) ; Check if char is available
and #0x01
jp z,bload
in a, (0x1E) ; Read char
ld (hl), a ; Write char to memory
inc hl
dec bc ; Decrement counter
ld a, b ; Need to test BC this way because
or c ; dec rp instruction does not change flags
jp nz, bload
ret
; Binary dump to port. Send a stream of binary data from memory to serial output
; Address of dump passed in HL, length of dump in BC
bdump:
in a, (0x03) ; Check if OK to send
and #0x01
jp z, bdump
ld a, (hl) ; Load from memory
out (0x02), a
inc hl
dec bc ; Decrement counter
ld a, b ; Need to test BC this way because
or c ; dec rp instruction does not change flags
jp nz, bdump
ret
; Subroutine to get a string from serial input, place in buffer.
; Buffer address passed in HL reg.
; Uses A,BC,DE,HL registers (including calls to other subroutines).
; Line entry ends by hitting return key. Return char not included in string (replaced by zero).
; Backspace editing OK. No error checking.
get_line:
ld c, #0x00 ; Line position
ld a, h ; Put original buffer address in de
ld d, a ; after this don't need to preserve hl
ld a, l ; subroutines called don't use de
ld e, a
get_line_next_char:
in a, (0x1F) ; Check if char is available
and #0x01
jp z, get_line_next_char
in a, (0x1E) ; Read char
cp #0x0D ; Check if return
ret z
cp #0x7F ; Check if backspace (VT102 keys)
jp z, get_line_backspace
cp #0x08 ; Check if backspace (ANSI keys)
jp z, get_line_backspace
call write_char ; Display the char
ld (de), a ; Store char in buffer
inc de
inc c
ld a, #0x00 ; leaves a zero-terminated string in buffer
ld (de), a
jp get_line_next_char
get_line_backspace:
ld a, c ; Check current position in line
cp #0x00 ; At beginning of line?
jp z, get_line_next_char ; yes, ignore backspace, get next char
dec de ; No, erase char from buffer
dec c ; Back up one
ld a, #0x00 ; Put a zero in buffer where the last char was
ld (de), a
ld hl, #erase_char_string ; ANSI sequence to delete one char from line
call write_string ; Transmits sequence to backspace and erase char
jp get_line_next_char
; Creates a two-char hex string from the byte value passed in register A
; Location to place string passed in HL
; String is zero-terminated, stored in 3 locations starting at HL
; Also uses registers b,d, and e
byte_to_hex_string:
ld b, a ; Store original byte
srl a ; Shift right 4 times, putting
srl a ; high nybble in low-nybble spot
srl a ; and zeros in high-nybble spot
srl a
ld d, #0x00 ; Prepare for 16-bit addition
ld e, a ; de contains offset
push hl ; Temporarily store string target address
ld hl, #hex_char_table ; Use char table to get high-nybble character
add hl, de ; Add offset to start of table
ld a, (hl) ; Get char
pop hl ; Get string target address
ld (hl), a ; Store first char of string
inc hl ; Point to next string target address
ld a, b ; Get original byte back from reg b
and #0x0F ; Mask off high-nybble
ld e, a ; d still has 000h, now de has offset
push hl ; Temp store string target address
ld hl, #hex_char_table ; Start of table
add hl, de ; Add offset
ld a, (hl) ; Get char
pop hl ; Get string target address
ld (hl), a ; Store second char of string
inc hl ; Point to third location
ld a, #0x00 ; Zero to terminate string
ld (hl), a ; Store the zero
ret ; Done
; Converts a single ASCII hex char to a nybble value
; Pass char in reg A. Letter numerals must be upper case.
; Return nybble value in low-order reg A with zeros in high-order nybble if no error.
; Return 0ffh in reg A if error (char not a valid hex numeral).
; Also uses b, c, and hl registers.
hex_char_to_nybble:
ld hl, #hex_char_table
ld b, #0x0f ; No. of valid characters in table - 1.
ld c, #0x00 ; Will be nybble value
hex_to_nybble_loop:
cp (hl) ; Character match here?
jp z, hex_to_nybble_ok ; match found, exit
dec b ; No match, check if at end of table
jp m, hex_to_nybble_err ; Table limit exceded, exit with error
inc c ; Still inside table, continue search
inc hl
jp hex_to_nybble_loop
hex_to_nybble_ok:
ld a, c ; Put nybble value in a
ret
hex_to_nybble_err:
ld a, #0xFF ; Error value
ret
; Converts a hex character pair to a byte value
; Called with location of high-order char in HL
; If no error carry flag clear, returns with byte value in register A, and
; HL pointing to next mem location after char pair.
; If error (non-hex char) carry flag set, HL pointing to invalid char
hex_to_byte:
ld a, (hl) ; Location of character pair
push hl ; Store hl (hex_char_to_nybble uses it)
call hex_char_to_nybble
pop hl ; Returns with nybble value in a reg, or 0ffh if error
cp #0xFF ; Non-hex character?
jp z, hex_to_byte_err ; Yes, exit with error
sla a ; No, move low order nybble to high side
sla a
sla a
sla a
ld d, a ; Store high-nybble
inc hl ; Get next character of the pair
ld a, (hl)
push hl ; Store hl
call hex_char_to_nybble
pop hl
cp #0xFF ; Non-hex character?
jp z, hex_to_byte_err ; Yes, exit with error
or d ; No, combine with high-nybble
inc hl ; Point to next memory location after char pair
scf
ccf ; No-error exit (carry = 0)
ret
hex_to_byte_err:
scf ; Error, carry flag set
ret
hex_char_table:
.ascii /0123456789ABCDEF/ ; ASCII hex table
; Subroutine to get a two-byte address from serial input.
; Returns with address value in HL
; Uses locations in RAM for buffer and variables
address_entry:
ld hl, #buffer ; Location for entered string
call get_line ; Returns with address string in buffer
ld hl, #buffer ; Location of stored address entry string
call hex_to_byte ; Will get high-order byte first
jp c, address_entry_error ; If error, jump
ld (current_location+1), a ; Store high-order byte, little-endian
ld hl, #buffer+2 ; Point to low-order hex char pair
call hex_to_byte ; Get low-order byte
jp c, address_entry_error ; Jump if error
ld (current_location), a ; Store low-order byte in lower memory
ld hl, (current_location) ; Put memory address in hl
ret
address_entry_error:
ld hl, #address_error_msg
call write_string
jp address_entry
; Subroutine to get a decimal string, return a word value
; Calls decimal_string_to_word subroutine
decimal_entry:
ld hl, #buffer
call get_line ; Returns with DE pointing to terminating zero
ld hl, #buffer
call decimal_string_to_word
ret nc ; No error, return with word in hl
ld hl, #decimal_error_msg ; Error, try again
call write_string
jp decimal_entry
; Subroutine to convert a decimal string to a word value
; Call with address of string in HL, pointer to end of string in DE
; Carry flag set if error (non-decimal char)
; Carry flag clear, word value in HL if no error.
decimal_string_to_word:
ld b, d
ld c, e ; Use BC as string pointer
ld (current_location), hl ; Store addr. of start of buffer in RAM word variable
ld hl, #0x00 ; Starting value zero
ld (current_value), hl
ld hl, #decimal_place_value ; Pointer to values
ld (value_pointer), hl
decimal_next_char:
dec bc ; Next char in string (moving right to left)
ld hl,(current_location) ; Check if at end of decimal string
scf ; Get ready to subtract de from buffer addr.
ccf ; Set carry to zero (clear)
sbc hl, bc ; Keep going if bc > or = hl (buffer address)
jp c, decimal_continue ; Borrow means bc > hl
jp z, decimal_continue ; z means bc = hl
ld hl, (current_value) ; Return if de < buffer address (no borrow)
scf ; Get value back from RAM variable
ccf
ret ; Return with carry clear, value in hl
decimal_continue:
ld a, (bc) ; Next char in string (right to left)
sub #0x30 ; ASCII value of zero char
jp m, decimal_error ; Error if char value less than 030h
cp #0x0A ; Error if byte value > or = 10 decimal
jp p, decimal_error ; a reg now has value of decimal numeral
ld hl, (value_pointer) ; Get value to add an put in de
ld e, (hl) ; Little-endian (low byte in low memory)
inc hl
ld d, (hl)
inc hl ; hl now points to next value
ld (value_pointer), hl
ld hl, (current_value) ; Get back current value
decimal_add:
dec a ; Add loop to increase total value
jp m, decimal_add_done ; End of multiplication
add hl, de
jp decimal_add
decimal_add_done:
ld (current_value), hl
jp decimal_next_char
decimal_error:
scf
ret
jp decimal_add
decimal_place_value:
.dw 1,10,100,1000,10000
; Memory dump
; Displays a 256-byte block of memory in 16-byte rows.
; Called with address of start of block in HL
memory_dump:
ld (current_location), hl ; Store address of block to be displayed
ld a, #0x00
ld (byte_count), a ; Initialize byte count
ld (line_count), a ; Initialize line count
jp dump_new_line
dump_next_byte:
ld hl, (current_location) ; Get byte address from storage,
ld a, (hl) ; Get byte to be converted to string
inc hl ; Increment address and
ld (current_location), hl ; Store back
ld hl, #buffer ; Location to store string
call byte_to_hex_string ; Convert
ld hl, #buffer ; Display string
call write_string
ld a, (byte_count) ; Next byte
inc a
jp z, dump_done ; Stop when 256 bytes displayed
ld (byte_count),a ; Not finished yet, store
ld a, (line_count) ; End of line (16 characters)?
cp #0x0f ; Yes, start new line
jp z, dump_new_line
inc a ; No, increment line count
ld (line_count), a
ld a, #0x20 ; Print space
call write_char
jp dump_next_byte ; Continue
dump_new_line:
ld a, #0x00 ; Reset line count to zero
ld (line_count), a
call write_newline
ld hl, (current_location) ; Location of start of line
ld a, h ; High byte of address
ld hl, #buffer
call byte_to_hex_string ; Convert
ld hl, #buffer
call write_string ; Write high byte
ld hl, (current_location)
ld a, l ; Low byte of address
ld hl, #buffer
call byte_to_hex_string ; Convert
ld hl, #buffer
call write_string ; Write low byte
ld a, #0x20 ; Space
call write_char
jp dump_next_byte ; Now write 16 bytes
dump_done:
ld a, #0x00
ld hl, #buffer
ld (hl), a ; Clear buffer of last string
call write_newline
ret
;
;Memory load
;Loads RAM memory with bytes entered as hex characters
;Called with address to start loading in HL
;Displays entered data in 16-byte rows.
memory_load:
ld (current_location), hl
ld hl, #data_entry_msg
call write_string
jp load_new_line
load_next_char:
call get_char
cp #0x0D ; Return?
jp z, load_done ; Yes, quit
ld (buffer), a
call get_char
cp #0x0D ; Return?
jp z, load_done ; Yes, quit
ld (buffer+1), a
ld hl, #buffer
call hex_to_byte
jp c, load_data_entry_error ; Non-hex character
ld hl, (current_location) ; Get byte address from storage,
ld (hl), a ; Store byte
inc hl ; Increment address and
ld (current_location), hl ; Store back
ld a, (buffer)
call write_char
ld a, (buffer+1)
call write_char
ld a, (line_count) ; End of line (16 characters)?
cp #0x0F ; Yes, start new line
jp z, load_new_line
inc a ; No, increment line count
ld (line_count), a
ld a, #0x20 ; Print space
call write_char
jp load_next_char ; Continue
load_new_line:
ld a, #0x00 ; Reset line count to zero
ld (line_count), a
call write_newline
jp load_next_char ; Continue
load_data_entry_error:
call write_newline
ld hl, #data_error_msg
call write_string
ret
load_done:
call write_newline
ret
; Get one ASCII character from the serial port.
; Returns with char in A reg. No error checking.
get_char:
in a, (0x1F) ; Get status
and #0x01 ; Check RxRDY bit
jp z, get_char ; Not ready, loop
in a, (0x1E) ; Get char
ret
; Subroutine to start a new line
write_newline:
ld a, #0x0D ; ASCII carriage return character
call write_char
ld a, #0x0A ; New line (line feed) character
call write_char
ret
; Subroutine to read one disk sector (128 bytes)
; Address to place data passed in HL
; LBA bits 0 to 7 passed in C, bits 8 to 15 passed in B
; LBA bits 16 to 23 passed in E
disk_read::
ld a, c
out (0x0B), a ; lba bits 0 - 7
ld a, b
out (0x0C), a ; lba bits 8 - 15
ld a, e
out (0x0D), a ; lba bits 16 - 23
ld a, #0x20 ; Read sector command
out (0x0F), a
rd_wait_for_DRQ_set:
in a, (0x0F) ; Read status
and #0x08 ; DRQ bit
jp z, rd_wait_for_DRQ_set ; Loop until bit set
read_loop:
in a, (0x08) ; Get data
ld (hl), a
inc hl
in a, (0x0f) ; Check status
and #0x08 ; DRQ bit
jp nz, read_loop ; Loop until cleared
ret
; Subroutine to write one disk sector (128 bytes)
; Address of data to write to disk passed in HL
; LBA bits 0 to 7 passed in C, bits 8 to 15 passed in B
; LBA bits 16 to 23 passed in E
disk_write:
ld a, c
out (0x0b), a ; lba bits 0 - 7
ld a, b
out (0x0c), a ; lba bits 8 - 15
ld a, e
out (0x0d), a ; lba bits 16 - 23
ld a, #0x30 ; Write sector command
out (0x0f), a
wr_wait_for_DRQ_set:
in a, (0x0f) ; Read status
and #0x08 ; DRQ bit
jp z, wr_wait_for_DRQ_set ; Loop until bit set
write_loop:
ld a, (hl)
out (0x08), a ; Write data
inc hl
in a, (0x0f) ; Read status
and #0x08 ; Check DRQ bit
jp nz, write_loop ;write until bit cleared
ret
; Strings used in subroutines
length_entry_string:
.str /Enter length of file to load (decimal): \0/
dump_entry_string:
.str /Enter no. of bytes to dump (decimal): \0/
LBA_entry_string:
.str /Enter LBA (decimal, 0 to 65535): \0/
erase_char_string: ;ANSI sequence for backspace, erase to end of line.
.db #0x08
.db #0x1B
.str /[K\0/
address_entry_msg:
.str /Enter 4-digit hex address (use upper-case A through F): \0/
address_error_msg:
.str /\r\nError: invalid hex character, try again: \0/
data_entry_msg:
.str /Enter hex bytes, hit return when finished.\r\n\0/
data_error_msg:
.str /Error: invalid hex byte.\r\n\0/
decimal_error_msg:
.str /\r\nError: invalid decimal number, try again: \0/
; Simple monitor program for CPUville Z80 computer with serial interface.
monitor_start::
call write_newline ; Routine program return here to avoid re-initialization of port
ld a, #0x03e ; Cursor symbol
call write_char
ld hl, #buffer
call get_line ; Get monitor input string (command)
call write_newline
call parse ; Interprets command, returns with address to jump to in HL
jp (hl)
; Parses an input line stored in buffer for available commands as described in parse table.
; Returns with address of jump to action for the command in HL
parse:
ld bc, #parse_table ; bc is pointer to parse_table
parse_start:
ld a, (bc) ; Get pointer to match string from parse table
ld e, a
inc bc
ld a, (bc)
ld d, a ; de will is pointer to strings for matching
ld a, (de) ; Get first char from match string
or #0x00 ; Zero?
jp z, parser_exit ; Yes, exit no_match
ld hl, #buffer ; No, parse input string
match_loop:
cp (hl) ; Compare buffer char with match string char
jp nz, no_match ; No match, go to next match string
or #0x00 ; End of strings (zero)?
jp z, parser_exit ; Yes, matching string found
inc de ; Match so far, point to next char in match string
ld a, (de) ; Get next character from match string
inc hl ; And point to next char in input string
jp match_loop ; Check for match
no_match:
inc bc ; Skip over jump target to
inc bc
inc bc ; Get address of next matching string
jp parse_start
parser_exit:
inc bc ; Skip to address of jump for match
ld a, (bc)
ld l, a
inc bc
ld a,(bc)
ld h, a ; Returns with jump address in hl
ret
; Actions to be taken on match
;
; Memory dump program
; Input 4-digit hexadecimal address
; Calls memory_dump subroutine
dump_jump:
ld hl, #dump_message ; Display greeting
call write_string
ld hl, #address_entry_msg ; Get ready to get address
call write_string
call address_entry ; Returns with address in HL
call write_newline
call memory_dump
jp monitor_start
; Hex loader, displays formatted input
load_jump:
ld hl, #load_message ; Display greeting
call write_string ; Get address to load
ld hl, #address_entry_msg ; Get ready to get address
call write_string
call address_entry
call write_newline
call memory_load
jp monitor_start
; Jump and run do the same thing: get an address and jump to it.
run_jump:
ld hl, #run_message ; Display greeting
call write_string
ld hl, #address_entry_msg ; Get ready to get address
call write_string
call address_entry
jp (hl)
; Help and ? do the same thing, display the available commands
help_jump:
ld hl, #help_message
call write_string
ld bc, #parse_table ; Table with pointers to command strings
help_loop:
ld a, (bc) ; Displays the strings for matching commands,
ld l, a ; Getting the string addresses from the
inc bc ; Parse table
ld a, (bc) ; Pass address of string to hl through a reg
ld h, a
ld a, (hl) ; hl now points to start of match string
or #0x00 ; Exit if no_match string
jp z, help_done
push bc ; Write_char uses b register
ld a, #0x20 ; Space char
call write_char
pop bc
call write_string ; Writes match string
inc bc ; Pass over jump address in table
inc bc
inc bc
jp help_loop
help_done:
jp monitor_start
; Binary file load. Need both address to load and length of file
bload_jump:
ld hl, #bload_message
call write_string
ld hl, #address_entry_msg
call write_string
call address_entry
call write_newline
push hl
ld hl, #length_entry_string
call write_string
call decimal_entry
ld b, h
ld c, l
ld hl, #bload_ready_message
call write_string
pop hl
call bload
jp monitor_start
; Binary memory dump. Need address of start of dump and no. bytes
bdump_jump:
ld hl, #bdump_message
call write_string
ld hl, #address_entry_msg
call write_string
call address_entry
call write_newline
push hl
ld hl, #dump_entry_string
call write_string
call decimal_entry
ld b, h
ld c, l
ld hl, #bdump_ready_message
call write_string
call get_char
pop hl
call bdump
jp monitor_start
; Disk read. Need memory address to place data, LBA of sector to read
diskrd_jump:
ld hl, #diskrd_message
call write_string
ld hl, #address_entry_msg
call write_string
call address_entry
call write_newline
push hl
ld hl, #LBA_entry_string
call write_string
call decimal_entry
ld b, h
ld c, l
ld e, #0x00
pop hl
call disk_read
jp monitor_start
diskwr_jump:
ld hl, #diskwr_message
call write_string
ld hl, #address_entry_msg
call write_string
call address_entry
call write_newline
push hl
ld hl, #LBA_entry_string
call write_string
call decimal_entry
ld b, h
ld c, l
ld e, #0x00
pop hl
call disk_write
jp monitor_start
; Prints message for no match to entered command
no_match_jump:
ld hl, #no_match_message
call write_string
ld hl, #buffer
call write_string
jp monitor_start
; Monitor data structures:
no_match_message:
.str /? \0/
help_message:
.str /Commands implemented:\r\n\0/
dump_message:
.str /Displays a 256-byte block of memory.\r\n\0/
load_message:
.str /Enter hex bytes starting at memory location.\r\n\0/
run_message:
.str /Will jump to (execute) program at address entered.\r\n\0/
bload_message:
.str /Loads a binary file into memory.\r\n\0/
bload_ready_message:
.str /\r\nReady to receive, start transfer.\0/
bdump_message:
.str /Dumps binary data from memory to serial port.\r\n\0/
bdump_ready_message:
.str /\r\nReady to send, hit any key to start.\0/
diskrd_message:
.str /Reads one sector from disk to memory.\r\n\0/
diskwr_message:
.str /Writes one sector from memory to disk.\r\n\0/
; Strings for matching:
dump_string:
.str /dump\0/
load_string:
.str /load\0/
jump_string:
.str /jump\0/
run_string:
.str /run\0/
question_string:
.str /?\0/
help_string:
.str /help\0/
bload_string:
.str /bload\0/
bdump_string:
.str /bdump\0/
diskrd_string:
.str /diskrd\0/
diskwr_string:
.str /diskwr\0/
no_match_string:
.dw #0x00
;Table for matching strings to jumps
.area PARSE_TABLE
parse_table:
.dw dump_string, dump_jump
.dw load_string, load_jump
.dw jump_string, run_jump
.dw run_string, run_jump
.dw question_string, help_jump
.dw help_string, help_jump
.dw bload_string, bload_jump
.dw bdump_string, bdump_jump
.dw diskrd_string, diskrd_jump
.dw diskwr_string, diskwr_jump
.area PARSE_TABLE_END
.dw no_match_string, no_match_jump
end::

49
src/rom.s Normal file
View File

@ -0,0 +1,49 @@
stack .equ 0x10ff
bootloader .equ 0x1100
.globl disk_read
.globl write_string
.globl monitor_start
.area BOOT
start:
ld sp, #stack
call initialize
ld hl, #monitor_message
call write_string
jp monitor_start
monitor_message:
.db #0x1B
.str /[2J/
.db #0x1B
.str /[H\r\nROM Ver. 9\r\n\0/
; Clear out bufferend input
initialize:
initialize_loop_1:
in a, (0x1E) ; Read char from keyboard
in a, (0x1F) ; Check if there is another char
and #0x01
jp nz, initialize_loop_1
; Wait for GPU be ready
initialize_loop_2:
in a, (0x03) ; If GPU is not ready value is 0xFF
and #0x02
jp nz, initialize_loop_2
ret
.area MAIN
boot_jump:
ld hl, #bootloader ; Set destination
ld bc, #0x0000 ; Set lba of bootloader
ld e, #0x00
call disk_read
jp bootloader
boot_string:
.str /boot\0/
.area PARSE_TABLE
.dw boot_string, boot_jump