You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
872 lines
16 KiB
872 lines
16 KiB
2 years ago
|
.include "instr.inc"
|
||
|
.text
|
||
|
|
||
|
mem_e000:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_e002:
|
||
|
.fill 0x0efe
|
||
|
|
||
|
mem_ef00:
|
||
|
.fill 0xb0
|
||
|
|
||
|
mem_efb0:
|
||
|
.fill 0x30
|
||
|
|
||
|
mem_efe0:
|
||
|
.fill 0x20
|
||
|
|
||
|
.global _start
|
||
|
_start:
|
||
|
ld_sp stack
|
||
|
|
||
|
# Set up the entrypoint for the breakpoint instruction
|
||
|
ld_r0 entry
|
||
|
ld_r1 0x98 # 'call'
|
||
|
strb_r1_r0
|
||
|
inc_r0
|
||
|
ld_r1 main
|
||
|
str_r1_r0
|
||
|
|
||
|
# Explain the debugger
|
||
|
ld_r2 str_intro
|
||
|
call PrintStr
|
||
|
|
||
|
auth_user:
|
||
|
# Gather the username
|
||
|
ld_r2 str_prompt_user
|
||
|
call PrintStr
|
||
|
ld_r3 0x10
|
||
|
ld_r2 mem_input_user
|
||
|
call ReadStr
|
||
|
|
||
|
ld_r2 database
|
||
|
auth_user_loop:
|
||
|
# Check if we've reached the end of the database
|
||
|
ldrb_r0_r2
|
||
|
cp_r0 0
|
||
|
jp_eq error_incorrect_user
|
||
|
|
||
|
# Check if the username matches the current entry
|
||
|
ld_r3 mem_input_user
|
||
|
push_r2
|
||
|
call StrCmp
|
||
|
pop_r2
|
||
|
cp_r0 0
|
||
|
jp_eq auth_pass
|
||
|
|
||
|
# Next entry
|
||
|
add_r2 0x50
|
||
|
jp auth_user_loop
|
||
|
|
||
|
auth_pass:
|
||
|
# Grab the password field
|
||
|
add_r2 0x10
|
||
|
push_r2
|
||
|
call delay_input
|
||
|
|
||
|
# Gather the password
|
||
|
ld_r2 str_prompt_pass
|
||
|
call PrintStr
|
||
|
ld_r3 0x30
|
||
|
ld_r2 mem_input_pass
|
||
|
call ReadStr
|
||
|
call delay_input
|
||
|
|
||
|
# Load the ENCTABLE.BIN file
|
||
|
ld_r0 1
|
||
|
ld_r1 0xc000
|
||
|
copr_readblk
|
||
|
|
||
|
# r2 = encoded pass
|
||
|
# r3 = input pass
|
||
|
pop_r2
|
||
|
ld_r3 mem_input_pass
|
||
|
auth_pass_loop:
|
||
|
push_r3
|
||
|
|
||
|
# b = *(0xc000 + *input)
|
||
|
ld_r1 0xc000
|
||
|
ldrb_r0_r3
|
||
|
add_r1_r0
|
||
|
ld_r3 0
|
||
|
ldrb_r0_r1
|
||
|
add_r3_r0
|
||
|
|
||
|
# b += *(0xc100 + *input)
|
||
|
add_r1 0x100
|
||
|
ldrb_r0_r1
|
||
|
add_r3_r0
|
||
|
|
||
|
# b += *(0xc200 + *input)
|
||
|
add_r1 0x100
|
||
|
ldrb_r0_r1
|
||
|
add_r3_r0
|
||
|
|
||
|
# b += *(0xc300 + *input)
|
||
|
add_r1 0x100
|
||
|
ldrb_r0_r1
|
||
|
add_r3_r0
|
||
|
|
||
|
# b &= 0xff
|
||
|
ld_r0_r3
|
||
|
and_r0 0xff
|
||
|
|
||
|
ldrb_r1_r2
|
||
|
cp_r0_r1
|
||
|
jp_ne error_incorrect_pass
|
||
|
pop_r3
|
||
|
|
||
|
call rotate_enctable
|
||
|
inc_r2
|
||
|
inc_r3
|
||
|
ldrb_r0_r2
|
||
|
cp_r0 0
|
||
|
jp_eq auth_success
|
||
|
jp auth_pass_loop
|
||
|
|
||
|
auth_success:
|
||
|
ld_r2 str_login_success
|
||
|
call PrintStr
|
||
|
|
||
|
# Execute the breakpoint, jump to main
|
||
|
brk
|
||
|
|
||
|
# If breakpoint returns here, we've ran out of stack
|
||
|
ld_r2 str_dry_stack
|
||
|
call PrintStr
|
||
|
copr_halt
|
||
|
die:
|
||
|
jp die
|
||
|
|
||
|
error_incorrect_user:
|
||
|
call delay_input
|
||
|
ld_r2 str_incorrect_user
|
||
|
call PrintStr
|
||
|
jp auth_user
|
||
|
|
||
|
error_incorrect_pass:
|
||
|
ld_r2 str_incorrect_pass
|
||
|
call PrintStr
|
||
|
jp auth_user
|
||
|
|
||
|
rotate_enctable:
|
||
|
ldrb_r0 0xc000
|
||
|
strb_r0 rotate_enctable_temp + 0
|
||
|
ldrb_r0 0xc100
|
||
|
strb_r0 rotate_enctable_temp + 1
|
||
|
ldrb_r0 0xc200
|
||
|
strb_r0 rotate_enctable_temp + 2
|
||
|
ldrb_r0 0xc300
|
||
|
strb_r0 rotate_enctable_temp + 3
|
||
|
ld_r1 0xc000
|
||
|
|
||
|
rotate_enctable_loop:
|
||
|
inc_r1
|
||
|
ldrb_r0_r1
|
||
|
dec_r1
|
||
|
strb_r0_r1
|
||
|
inc_r1
|
||
|
cp_r1 0xc3ff
|
||
|
jp_ne rotate_enctable_loop
|
||
|
|
||
|
ldrb_r0 rotate_enctable_temp + 0
|
||
|
strb_r0 0xc0ff
|
||
|
ldrb_r0 rotate_enctable_temp + 1
|
||
|
strb_r0 0xc1ff
|
||
|
ldrb_r0 rotate_enctable_temp + 2
|
||
|
strb_r0 0xc2ff
|
||
|
ldrb_r0 rotate_enctable_temp + 3
|
||
|
strb_r0 0xc3ff
|
||
|
ret
|
||
|
|
||
|
rotate_enctable_temp:
|
||
|
.fill 4
|
||
|
|
||
|
delay_input:
|
||
|
push_r2
|
||
|
ld_r2 str_please_wait
|
||
|
call PrintStr
|
||
|
pop_r2
|
||
|
|
||
|
ld_r0 0x3fff
|
||
|
delay_input_loop:
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
nop
|
||
|
dec_r0
|
||
|
cp_r0 0
|
||
|
jp_ne delay_input_loop
|
||
|
ret
|
||
|
|
||
|
database:
|
||
|
.fill 0x00 - (. - database)
|
||
|
.ascii "ax.arwen\0"
|
||
|
.fill 0x10 - (. - database)
|
||
|
.byte 0xc6, 0x44, 0x99, 0xe3, 0xe9, 0x19, 0x0d, 0x07, 0x0d, 0x12, 0x79
|
||
|
|
||
|
.fill 0x50 - (. - database)
|
||
|
.ascii "sbw.shadow\0"
|
||
|
.fill 0x60 - (. - database)
|
||
|
.byte 0xe9, 0x22, 0xd8, 0x7c, 0x3c, 0x07, 0x54, 0x2d
|
||
|
.byte 0x5e, 0x53, 0x6a, 0xff, 0x80, 0x5e, 0xcd, 0xc8
|
||
|
.byte 0xcf, 0xff, 0x44, 0x74, 0xc8, 0xd8, 0x4b
|
||
|
|
||
|
.fill 0xbd - (. - database)
|
||
|
|
||
|
mem_input_user:
|
||
|
.ascii "________________\0"
|
||
|
|
||
|
mem_input_pass:
|
||
|
.ascii "________________________________________________________________\0"
|
||
|
|
||
|
str_prompt_user:
|
||
|
.ascii "Username: \0"
|
||
|
|
||
|
str_prompt_pass:
|
||
|
.ascii ">> Username OK. Password required\n"
|
||
|
.ascii "Password: \0"
|
||
|
|
||
|
str_please_wait:
|
||
|
.ascii ">> Please wait...\n\0"
|
||
|
|
||
|
str_incorrect_user:
|
||
|
.ascii ">> User not found in database.\n\0"
|
||
|
|
||
|
str_incorrect_pass:
|
||
|
.ascii ">> Password is incorrect.\n\0"
|
||
|
|
||
|
str_login_success:
|
||
|
.ascii ">> Login successful.\n"
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "Running machine language monitor now.\n"
|
||
|
.ascii "======================================================================\n"
|
||
|
.ascii "\n\0"
|
||
|
|
||
|
main:
|
||
|
# Save all the registers
|
||
|
push_sp
|
||
|
str_r0 mem_save_r0
|
||
|
str_r1 mem_save_r1
|
||
|
str_r2 mem_save_r2
|
||
|
str_r3 mem_save_r3
|
||
|
|
||
|
# Store the stack pointer
|
||
|
pop_r0
|
||
|
str_r0 mem_info_sp
|
||
|
|
||
|
# Read the return address
|
||
|
ld_r0_sp
|
||
|
ldr_r0_r0
|
||
|
add_r0 -1
|
||
|
str_r0 mem_info_pc
|
||
|
|
||
|
# Read some more stack values
|
||
|
ld_r1 (6 * 2)
|
||
|
ld_r2 mem_info_stack
|
||
|
ldr_r3 mem_info_sp
|
||
|
call MemCpy
|
||
|
|
||
|
# Print the processor state
|
||
|
ld_r2 str_breakpoint
|
||
|
call PrintStr
|
||
|
|
||
|
main_cmd_loop:
|
||
|
ld_r0 0
|
||
|
strb_r0 mem_e002
|
||
|
|
||
|
ld_r2 str_ready
|
||
|
call PrintStr
|
||
|
|
||
|
# Read input
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
cp_r3 0
|
||
|
jp_eq error_too_long
|
||
|
ld_r2 mem_e000
|
||
|
call StrTrim
|
||
|
|
||
|
# Make sure the input is at most 2 characters
|
||
|
ldrb_r0 mem_e002
|
||
|
cp_r0 0
|
||
|
jp_ne error_bad_command
|
||
|
|
||
|
# Parse all the commands
|
||
|
ldr_r0 mem_e000
|
||
|
|
||
|
cp_r0 ('h' + '\n' * 0x100)
|
||
|
jp_eq cmd_help
|
||
|
cp_r0 'h'
|
||
|
jp_eq cmd_help
|
||
|
|
||
|
cp_r0 'r'
|
||
|
jp_eq cmd_read
|
||
|
cp_r0 ('r' + '\n' * 0x100)
|
||
|
jp_eq cmd_read
|
||
|
|
||
|
cp_r0 'p'
|
||
|
jp_eq cmd_print
|
||
|
cp_r0 ('p' + '\n' * 0x100)
|
||
|
jp_eq cmd_print
|
||
|
|
||
|
cp_r0 'x'
|
||
|
jp_eq cmd_exec
|
||
|
cp_r0 ('x' + '\n' * 0x100)
|
||
|
jp_eq cmd_exec
|
||
|
|
||
|
cp_r0 'c'
|
||
|
jp_eq cmd_cont
|
||
|
cp_r0 ('c' + '\n' * 0x100)
|
||
|
jp_eq cmd_cont
|
||
|
|
||
|
cp_r0 ('U' + 'C' * 0x100)
|
||
|
jp_eq cmd_undoc
|
||
|
|
||
|
cp_r0 ('l' + 's' * 0x100)
|
||
|
jp_eq cmd_list
|
||
|
|
||
|
cp_r0 ('r' + 'f' * 0x100)
|
||
|
jp_eq cmd_readfile
|
||
|
|
||
|
cp_r0 'w'
|
||
|
jp_eq cmd_write
|
||
|
cp_r0 ('w' + '\n' * 0x100)
|
||
|
jp_eq cmd_write
|
||
|
|
||
|
error_bad_command:
|
||
|
ld_r2 str_error_bad_command
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
error_too_long:
|
||
|
ld_r2 str_error_too_long
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_help:
|
||
|
ld_r2 str_help
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_read:
|
||
|
# Get the address to read
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_read_invalid
|
||
|
push_r0
|
||
|
|
||
|
# Get the amount of lines to read
|
||
|
ld_r2 str_prompt_lines
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_read_invalid
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_read_invalid
|
||
|
|
||
|
# r2 = address, r3 = lines
|
||
|
ld_r3_r0
|
||
|
pop_r2
|
||
|
|
||
|
cmd_read_loop:
|
||
|
# Read 8 bytes
|
||
|
push_r2
|
||
|
push_r3
|
||
|
ld_r1 8
|
||
|
ld_r3_r2
|
||
|
ld_r2 mem_data
|
||
|
call MemCpy
|
||
|
pop_r3
|
||
|
pop_r2
|
||
|
|
||
|
# Store the current read address
|
||
|
str_r2 mem_addr
|
||
|
|
||
|
# Write it out
|
||
|
push_r2
|
||
|
push_r3
|
||
|
ld_r2 str_hexdump
|
||
|
call PrintStr
|
||
|
pop_r3
|
||
|
pop_r2
|
||
|
|
||
|
# Check if we're done
|
||
|
add_r2 8
|
||
|
dec_r3
|
||
|
cp_r3 0
|
||
|
jp_ne cmd_read_loop
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_read_invalid:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_write:
|
||
|
# Get the address to write
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_invalid
|
||
|
str_r0 mem_addr
|
||
|
|
||
|
ld_r2 str_prompt_hex
|
||
|
call PrintStr
|
||
|
|
||
|
cmd_write_loop:
|
||
|
# Clear the buffer
|
||
|
ld_r3 mem_e000 + 2
|
||
|
ld_r0 0
|
||
|
strb_r0_r3
|
||
|
dec_r3
|
||
|
strb_r0_r3
|
||
|
dec_r3
|
||
|
|
||
|
cmd_write_loop_first:
|
||
|
# Get the first nybble
|
||
|
copr_getc
|
||
|
strb_r0_r3
|
||
|
ld_r2_r3
|
||
|
|
||
|
# Check if it's the end or invalid
|
||
|
cp_r0 '.'
|
||
|
jp_eq cmd_write_end
|
||
|
cp_r0 '\n'
|
||
|
jp_eq cmd_write_loop_first
|
||
|
|
||
|
# Try to convert the nybble
|
||
|
push_r3
|
||
|
call ConvertHex
|
||
|
pop_r3
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_loop_first
|
||
|
|
||
|
inc_r3
|
||
|
|
||
|
cmd_write_loop_second:
|
||
|
# Get the second nybble
|
||
|
copr_getc
|
||
|
strb_r0_r3
|
||
|
ld_r2_r3
|
||
|
|
||
|
# Check if it's the end or invalid
|
||
|
cp_r0 '.'
|
||
|
jp_eq cmd_write_end
|
||
|
cp_r0 '\n'
|
||
|
jp_eq cmd_write_loop_second
|
||
|
|
||
|
# Try to convert the nybble
|
||
|
push_r3
|
||
|
call ConvertHex
|
||
|
pop_r3
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_write_loop_second
|
||
|
|
||
|
# Convert and store the full byte
|
||
|
dec_r3
|
||
|
ld_r2_r3
|
||
|
call ConvertHex
|
||
|
ldr_r1 mem_addr
|
||
|
strb_r0_r1
|
||
|
inc_r1
|
||
|
str_r1 mem_addr
|
||
|
jp cmd_write_loop # 0xf1d0
|
||
|
|
||
|
cmd_write_end:
|
||
|
# Read until newline
|
||
|
copr_getc
|
||
|
cp_r0 '\n'
|
||
|
jp_ne cmd_write_end
|
||
|
|
||
|
ld_r2 str_loaded
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_write_invalid:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_print:
|
||
|
# Get the string to print
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
|
||
|
ld_r2_r0
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_exec:
|
||
|
# Get the address to execute
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ld_r2 mem_e000
|
||
|
call ConvertHex
|
||
|
|
||
|
# Prompt the user to execute the address
|
||
|
push_r0
|
||
|
str_r0 mem_addr
|
||
|
ld_r2 str_prompt_exec
|
||
|
call PrintStr
|
||
|
ld_r2 mem_e000
|
||
|
ld_r3 8
|
||
|
call ReadStr
|
||
|
ldrb_r0 mem_e000
|
||
|
cp_r0 'Y'
|
||
|
jp_eq cmd_exec_go
|
||
|
cp_r0 'y'
|
||
|
jp_eq cmd_exec_go
|
||
|
|
||
|
# Cancel the call
|
||
|
ld_r2 str_error_cancelled
|
||
|
call PrintStr
|
||
|
pop_r0
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_exec_go:
|
||
|
# Call the function
|
||
|
pop_r3
|
||
|
call_r3
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_cont:
|
||
|
ld_r2 str_continuing
|
||
|
call PrintStr
|
||
|
|
||
|
# Restore register state and unpause
|
||
|
ldr_r0 mem_save_r0
|
||
|
ldr_r1 mem_save_r1
|
||
|
ldr_r2 mem_save_r2
|
||
|
ldr_r3 mem_save_r3
|
||
|
ret
|
||
|
|
||
|
cmd_list:
|
||
|
ld_r2 str_file_list_header
|
||
|
call PrintStr
|
||
|
|
||
|
# Read directory
|
||
|
ld_r0 0
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
ld_r3 mem_e000
|
||
|
cmd_list_loop:
|
||
|
ldrb_r0_r3
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_list_next
|
||
|
|
||
|
# Store block
|
||
|
push_r3
|
||
|
strb_r0 mem_data
|
||
|
inc_r3
|
||
|
ldr_r0_r3
|
||
|
|
||
|
# Store size
|
||
|
push_r3
|
||
|
str_r0 mem_addr
|
||
|
|
||
|
# Print block and size
|
||
|
ld_r2 str_file_list_entry
|
||
|
call PrintStr
|
||
|
pop_r3
|
||
|
|
||
|
# Print filename
|
||
|
inc_r3
|
||
|
inc_r3
|
||
|
ld_r2_r3
|
||
|
call PrintStr
|
||
|
ld_r0 '\n'
|
||
|
copr_putc
|
||
|
pop_r3
|
||
|
|
||
|
cmd_list_next:
|
||
|
add_r3 0x10
|
||
|
cp_r3 mem_ef00
|
||
|
jp_ne cmd_list_loop
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_undoc:
|
||
|
ld_r2 str_undoc
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile:
|
||
|
ld_r2 str_prompt_filename
|
||
|
call PrintStr
|
||
|
|
||
|
# Read directory
|
||
|
ld_r0 0
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
# Get filename to read
|
||
|
ld_r2 mem_efb0
|
||
|
ld_r3 0x10
|
||
|
call ReadStr
|
||
|
cp_r3 0
|
||
|
jp_eq cmd_readfile_error_too_long
|
||
|
ld_r2 mem_efb0
|
||
|
call StrTrim
|
||
|
|
||
|
ld_r3 mem_e000 + 3
|
||
|
cmd_readfile_loop:
|
||
|
# Check if the filename matches
|
||
|
ld_r2 mem_efb0
|
||
|
push_r3
|
||
|
call StrCmp
|
||
|
pop_r3
|
||
|
cp_r0 0
|
||
|
jp_eq cmd_readfile_match
|
||
|
|
||
|
add_r3 0x10
|
||
|
cp_r3 mem_ef00 + 3
|
||
|
jp_eq cmd_readfile_error_not_found
|
||
|
jp cmd_readfile_loop
|
||
|
|
||
|
cmd_readfile_match:
|
||
|
# Read file block
|
||
|
dec_r3
|
||
|
dec_r3
|
||
|
dec_r3
|
||
|
ldrb_r0_r3
|
||
|
|
||
|
# Read file size
|
||
|
inc_r3
|
||
|
ldr_r1_r3
|
||
|
|
||
|
# Read file into memory
|
||
|
push_r1
|
||
|
ld_r1 mem_e000
|
||
|
copr_readblk
|
||
|
|
||
|
# Prompt for address to write to
|
||
|
ld_r2 str_prompt_address
|
||
|
call PrintStr
|
||
|
ld_r2 mem_efe0
|
||
|
ld_r3 0x10
|
||
|
call ReadStr
|
||
|
ld_r2 mem_efe0
|
||
|
call ConvertHex
|
||
|
pop_r1
|
||
|
cp_r0 -1
|
||
|
jp_eq cmd_readfile_error_invalid_input
|
||
|
|
||
|
# Copy the data
|
||
|
ld_r2_r0
|
||
|
ld_r3 mem_e000
|
||
|
call MemCpy
|
||
|
|
||
|
ld_r2 str_loaded
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_not_found:
|
||
|
ld_r2 str_error_not_found
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_too_long:
|
||
|
ld_r2 str_error_too_long
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
cmd_readfile_error_invalid_input:
|
||
|
ld_r2 str_error_invalid_input
|
||
|
call PrintStr
|
||
|
jp main_cmd_loop
|
||
|
|
||
|
str_intro:
|
||
|
.ascii "======================================================================\r\n"
|
||
|
.ascii "Welcome to Glitch Research Laboratory Network: Test Server 2 (GRLTS02)\r\n"
|
||
|
.ascii "======================================================================\r\n"
|
||
|
.ascii "This machine requires authentication.\r\n\0"
|
||
|
|
||
|
str_error_too_long:
|
||
|
.ascii "! Input too long error.\n\0"
|
||
|
|
||
|
str_error_bad_command:
|
||
|
.ascii "! Bad command error (h for help).\n\0"
|
||
|
|
||
|
str_error_invalid_input:
|
||
|
.ascii "! Invalid input error.\n\0"
|
||
|
|
||
|
str_prompt_address:
|
||
|
.ascii "> Which address? \0"
|
||
|
|
||
|
str_prompt_lines:
|
||
|
.ascii "> How many lines? \0"
|
||
|
|
||
|
str_prompt_exec:
|
||
|
.ascii "> Really exec at "
|
||
|
text_ram_word mem_addr
|
||
|
.ascii "? Type Y if so: \0"
|
||
|
|
||
|
str_error_cancelled:
|
||
|
.ascii "! Cancelled action error.\n\0"
|
||
|
|
||
|
str_continuing:
|
||
|
.ascii "Continuing.\n\0"
|
||
|
|
||
|
str_loaded:
|
||
|
.ascii "Loaded.\n\0"
|
||
|
|
||
|
str_dry_stack:
|
||
|
.ascii "! Dry stack. Halting machine.\n\0"
|
||
|
|
||
|
str_prompt_filename:
|
||
|
.ascii "> Filename? \0"
|
||
|
|
||
|
str_error_not_found:
|
||
|
.ascii "! File not found error.\n\0"
|
||
|
|
||
|
str_prompt_hex:
|
||
|
.ascii "> Enter hex data. End with dot \".\" + newline:\n\0"
|
||
|
|
||
|
str_undoc:
|
||
|
.ascii "Wow, undocumented monitor command! FOOLS2023_{Secret"
|
||
|
text_ram_word 0xe000
|
||
|
.ascii "x"
|
||
|
text_ram_word 0xe001
|
||
|
.ascii "Command}\n\0"
|
||
|
|
||
|
str_help:
|
||
|
.ascii "Available commands:\n"
|
||
|
.ascii "r :: print memory as hex\n"
|
||
|
.ascii "p :: print memory as text\n"
|
||
|
.ascii "w :: write hex data to memory\n"
|
||
|
.ascii "x :: execute memory\n"
|
||
|
.ascii "rf :: load memory from file\n"
|
||
|
.ascii "ls :: print file index\n"
|
||
|
.ascii "h :: print this help message\n"
|
||
|
.ascii "c :: exit monitor and continue\n"
|
||
|
.ascii "Please enter hex numbers when prompted.\n"
|
||
|
.ascii "If necessary for debugging, you can break into monitor\n"
|
||
|
.ascii "with instruction BRK (0x00) and continue with 'c'\n"
|
||
|
.ascii "Note: memory region E000-FFFF is used by monitor\n\0"
|
||
|
|
||
|
str_file_list_header:
|
||
|
.ascii "BLK SIZE NAME\n"
|
||
|
.ascii "=======================\n\0"
|
||
|
|
||
|
str_file_list_entry:
|
||
|
text_ram_byte mem_data
|
||
|
.ascii " "
|
||
|
text_ram_word mem_addr
|
||
|
.ascii " \0" # 0xfa97
|
||
|
|
||
|
str_ready:
|
||
|
.ascii "Ready.\n"
|
||
|
.ascii "> \0"
|
||
|
|
||
|
str_breakpoint:
|
||
|
.ascii "*** BREAK INTO MONITOR AT $"
|
||
|
text_ram_word mem_info_pc
|
||
|
.ascii " ***\n"
|
||
|
.ascii "R0=$"
|
||
|
text_ram_word mem_save_r0
|
||
|
.ascii " R1=$"
|
||
|
text_ram_word mem_save_r1
|
||
|
.ascii " R2=$"
|
||
|
text_ram_word mem_save_r2
|
||
|
.ascii " R3=$"
|
||
|
text_ram_word mem_save_r3
|
||
|
.ascii "\n"
|
||
|
.ascii "SP=$"
|
||
|
text_ram_word mem_info_sp
|
||
|
.ascii " ["
|
||
|
text_ram_byte mem_info_stack + 0
|
||
|
text_ram_byte mem_info_stack + 1
|
||
|
text_ram_byte mem_info_stack + 2
|
||
|
text_ram_byte mem_info_stack + 3
|
||
|
text_ram_byte mem_info_stack + 4
|
||
|
text_ram_byte mem_info_stack + 5
|
||
|
text_ram_byte mem_info_stack + 6
|
||
|
text_ram_byte mem_info_stack + 7
|
||
|
text_ram_byte mem_info_stack + 8
|
||
|
text_ram_byte mem_info_stack + 9
|
||
|
text_ram_byte mem_info_stack + 10
|
||
|
text_ram_byte mem_info_stack + 11
|
||
|
.ascii "]\n\0"
|
||
|
|
||
|
str_hexdump:
|
||
|
text_ram_word mem_addr
|
||
|
.ascii " | "
|
||
|
text_ram_byte mem_data + 0
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 1
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 2
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 3
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 4
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 5
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 6
|
||
|
.ascii " "
|
||
|
text_ram_byte mem_data + 7
|
||
|
.ascii "\n\0"
|
||
|
|
||
|
mem_save_r0:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r1:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r2:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_save_r3:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_sp:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_pc:
|
||
|
.2byte 0
|
||
|
|
||
|
mem_info_stack:
|
||
|
.fill 12
|
||
|
|
||
|
mem_data:
|
||
|
.fill 8
|
||
|
|
||
|
mem_addr:
|
||
|
.2byte 0
|
||
|
|
||
|
.fill 0xf00 - (. - _start)
|
||
|
stack:
|
||
|
.fill 0xf0
|
||
|
|
||
|
entry:
|
||
|
.fill 0x10
|