@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