fox32rom: Use a FIFO queue for events instead of a LIFO stack

Using a LIFO stack for events was a dumb idea in the first place, this
should've been a FIFO queue from the beginning.

This allows the system to respond to events in the same order that they
are generated, instead of always responding to the newest event first.
This commit is contained in:
ry755 2022-02-11 20:27:23 -08:00 committed by Ry
parent 203822e4f6
commit 041cf206ec
6 changed files with 160 additions and 93 deletions

196
event.asm
View File

@ -1,7 +1,11 @@
; event system routines
const event_stack: 0x01FFFFFC ; pre-decremented
const event_stack_pointer: 0x01FFFFFC
const event_queue_top: 0x01FFFFFE
const event_queue_bottom: 0x01FFFBFE ; top - 0x400 (32 events * (4 bytes * (1 type + 7 parameters)))
const event_queue_index: 0x01FFFFFF ; byte
const event_queue_size: 32 ; 32 events
const event_size_bytes: 32 ; 32 bytes per event
const event_size_words: 8 ; 8 words per event
; event types
const mouse_click_event_type: 0x00000000
@ -15,112 +19,164 @@ const empty_event_type: 0xFFFFFFFF
; none
; outputs:
; r0: event type
; r1-r5: event parameters
; r1-r7: event parameters
wait_for_event:
ise
halt
; check the event stack pointer
; if equal to its base address, then the event stack is empty
cmp [event_stack_pointer], event_stack_pointer
; if the event queue index doesn't equal zero, then at least one event is available
cmp.8 [event_queue_index], 0
ifz jmp wait_for_event
; an event is available in the event stack, pop it from the stack and return it
call pop_event
; an event is available in the event queue, remove it from the queue and return it
call get_next_event
ret
; push an event to the event stack
; add an event to the event queue
; inputs:
; r0: event type
; r1-r5: event parameters
; r1-r7: event parameters
; outputs:
; none
push_event:
push r6
new_event:
; ensure there is enough space left for another event
cmp.8 [event_queue_index], event_queue_size
ifz ret
mov r6, [event_stack_pointer]
; TODO: check to make sure we don't accidentally clobber the system stack by pushing too many events
push r8
push r9
; push r0
sub r6, 4
mov [r6], r0
; point to the current event queue index
mov r8, event_queue_bottom
movz.8 r9, [event_queue_index]
mul r9, event_size_bytes
add r8, r9
; push r1
sub r6, 4
mov [r6], r1
; copy the event type
mov [r8], r0
add r8, 4
; push r2
sub r6, 4
mov [r6], r2
; copy the event parameters
mov [r8], r1
add r8, 4
mov [r8], r2
add r8, 4
mov [r8], r3
add r8, 4
mov [r8], r4
add r8, 4
mov [r8], r5
add r8, 4
mov [r8], r6
add r8, 4
mov [r8], r7
add r8, 4
; push r3
sub r6, 4
mov [r6], r3
; increment the index
inc.8 [event_queue_index]
; push r4
sub r6, 4
mov [r6], r4
; push r5
sub r6, 4
mov [r6], r5
mov [event_stack_pointer], r6
pop r6
pop r9
pop r8
ret
; pop an event from the event stack
; get the next event and remove it from the event queue
; inputs:
; none
; outputs:
; r0: event type
; r1-r5: event parameters
pop_event:
; check the event stack pointer
; if equal to its base address, then the event stack is empty
cmp [event_stack_pointer], event_stack_pointer
ifz jmp pop_event_empty
; r1-r7: event parameters
get_next_event:
; if the event queue index equals zero, then the queue is empty
cmp.8 [event_queue_index], 0
ifz jmp get_next_event_empty
push r6
icl
push r8
mov r6, [event_stack_pointer]
; point to the bottom of the event queue
mov r8, event_queue_bottom
; pop r5
mov r5, [r6]
add r6, 4
; copy the event type
mov r0, [r8]
add r8, 4
; pop r4
mov r4, [r6]
add r6, 4
; copy the event parameters
mov r1, [r8]
add r8, 4
mov r2, [r8]
add r8, 4
mov r3, [r8]
add r8, 4
mov r4, [r8]
add r8, 4
mov r5, [r8]
add r8, 4
mov r6, [r8]
add r8, 4
mov r7, [r8]
; pop r3
mov r3, [r6]
add r6, 4
; shift all events down by one
call shift_events
; pop r2
mov r2, [r6]
add r6, 4
; decrement the index
dec.8 [event_queue_index]
; pop r1
mov r1, [r6]
add r6, 4
; pop r0
mov r0, [r6]
add r6, 4
mov [event_stack_pointer], r6
pop r6
pop r8
ise
ret
pop_event_empty:
get_next_event_empty:
mov r0, empty_event_type
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
ret
; shift all events down by one, overwriting the zero'th event
; inputs:
; none
; outputs:
; none
shift_events:
push r0
push r1
push r2
push r3
push r4
; for (int i = 0; i < (event_queue_index - 1); i++) {
; event_queue[i] = event_queue[i + 1];
; }
movz.8 r31, [event_queue_index]
mov r3, 0 ; i
; source pointer: event_queue[i + 1]
mov r0, event_queue_bottom
mov r4, r3
inc r4
mul r4, event_size_words
add r0, r4
; destination pointer: event_queue[i]
mov r1, event_queue_bottom
mov r4, r3
mul r4, event_size_words
add r1, r4
; size: event_size_words
mov r2, event_size_words
call copy_memory_words
pop r4
pop r3
pop r2
pop r1
pop r0
ret

