diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2024-04-26 15:40:14 +0300 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2024-04-26 15:40:14 +0300 |
| commit | 7ca56c1a730fcecd0fe3af5e6b652fa09514a18b (patch) | |
| tree | e2ef6a4d28fa26adf11e00d138ef21b8316497f6 /atk16_projects/monitor | |
| parent | 2b18b320e97260f1d27143a37fe14953cf62e56d (diff) | |
Refactor project structure, add README and LICENSE
Diffstat (limited to 'atk16_projects/monitor')
| -rw-r--r-- | atk16_projects/monitor/Makefile | 16 | ||||
| -rw-r--r-- | atk16_projects/monitor/monitor.atk16 | 176 | ||||
| -rw-r--r-- | atk16_projects/monitor/monitor_macros.py | 45 |
3 files changed, 237 insertions, 0 deletions
diff --git a/atk16_projects/monitor/Makefile b/atk16_projects/monitor/Makefile new file mode 100644 index 0000000..ad8013b --- /dev/null +++ b/atk16_projects/monitor/Makefile @@ -0,0 +1,16 @@ +EMULATOR = atk16emu +ASSEMBLER = atk16c +PROJ = monitor + +out/$(PROJ).bin: $(PROJ).atk16 + $(ASSEMBLER) $< -o out/$(PROJ).bin + +### + +@PHONY: run +run: out/$(PROJ).bin + $(EMULATOR) $< + +@PHONY: debug +debug: out/$(PROJ).bin + $(EMULATOR) -d $< diff --git a/atk16_projects/monitor/monitor.atk16 b/atk16_projects/monitor/monitor.atk16 new file mode 100644 index 0000000..d3b8756 --- /dev/null +++ b/atk16_projects/monitor/monitor.atk16 @@ -0,0 +1,176 @@ +@use monitor_macros:* + +@include %bootstrap +@include %std_mem +@include %std_term +@include %std_bump_alloc + +; Constants +@data text_buffer_size 2048 +@data input_buffer_size 64 + +; Global variable pointers +; 0xE800 - 0xEFFF: sprite buffer space that is unused in this program +@data text_cursor_p 0xE800 +@data input_buffer_p 0xE801 +@data input_cursor_p 0xE802 + +@data title_string " »» ATK16 monitor v0.1 »»" +@data subtitle_string " Run [help] for a list of commands" +@data prompt_string " > " + +@label main + ; initialize heap allocator + calli bump_reset + + ; initialize global variables + ; BEGIN text_cursor_p = text_mem + ldi text_cursor_p RA + ldr RA RA + ldi vt_text_mem RB + ldr RB RB + str RB RA + ; END + + ; BEGIN input_buffer_p = alloc(64) + ldi input_buffer_size RA + calli bump_alloc + ldi input_buffer_p RA + ldr RA RA + str RG RA + ; END + + ; use memset to clear the text buffer + ; BEGIN memset(text_mem, 0, text_buffer_size) + ldi vt_text_mem RA ; RA := text buffer address pointer + ldr RA RA ; RA := text buffer address + ldi text_buffer_size RB ; RB := pointer to text_buffer_size + ldr RB RB ; RB := text_buffer_size + ldi 0 RC ; RC := 0 + calli memset + ; END + + set_graphics_mode gr_text_mode + + m_newline RA RB + + ; BEGIN put_string(title_string) + ldi title_string RA + calli put_string + ; END + + m_newline RA RB + + ; BEGIN put_string(subtitle_string) + ldi subtitle_string RA + calli put_string + ; END + + m_newline RA RB + m_newline RA RB + + ldi prompt_string RA + calli put_string + +; loop forever +@label loop + ; BEGIN critical section + m_set_critical RA RB + + calli is_newline_pressed + subi RG 1 RG ; if is_newline_pressed() == 1, then loop_newline_pressed + bri zero loop_newline_pressed + jpi loop_finally + +@label loop_newline_pressed + ; TODO + jpi loop_finally + +@label loop_finally + m_clear_critical RA RB + ; END critical section + jpi loop + +;;; Subroutines + +@label newline + ; move cursor to the beginning of the next line + ; parameters: none + ; returns: none + + stack_stash RA RB + m_newline RA RB + stack_restore RA RB + return + +@label put_char + ; put a character at the current cursor position + ; parameters: RA = character to put + ; returns: none + + stack_stash RB RC + m_put_char RA RB RC + stack_restore RB RC + return + +@label put_string + ; put a string at the current cursor position + ; parameters: RA = string_p + ; returns: none + + stack_stash RA RB RC RD RE + ldr RA RB ; RB := string length + addi RA 1 RC ; RC := pointer to first character +@label put_string_loop + subi RB 0 RB ; exit if RB has been decremented to 0 + bri zero put_string_done ; i.e. no more characters to put + + ldr RC RA ; RA := character to put + m_put_char RA RD RE ; inline the put_char subroutine to avoid function call overhead + + inc RC + subi RB 1 RB + jpi put_string_loop +@label put_string_done + stack_restore RA RB RC RD RE + return + +@label wait_for_input_newline + ; wait for a newline character in the input buffer + ; parameters: none + ; returns: RG = key code + stack_stash RA RB + ldi 10 RB ; RB := newline character +@label wait_for_input_newline_loop + ldi input_cursor_p RA ; RA := data segment pointer + ldr RA RA ; RA := 0xE802 + ldr RA RA ; RA := &char + ldr RA RA ; RA := char + + sub RA RB RA ; if RA == newline, then stop waiting + bri zero wait_for_input_newline_done + + jpi wait_for_input_newline_loop +@label wait_for_input_newline_done + stack_restore RA RB + return + +@label is_newline_pressed + ; check if the last character in the input buffer is a newline + ; parameters: none + ; returns: RG = 1 if newline is pressed, 0 otherwise + stack_stash RA RB + ldi 10 RB ; RB := newline character + + ldi input_cursor_p RA ; RA := data segment pointer + ldr RA RA ; RA := 0xE802 + ldr RA RA ; RA := &char + ldr RA RA ; RA := char + + ldi 1 RG ; RG := 1 + sub RA RB RA ; if RA == newline, then return RG = 1 + bri zero is_newline_pressed_done + ldi 0 RG ; else return RG = 0 +@label is_newline_pressed_done + stack_restore RA RB + return diff --git a/atk16_projects/monitor/monitor_macros.py b/atk16_projects/monitor/monitor_macros.py new file mode 100644 index 0000000..b40be9e --- /dev/null +++ b/atk16_projects/monitor/monitor_macros.py @@ -0,0 +1,45 @@ +from atk16_asm.asm_ops import * + +expansions: dict[str, Callable[..., ExpandResult]] = {} +def register_macro(func): + expansions[func.__name__] = func + return func + +@register_macro +def m_newline(r1: str, r2: str) -> ExpandResult: + return [ + *expand_ldi("text_cursor_p", r1), + *expand_ldr(r1, r1), + *expand_ldr(r1, r2), + *expand_slri(r2, "6", r2), # cursor = cursor / 64 + *expand_addi(r2, "1", r2), # cursor = cursor + 1 + *expand_slli(r2, "6", r2), # cursor = cursor * 64 + *expand_str(r2, r1), + ] + +@register_macro +def m_put_char(char_r: str, r1: str, r2: str) -> ExpandResult: + return [ + *expand_ldi("text_cursor_p", r1), + *expand_ldr(r1, r1), + *expand_ldr(r1, r2), + *expand_str(char_r, r2), + *expand_addi(r2, "1", r2), + *expand_str(r2, r1), + ] + +def m_set_interrupt_state(r1: str, r2: str, value: int) -> ExpandResult: + return [ + *expand_ldi("vt_iset_addr", r1), + *expand_ldr(r1, r1), + *expand_ldi(value, r2), + *expand_str(r2, r1), + ] + +@register_macro +def m_set_critical(r1: str, r2: str) -> ExpandResult: + return m_set_interrupt_state(r1, r2, 1) + +@register_macro +def m_clear_critical(r1: str, r2: str) -> ExpandResult: + return m_set_interrupt_state(r1, r2, 0) |