View File

@ -3,8 +3,9 @@
; system jump table entries
system_vsync_handler: jmp [0xF1000000]
get_mouse_position: jmp [0xF1000004]
push_event: jmp [0xF1000008]
new_event: jmp [0xF1000008]
wait_for_event: jmp [0xF100000C]
get_next_event: jmp [0xF1000010]
; background jump table entries
draw_str_to_background: jmp [0xF1001000]

View File

@ -8,7 +8,6 @@ const background_color: 0xFF414C50
; initialization code
entry:
mov rsp, system_stack
mov [event_stack_pointer], event_stack
mov [0x000003FC], system_vsync_handler
@ -110,8 +109,7 @@ draw_startup_text:
ise
event_loop:
halt
call pop_event
call get_next_event
; was the mouse clicked?
cmp r0, mouse_click_event_type
@ -183,8 +181,9 @@ mount_boot_disk:
org.pad 0xF1000000
data.32 system_vsync_handler
data.32 get_mouse_position
data.32 push_event
data.32 new_event
data.32 wait_for_event
data.32 get_next_event
; background jump table
org.pad 0xF1001000

View File

@ -113,6 +113,8 @@ menu_bar_click_event:
push r3
push r4
push r5
push r6
push r7
push r28
push r29
push r30
@ -156,18 +158,7 @@ menu_bar_click_event_loop:
;mov r1, 0xFFFFFFFF
;call draw_menu_bar_root_items ; close_submenu already calls this
call close_submenu
pop r31
pop r30
pop r29
pop r28
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
ret
jmp menu_bar_click_event_end
menu_bar_click_event_found_item:
; r30 contains the clicked root menu item (starting at 0)
pop r0
@ -182,13 +173,17 @@ menu_bar_click_event_found_item:
mov r3, 0xFFFFFFFF ; event parameter 2: hovering submenu item (or 0xFFFFFFFF for none)
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, submenu_update_event_type
call push_event
call new_event
menu_bar_click_event_end:
pop r31
pop r30
pop r29
pop r28
pop r7
pop r6
pop r5
pop r4
pop r3

View File

@ -34,6 +34,8 @@ mouse_update:
push r3
push r4
push r5
push r6
push r7
mov r0, 0x8000001F ; overlay 31: position
in r2, 0x80000401 ; mouse position
@ -75,8 +77,10 @@ mouse_update:
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, mouse_click_event_type ; set event type to mouse type
call push_event
call new_event
jmp mouse_update_end
mouse_update_menu_was_clicked:
mov r2, r1 ; copy Y position to event parameter 1
@ -84,9 +88,13 @@ mouse_update_menu_was_clicked:
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, menu_bar_click_event_type ; set event type to menu bar click type
call push_event
call new_event
mouse_update_end:
pop r7
pop r6
pop r5
pop r4
pop r3

View File

@ -186,6 +186,8 @@ submenu_update_event:
push r3
push r4
push r5
push r6
push r7
push r8
push r9
@ -235,8 +237,10 @@ submenu_update_event_clicked:
mov r3, r10 ; event parameter 2: selected submenu item
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, submenu_click_event_type
call push_event
call new_event
mov r0, r1
call close_submenu
jmp submenu_update_event_end_no_push
@ -247,11 +251,15 @@ submenu_update_event_end_push:
mov r3, r10 ; event parameter 2: hovering submenu item (or 0xFFFFFFFF for none)
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r0, submenu_update_event_type
call push_event
call new_event
submenu_update_event_end_no_push:
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
pop r3