Initial commit
I should've made a git repo for this much sooner, oops :p
This commit is contained in:
commit
705593697b
166
background.asm
Normal file
166
background.asm
Normal file
|
@ -0,0 +1,166 @@
|
|||
; background routines
|
||||
|
||||
const background: 0x02000000 ; pointer to background framebuffer
|
||||
|
||||
; fill the whole background with a color
|
||||
; inputs:
|
||||
; r0: color
|
||||
; outputs:
|
||||
; none
|
||||
fill_background:
|
||||
push r1
|
||||
push r31
|
||||
|
||||
mov r1, background
|
||||
mov r31, 0x0004B000 ; 640*480
|
||||
fill_background_loop:
|
||||
mov [r1], r0
|
||||
add r1, 4
|
||||
loop fill_background_loop
|
||||
|
||||
pop r31
|
||||
pop r1
|
||||
ret
|
||||
|
||||
; draw a filled rectangle to the background
|
||||
; inputs:
|
||||
; r0: X coordinate of top-left
|
||||
; r1: Y coordinate of top-left
|
||||
; r2: X size
|
||||
; r3: Y size
|
||||
; r4: color
|
||||
; outputs:
|
||||
; none
|
||||
draw_filled_rectangle_to_background:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
|
||||
; calculate pointer to the framebuffer
|
||||
mul r1, 2560 ; y * 2560 (640 * 4 = 2560)
|
||||
mul r0, 4 ; x * 4
|
||||
add r0, r1 ; y * 2560 + (x * 4)
|
||||
add r0, background ; r0: pointer to framebuffer
|
||||
|
||||
mov r6, r2
|
||||
mul r6, 4 ; multiply the X size by 4, since 4 bytes per pixel
|
||||
|
||||
draw_filled_rectangle_to_background_y_loop:
|
||||
mov r5, r2 ; x counter
|
||||
draw_filled_rectangle_to_background_x_loop:
|
||||
mov [r0], r4
|
||||
add r0, 4 ; increment framebuffer pointer
|
||||
dec r5
|
||||
ifnz jmp draw_filled_rectangle_to_background_x_loop ; loop if there are still more X pixels to draw
|
||||
|
||||
sub r0, r6 ; return to the beginning of this line
|
||||
add r0, 2560 ; 640*4, increment to the next line
|
||||
dec r3
|
||||
ifnz jmp draw_filled_rectangle_to_background_y_loop ; loop if there are still more Y pixels to draw
|
||||
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; draw a single font tile to the background
|
||||
; inputs:
|
||||
; r0: tile number
|
||||
; r1: X coordinate
|
||||
; r2: Y coordinate
|
||||
; r3: foreground color
|
||||
; r4: background color
|
||||
; outputs:
|
||||
; none
|
||||
draw_font_tile_to_background:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r5
|
||||
push r6
|
||||
|
||||
;movz.8 r0, r0 ; ensure the tile number is a single byte
|
||||
|
||||
; calculate pointer to the tile data
|
||||
push r1
|
||||
push r2
|
||||
mov r1, 8 ; tile width
|
||||
mov r2, 16 ; tile height
|
||||
mul r1, r2
|
||||
mul r0, r1
|
||||
mul r0, 4 ; 4 bytes per pixel
|
||||
add r0, font ; r0: pointer to tile data
|
||||
pop r2
|
||||
pop r1
|
||||
|
||||
; calculate pointer to the framebuffer
|
||||
mul r2, 2560 ; y * 2560 (640 * 4 = 2560)
|
||||
mul r1, 4 ; x * 4
|
||||
add r1, r2 ; y * 2560 + (x * 4)
|
||||
add r1, background ; r1: pointer to framebuffer
|
||||
|
||||
mov r6, 16 ; y counter
|
||||
draw_font_tile_to_background_y_loop:
|
||||
mov r5, 8 ; x counter
|
||||
draw_font_tile_to_background_x_loop:
|
||||
mov r2, [r0]
|
||||
cmp r2, 0xFF000000
|
||||
ifz jmp draw_font_tile_to_background_x_loop_background
|
||||
; drawing foreground pixel
|
||||
cmp r3, 0x00000000 ; is the foreground color supposed to be transparent?
|
||||
ifz jmp draw_font_tile_to_background_x_loop_end
|
||||
mov [r1], r3 ; draw foreground color
|
||||
jmp draw_font_tile_to_background_x_loop_end
|
||||
draw_font_tile_to_background_x_loop_background:
|
||||
; drawing background pixel
|
||||
cmp r4, 0x00000000 ; is the background color supposed to be transparent?
|
||||
ifz jmp draw_font_tile_to_background_x_loop_end
|
||||
mov [r1], r4 ; draw background color
|
||||
draw_font_tile_to_background_x_loop_end:
|
||||
add r0, 4 ; increment tile pointer
|
||||
add r1, 4 ; increment framebuffer pointer
|
||||
dec r5
|
||||
ifnz jmp draw_font_tile_to_background_x_loop ; loop if there are still more X pixels to draw
|
||||
sub r1, 32 ; 8*4, return to the beginning of this line
|
||||
add r1, 2560 ; 640*4, increment to the next line
|
||||
dec r6
|
||||
ifnz jmp draw_font_tile_to_background_y_loop ; loop if there are still more Y pixels to draw
|
||||
|
||||
pop r6
|
||||
pop r5
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; draw text on the background
|
||||
; inputs:
|
||||
; r0: pointer to null-terminated string
|
||||
; r1: X coordinate
|
||||
; r2: Y coordinate
|
||||
; r3: foreground color
|
||||
; r4: background color
|
||||
; outputs:
|
||||
; r1: X coordinate of end of text
|
||||
draw_str_to_background:
|
||||
push r0
|
||||
push r5
|
||||
mov r5, r0
|
||||
draw_str_to_background_loop:
|
||||
movz.8 r0, [r5]
|
||||
call draw_font_tile_to_background
|
||||
inc r5
|
||||
add r1, 8
|
||||
cmp.8 [r5], 0x00
|
||||
ifnz jmp draw_str_to_background_loop
|
||||
pop r5
|
||||
pop r0
|
||||
ret
|
93
event.asm
Normal file
93
event.asm
Normal file
|
@ -0,0 +1,93 @@
|
|||
; event system routines
|
||||
|
||||
const event_stack: 0x01FFFFFC ; pre-decremented
|
||||
const event_stack_pointer: 0x01FFFFFC
|
||||
|
||||
; event types
|
||||
const mouse_click_event_type: 0x00000000
|
||||
const menu_bar_click_event_type: 0x00000001
|
||||
const submenu_update_event_type: 0x00000002
|
||||
const submenu_click_event_type: 0x00000003
|
||||
const empty_event_type: 0xFFFFFFFF
|
||||
|
||||
; block until an event is available
|
||||
; inputs:
|
||||
; none
|
||||
; outputs:
|
||||
; r0: event type
|
||||
; r1-r5: event parameters
|
||||
wait_for_event:
|
||||
ise
|
||||
halt
|
||||
|
||||
; check the event stack pointer
|
||||
; if equal to 0x01FFFFFC, then the event stack is empty
|
||||
cmp [event_stack_pointer], 0x01FFFFFC
|
||||
ifz jmp wait_for_event
|
||||
|
||||
; an event is available in the event stack, pop it from the stack and return it
|
||||
call pop_event
|
||||
|
||||
ret
|
||||
|
||||
; push an event to the event stack
|
||||
; inputs:
|
||||
; r0: event type
|
||||
; r1-r5: event parameters
|
||||
; outputs:
|
||||
; none
|
||||
push_event:
|
||||
icl
|
||||
push r6
|
||||
mov r6, rsp
|
||||
mov rsp, [event_stack_pointer]
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
mov [event_stack_pointer], rsp
|
||||
mov rsp, r6
|
||||
pop r6
|
||||
ise
|
||||
|
||||
ret
|
||||
|
||||
; pop an event from the event stack
|
||||
; inputs:
|
||||
; none
|
||||
; outputs:
|
||||
; r0: event type
|
||||
; r1-r5: event parameters
|
||||
pop_event:
|
||||
; check the event stack pointer
|
||||
; if equal to 0x01FFFFFC, then the event stack is empty
|
||||
cmp [event_stack_pointer], 0x01FFFFFC
|
||||
ifz jmp pop_event_empty
|
||||
|
||||
icl
|
||||
push r6
|
||||
mov r6, rsp
|
||||
mov rsp, [event_stack_pointer]
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
mov [event_stack_pointer], rsp
|
||||
mov rsp, r6
|
||||
pop r6
|
||||
ise
|
||||
|
||||
ret
|
||||
pop_event_empty:
|
||||
mov r0, empty_event_type
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
|
||||
ret
|
BIN
font/cursor2.png
Normal file
BIN
font/cursor2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 625 B |
BIN
font/cursor2.raw
Normal file
BIN
font/cursor2.raw
Normal file
Binary file not shown.
BIN
font/cursor2.xcf
Normal file
BIN
font/cursor2.xcf
Normal file
Binary file not shown.
4352
font/unifont-thin.inc
Normal file
4352
font/unifont-thin.inc
Normal file
File diff suppressed because it is too large
Load Diff
BIN
font/unifont-thin.png
Normal file
BIN
font/unifont-thin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
font/unifont-thin.xcf
Normal file
BIN
font/unifont-thin.xcf
Normal file
Binary file not shown.
227
menu.asm
Normal file
227
menu.asm
Normal file
|
@ -0,0 +1,227 @@
|
|||
; menu bar routines
|
||||
|
||||
; clear menu bar
|
||||
; inputs:
|
||||
; none
|
||||
; outputs:
|
||||
; none
|
||||
clear_menu_bar:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r31
|
||||
|
||||
mov r31, 80
|
||||
movz.8 r0, ' '
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0xFF000000
|
||||
mov r4, 0xFFFFFFFF
|
||||
mov r5, 30
|
||||
clear_menu_bar_loop:
|
||||
call draw_font_tile_to_overlay
|
||||
add r1, 8
|
||||
loop clear_menu_bar_loop
|
||||
|
||||
pop r31
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
|
||||
; draw root menu bar items
|
||||
; inputs:
|
||||
; r0: pointer to menu bar root struct
|
||||
; r1: selected root menu item (or 0xFFFFFFFF for none)
|
||||
; outputs:
|
||||
; none
|
||||
draw_menu_bar_root_items:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
push r29
|
||||
push r30
|
||||
push r31
|
||||
|
||||
movz.8 r31, [r0] ; load number of root menu items into r31 for looping
|
||||
mov r30, r1 ; r30: number of the selected item
|
||||
mov r29, 0 ; counter of how many menu items drawn so far
|
||||
mov r6, r0
|
||||
add r6, 5 ; point to start of root menu items text pointer
|
||||
mov r1, 16 ; X = 16
|
||||
mov r2, 0 ; Y = 0
|
||||
mov r5, 30 ; overlay 30
|
||||
draw_menu_bar_root_items_loop:
|
||||
cmp r30, r29
|
||||
ifz mov r3, 0xFFFFFFFF ; foreground color: white
|
||||
ifz mov r4, 0xFF000000 ; background color: black
|
||||
ifnz mov r3, 0xFF000000 ; foreground color: black
|
||||
ifnz mov r4, 0xFFFFFFFF ; background color: white
|
||||
|
||||
; draw colored space before text
|
||||
sub r1, 8
|
||||
movz.8 r0, ' '
|
||||
call draw_font_tile_to_overlay
|
||||
add r1, 8
|
||||
|
||||
mov r0, [r6] ; get pointer to text
|
||||
inc r0 ; increment past length byte
|
||||
call draw_str_to_overlay ; draw menu item text
|
||||
|
||||
; draw colored space after text
|
||||
movz.8 r0, ' '
|
||||
call draw_font_tile_to_overlay
|
||||
|
||||
add r1, 16 ; add some space next to this menu item
|
||||
add r6, 8 ; increment pointer to text pointer
|
||||
inc r29
|
||||
loop draw_menu_bar_root_items_loop
|
||||
|
||||
pop r31
|
||||
pop r30
|
||||
pop r29
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; handle menu bar click
|
||||
; inputs:
|
||||
; r0: pointer to menu bar root struct
|
||||
; r1: X position where the menu bar was clicked
|
||||
; outputs:
|
||||
; none
|
||||
menu_bar_click_event:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r28
|
||||
push r29
|
||||
push r30
|
||||
push r31
|
||||
|
||||
; move the X coordinate to r3
|
||||
mov r3, r1
|
||||
push r0
|
||||
; the user might've clicked on a root menu item, check to see if they did and what button they clicked
|
||||
movz.8 r31, [r0] ; load number of root menu items into r31 for looping
|
||||
mov r30, 0 ; use r30 as an incrementing counter of menu item lengths calculated so far
|
||||
mov r29, 16 ; use r29 as the starting X coord of the current menu item
|
||||
;mov r28, 0 ; use r28 as the ending X coord of the current menu item
|
||||
mov r4, r0
|
||||
add r4, 5 ; point to start of root menu items text pointer
|
||||
menu_bar_click_event_loop:
|
||||
mov r0, [r4] ; get pointer to text
|
||||
movz.8 r1, [r0] ; get length byte
|
||||
mul r1, 8 ; calculate the length in pixels
|
||||
mov r28, r1
|
||||
add r28, r29 ; use r28 as the ending X coord of the current menu item
|
||||
mov r2, r1
|
||||
; now we need to check if the mouse's X coord is between the values of r29 and r28
|
||||
; if carry flag is set, value is less than
|
||||
; if carry flag is clear, value is greater than or equal to
|
||||
mov r1, r3
|
||||
; this is a trick to check if a value is within a certain range
|
||||
; see https://stackoverflow.com/questions/5196527/double-condition-checking-in-assembly for info
|
||||
sub r1, r29
|
||||
sub r28, r29
|
||||
cmp r28, r1
|
||||
ifnc jmp menu_bar_click_event_found_item
|
||||
inc r30 ; increment counter of menu item lengths calculated so far
|
||||
add r29, r2 ; add the size in pixels of the current root menu item to the counter
|
||||
add r29, 16 ; add 16 pixels to account for the space between the menu items
|
||||
add r4, 8 ; increment pointer to text pointer
|
||||
loop menu_bar_click_event_loop
|
||||
; if we reach this point, then the user didn't click on any root menu items
|
||||
; redraw the root menu items without anything selected
|
||||
pop r0
|
||||
;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
|
||||
menu_bar_click_event_found_item:
|
||||
; r30 contains the clicked root menu item (starting at 0)
|
||||
pop r0
|
||||
mov r1, r30
|
||||
mov r2, 0xFFFFFFFF
|
||||
call draw_menu_bar_root_items
|
||||
call draw_submenu_items
|
||||
|
||||
; push a submenu_update_event_type event to the event stack
|
||||
mov r1, r0 ; event parameter 0: pointer to menu bar root struct
|
||||
mov r2, r30 ; event parameter 1: selected root menu item
|
||||
mov r3, 0xFFFFFFFF ; event parameter 2: hovering submenu item (or 0xFFFFFFFF for none)
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r0, submenu_update_event_type
|
||||
call push_event
|
||||
|
||||
pop r31
|
||||
pop r30
|
||||
pop r29
|
||||
pop r28
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
;menu_items_root:
|
||||
; def.8 3 ; number of submenus
|
||||
; def.32 menu_items_file_list def.32 menu_items_file_name ; pointer to submenu list, pointer to submenu name
|
||||
; def.32 menu_items_edit_list def.32 menu_items_edit_name ; pointer to submenu list, pointer to submenu name
|
||||
; def.32 menu_items_system_list def.32 menu_items_system_name ; pointer to submenu list, pointer to submenu name
|
||||
;menu_items_file_name:
|
||||
; def.8 4 def.str "File" def.8 0x00 ; text length, text, null-terminator
|
||||
;menu_items_file_list:
|
||||
; def.8 2 ; number of items
|
||||
; def.8 6 ; submenu width (in number of characters)
|
||||
; def.8 6 def.str "Test 1" def.8 0x00 ; text length, text, null-terminator
|
||||
; def.8 6 def.str "Test 2" def.8 0x00 ; text length, text, null-terminator
|
||||
;menu_items_edit_name:
|
||||
; def.8 4 def.str "Edit" def.8 0x00 ; text length, text, null-terminator
|
||||
;menu_items_edit_list:
|
||||
; def.8 2 ; number of items
|
||||
; def.8 6 ; submenu width (in number of characters)
|
||||
; def.8 6 def.str "Test 3" def.8 0x00 ; text length, text, null-terminator
|
||||
; def.8 6 def.str "Test 4" def.8 0x00 ; text length, text, null-terminator
|
||||
;menu_items_system_name:
|
||||
; def.8 6 def.str "System" def.8 0x00 ; text length, text, null-terminator
|
||||
;menu_items_system_list:
|
||||
; def.8 4 ; number of items
|
||||
; def.8 6 ; submenu width (in number of characters)
|
||||
; def.8 6 def.str "Test 5" def.8 0x00 ; text length, text, null-terminator
|
||||
; def.8 6 def.str "Test 6" def.8 0x00 ; text length, text, null-terminator
|
||||
; def.8 6 def.str "Test 7" def.8 0x00 ; text length, text, null-terminator
|
||||
; def.8 6 def.str "Test 8" def.8 0x00 ; text length, text, null-terminator
|
95
mouse.asm
Normal file
95
mouse.asm
Normal file
|
@ -0,0 +1,95 @@
|
|||
; mouse routines
|
||||
|
||||
; gets the current position of the mouse cursor
|
||||
; this gets the position of the cursor overlay, rather than actually getting the mouse position
|
||||
; inputs:
|
||||
; none
|
||||
; outputs:
|
||||
; r0: X coordinate
|
||||
; r1: Y coordinate
|
||||
get_mouse_position:
|
||||
in r0, 0x0200001F ; overlay 31: position
|
||||
mov r1, r0
|
||||
and r0, 0x0000FFFF ; r0: overlay X position
|
||||
sra r1, 16 ; r1: overlay Y position
|
||||
|
||||
ret
|
||||
|
||||
; gets the current state of the mouse button
|
||||
; inputs:
|
||||
; none
|
||||
; outputs:
|
||||
; r0: button state
|
||||
get_mouse_button:
|
||||
in r0, 0x02000400 ; mouse button states
|
||||
|
||||
ret
|
||||
|
||||
; updates the cursor position and pushes a mouse_click_event_type event to the event stack if the mouse button was clicked
|
||||
; this should only be called by system_vsync_handler
|
||||
mouse_update:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
|
||||
mov r0, 0x0200001F ; overlay 31: position
|
||||
in r2, 0x02000401 ; mouse position
|
||||
out r0, r2
|
||||
|
||||
movz.16 r0, r2 ; r0: X position
|
||||
mov r1, r2
|
||||
sra r1, 16 ; r1: Y position
|
||||
|
||||
mov r2, 0x02000400 ; mouse button states
|
||||
in r3, r2
|
||||
|
||||
; check click bit
|
||||
bts r3, 0
|
||||
ifz jmp mouse_update_end
|
||||
; mouse was clicked
|
||||
out r2, 0 ; clear all button state bits
|
||||
|
||||
; check if the mouse was clicked in the menu bar
|
||||
;mov r2, 30
|
||||
;call overlay_check_if_enabled_covers_position
|
||||
;ifz jmp mouse_update_menu_was_clicked
|
||||
|
||||
; if Y <= 16, mouse was clicked in the menu bar
|
||||
; this is less expensive than calling overlay_check_if_enabled_covers_position every frame
|
||||
cmp r1, 17
|
||||
ifc jmp mouse_update_menu_was_clicked
|
||||
|
||||
; if a submenu is open, don't push a click event
|
||||
; this is hacky as fuck
|
||||
in r3, 0x0200031D ; overlay 29: enable status
|
||||
cmp r3, 0
|
||||
ifnz jmp mouse_update_end
|
||||
|
||||
; otherwise, just push a standard mouse click event to the event stack
|
||||
mov r2, r1 ; copy Y position to event parameter 1
|
||||
mov r1, r0 ; copy X position to event parameter 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r0, mouse_click_event_type ; set event type to mouse type
|
||||
call push_event
|
||||
jmp mouse_update_end
|
||||
mouse_update_menu_was_clicked:
|
||||
mov r2, r1 ; copy Y position to event parameter 1
|
||||
mov r1, r0 ; copy X position to event parameter 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r0, menu_bar_click_event_type ; set event type to menu bar click type
|
||||
call push_event
|
||||
mouse_update_end:
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
357
overlay.asm
Normal file
357
overlay.asm
Normal file
|
@ -0,0 +1,357 @@
|
|||
; overlay routines
|
||||
|
||||
; fill a whole overlay with a color
|
||||
; inputs:
|
||||
; r0: color
|
||||
; r1: overlay number
|
||||
; outputs:
|
||||
; none
|
||||
fill_overlay:
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r31
|
||||
|
||||
mov r2, r1
|
||||
or r2, 0x02000100 ; bitwise or the overlay number with the command to get the overlay size
|
||||
or r1, 0x02000200 ; bitwise or the overlay number with the command to get the framebuffer pointer
|
||||
in r1, r1 ; r1: overlay framebuffer poiner
|
||||
in r2, r2
|
||||
mov r3, r2
|
||||
and r2, 0x0000FFFF ; r2: X size
|
||||
sra r3, 16 ; r3: Y size
|
||||
mul r2, r3
|
||||
mov r31, r2
|
||||
fill_overlay_loop:
|
||||
mov [r1], r0
|
||||
add r1, 4
|
||||
loop fill_overlay_loop
|
||||
|
||||
pop r31
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
ret
|
||||
|
||||
; draw a filled rectangle to an overlay
|
||||
; inputs:
|
||||
; r0: X coordinate of top-left
|
||||
; r1: Y coordinate of top-left
|
||||
; r2: X size
|
||||
; r3: Y size
|
||||
; r4: color
|
||||
; r5: overlay number
|
||||
; outputs:
|
||||
; none
|
||||
draw_filled_rectangle_to_overlay:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
|
||||
; calculate pointer to the framebuffer
|
||||
mov r6, r5 ; r6: overlay number
|
||||
or r6, 0x02000100 ; bitwise or the overlay number with the command to get the overlay size
|
||||
in r7, r6
|
||||
and r7, 0x0000FFFF ; mask off the height, we only need the width
|
||||
mul r7, 4 ; r7: overlay width in bytes (width * 4)
|
||||
mul r1, r7 ; y * width * 4
|
||||
mul r0, 4 ; x * 4
|
||||
add r0, r1 ; y * width * 4 + (x * 4)
|
||||
or r5, 0x02000200 ; bitwise or the overlay number with the command to get the framebuffer pointer
|
||||
in r5, r5
|
||||
add r0, r5 ; r0: pointer to framebuffer
|
||||
|
||||
mov r6, r2
|
||||
mul r6, 4 ; multiply the X size by 4, since 4 bytes per pixel
|
||||
|
||||
draw_filled_rectangle_to_overlay_y_loop:
|
||||
mov r5, r2 ; x counter
|
||||
draw_filled_rectangle_to_overlay_x_loop:
|
||||
mov [r0], r4
|
||||
add r0, 4 ; increment framebuffer pointer
|
||||
dec r5
|
||||
ifnz jmp draw_filled_rectangle_to_overlay_x_loop ; loop if there are still more X pixels to draw
|
||||
|
||||
sub r0, r6 ; return to the beginning of this line
|
||||
add r0, r7 ; increment to the next line
|
||||
dec r3
|
||||
ifnz jmp draw_filled_rectangle_to_overlay_y_loop ; loop if there are still more Y pixels to draw
|
||||
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; draw a single font tile to an overlay
|
||||
; inputs:
|
||||
; r0: tile number
|
||||
; r1: X coordinate
|
||||
; r2: Y coordinate
|
||||
; r3: foreground color
|
||||
; r4: background color
|
||||
; r5: overlay number
|
||||
; outputs:
|
||||
; none
|
||||
draw_font_tile_to_overlay:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
|
||||
;movz.8 r0, r0 ; ensure the tile number is a single byte
|
||||
|
||||
; calculate pointer to the tile data
|
||||
push r1
|
||||
push r2
|
||||
mov r1, 8 ; tile width
|
||||
mov r2, 16 ; tile height
|
||||
mul r1, r2
|
||||
mul r0, r1
|
||||
mul r0, 4 ; 4 bytes per pixel
|
||||
add r0, font ; r0: pointer to tile data
|
||||
pop r2
|
||||
pop r1
|
||||
|
||||
; calculate pointer to the framebuffer
|
||||
mov r7, r5 ; r7: overlay number
|
||||
or r7, 0x02000100 ; bitwise or the overlay number with the command to get the overlay size
|
||||
in r6, r7
|
||||
and r6, 0x0000FFFF ; mask off the height, we only need the width
|
||||
mul r6, 4 ; 4 bytes per pixel
|
||||
mov r7, r6 ; r7: overlay width in bytes (width * 4)
|
||||
mul r2, r7 ; y * width * 4
|
||||
mul r1, 4 ; x * 4
|
||||
add r1, r2 ; y * width * 4 + (x * 4)
|
||||
or r5, 0x02000200 ; bitwise or the overlay number with the command to get the framebuffer pointer
|
||||
in r6, r5
|
||||
add r1, r6 ; r1: pointer to framebuffer
|
||||
|
||||
mov r6, 16 ; y counter
|
||||
draw_font_tile_to_overlay_y_loop:
|
||||
mov r5, 8 ; x counter
|
||||
draw_font_tile_to_overlay_x_loop:
|
||||
mov r2, [r0]
|
||||
cmp r2, 0xFF000000
|
||||
ifz jmp draw_font_tile_to_overlay_x_loop_background
|
||||
; drawing foreground pixel
|
||||
cmp r3, 0x00000000 ; is the foreground color supposed to be transparent?
|
||||
ifz jmp draw_font_tile_to_overlay_x_loop_end
|
||||
mov [r1], r3 ; draw foreground color
|
||||
jmp draw_font_tile_to_overlay_x_loop_end
|
||||
draw_font_tile_to_overlay_x_loop_background:
|
||||
; drawing background pixel
|
||||
cmp r4, 0x00000000 ; is the background color supposed to be transparent?
|
||||
ifz jmp draw_font_tile_to_background_x_loop_end
|
||||
mov [r1], r4 ; draw background color
|
||||
draw_font_tile_to_overlay_x_loop_end:
|
||||
add r0, 4 ; increment tile pointer
|
||||
add r1, 4 ; increment framebuffer pointer
|
||||
dec r5
|
||||
ifnz jmp draw_font_tile_to_overlay_x_loop ; loop if there are still more X pixels to draw
|
||||
sub r1, 32 ; 8*4, return to the beginning of this line
|
||||
add r1, r7 ; increment to the next line by adding the overlay width in bytes
|
||||
dec r6
|
||||
ifnz jmp draw_font_tile_to_overlay_y_loop ; loop if there are still more Y pixels to draw
|
||||
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; draw text on an overlay
|
||||
; inputs:
|
||||
; r0: pointer to null-terminated string
|
||||
; r1: X coordinate
|
||||
; r2: Y coordinate
|
||||
; r3: foreground color
|
||||
; r4: background color
|
||||
; r5: overlay number
|
||||
; outputs:
|
||||
; r1: X coordinate of end of text
|
||||
draw_str_to_overlay:
|
||||
push r0
|
||||
push r6
|
||||
mov r6, r0
|
||||
draw_str_to_overlay_loop:
|
||||
movz.8 r0, [r6]
|
||||
call draw_font_tile_to_overlay
|
||||
inc r6
|
||||
add r1, 8
|
||||
cmp.8 [r6], 0x00
|
||||
ifnz jmp draw_str_to_overlay_loop
|
||||
pop r6
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; finds the overlay with the highest priority covering the specified position
|
||||
; does not check overlay 31, which is always the mouse pointer
|
||||
; inputs:
|
||||
; r0: X coordinate
|
||||
; r1: Y coordinate
|
||||
; outputs:
|
||||
; r0: overlay number
|
||||
find_overlay_covering_position:
|
||||
; TODO:
|
||||
|
||||
; checks if the specified overlay is covering the specified position on screen
|
||||
; the overlay can be enabled or disabled
|
||||
; example:
|
||||
; overlay 0 is at (0,0) and is 32x32 in size
|
||||
; point (4,2) is covered by overlay 0
|
||||
; point (16,16) is covered by overlay 0
|
||||
; point (31,31) is covered by overlay 0
|
||||
; point (32,32) is NOT covered by overlay 0, because it is outside of the overlay's area
|
||||
; this works for overlays of any size, at any position on screen
|
||||
; inputs:
|
||||
; r0: X coordinate
|
||||
; r1: Y coordinate
|
||||
; r2: overlay number
|
||||
; outputs:
|
||||
; Z flag: set if covering, clear if not covering
|
||||
check_if_overlay_covers_position:
|
||||
push r0
|
||||
push r1
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
|
||||
mov r3, r2
|
||||
or r3, 0x02000000 ; bitwise or the overlay number with the command to get the overlay position
|
||||
in r4, r3
|
||||
mov r5, r4
|
||||
and r4, 0x0000FFFF ; r4: X position
|
||||
sra r5, 16 ; r5: Y position
|
||||
|
||||
mov r3, r2
|
||||
or r3, 0x02000100 ; bitwise or the overlay number with the command to get the overlay size
|
||||
in r6, r3
|
||||
mov r7, r6
|
||||
and r6, 0x0000FFFF ; r6: width
|
||||
sra r7, 16 ; r7: height
|
||||
|
||||
add r6, r4
|
||||
add r7, r5
|
||||
|
||||
; (r4,r5): coordinates of top-left of the overlay
|
||||
; (r6,r7): coordinates of bottom-right of the overlay
|
||||
|
||||
; now we need to check if:
|
||||
; - (r4,r5) is greater than or equal to (r0,r1)
|
||||
; and
|
||||
; - (r6,r7) is less than or equal to (r0,r1)
|
||||
|
||||
; if carry flag is set, value is less than
|
||||
; if carry flag is clear, value is greater than or equal to
|
||||
cmp r0, r4
|
||||
ifc jmp check_if_overlay_covers_position_fail
|
||||
cmp r0, r6
|
||||
ifnc jmp check_if_overlay_covers_position_fail
|
||||
|
||||
cmp r1, r5
|
||||
ifc jmp check_if_overlay_covers_position_fail
|
||||
cmp r1, r7
|
||||
ifnc jmp check_if_overlay_covers_position_fail
|
||||
|
||||
; if we reached this point then the point is within the bounds of the overlay !!!
|
||||
|
||||
mov.8 r0, 0
|
||||
cmp.8 r0, 0 ; set Z flag
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
check_if_overlay_covers_position_fail:
|
||||
mov.8 r0, 1
|
||||
cmp.8 r0, 0 ; clear Z flag
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; checks if the specified overlay is covering the specified position on screen
|
||||
; the overlay must be enabled
|
||||
; example:
|
||||
; overlay 0 is at (0,0) and is 32x32 in size
|
||||
; point (4,2) is covered by overlay 0
|
||||
; point (16,16) is covered by overlay 0
|
||||
; point (31,31) is covered by overlay 0
|
||||
; point (32,32) is NOT covered by overlay 0, because it is outside of the overlay's area
|
||||
; this works for overlays of any size, at any position on screen
|
||||
; inputs:
|
||||
; r0: X coordinate
|
||||
; r1: Y coordinate
|
||||
; r2: overlay number
|
||||
; outputs:
|
||||
; Z flag: set if covering, clear if not covering
|
||||
check_if_enabled_overlay_covers_position:
|
||||
push r3
|
||||
push r4
|
||||
|
||||
mov r3, r2
|
||||
or r3, 0x02000300 ; bitwise or the overlay number with the command to get the overlay enable status
|
||||
in r4, r3
|
||||
|
||||
cmp r4, 0
|
||||
pop r4
|
||||
pop r3
|
||||
ifnz jmp check_if_enabled_overlay_covers_position_is_enabled
|
||||
cmp r4, 1 ; r4 is known to be zero at this point, so compare it with 1 to clear the Z flag
|
||||
ret
|
||||
check_if_enabled_overlay_covers_position_is_enabled:
|
||||
call check_if_overlay_covers_position
|
||||
ret
|
||||
|
||||
; converts coordinates to be relative to the position of the specified overlay
|
||||
; the overlay can be enabled or disabled
|
||||
; example:
|
||||
; overlay is at (16,16)
|
||||
; (20,20) is specified
|
||||
; (4,4) will be returned
|
||||
; inputs:
|
||||
; r0: X coordinate
|
||||
; r1: Y coordinate
|
||||
; r2: overlay number
|
||||
; outputs:
|
||||
; r0: relative X coordinate
|
||||
; r1: relative Y coordinate
|
||||
make_coordinates_relative_to_overlay:
|
||||
push r2
|
||||
push r3
|
||||
|
||||
or r2, 0x02000000 ; bitwise or the overlay number with the command to get the overlay position
|
||||
in r2, r2
|
||||
mov r3, r2
|
||||
and r2, 0x0000FFFF ; r2: overlay X position
|
||||
sra r3, 16 ; r3: overlay Y position
|
||||
|
||||
sub r0, r2
|
||||
sub r1, r3
|
||||
|
||||
pop r3
|
||||
pop r2
|
||||
ret
|
245
rom.asm
Normal file
245
rom.asm
Normal file
|
@ -0,0 +1,245 @@
|
|||
; entry point
|
||||
; fox32 starts here on reset
|
||||
org 0xF0000000
|
||||
|
||||
const system_stack: 0x01FFF800
|
||||
const background_color: 0xFF414C50
|
||||
|
||||
; initialization code
|
||||
entry:
|
||||
mov rsp, system_stack
|
||||
mov [event_stack_pointer], event_stack
|
||||
|
||||
mov [0x000003FC], system_vsync_handler
|
||||
|
||||
; disable all overlays
|
||||
mov r31, 0x1F
|
||||
mov r0, 0x02000300
|
||||
disable_all_overlays_loop:
|
||||
out r0, 0
|
||||
inc r0
|
||||
loop disable_all_overlays_loop
|
||||
|
||||
; write the cursor bitmap to the overlay framebuffer
|
||||
mov r0, [overlay_31_framebuffer_ptr]
|
||||
mov r1, mouse_cursor
|
||||
mov r31, 96 ; 8x12
|
||||
cursor_overlay_loop:
|
||||
mov [r0], [r1]
|
||||
add r0, 4
|
||||
add r1, 4
|
||||
loop cursor_overlay_loop
|
||||
|
||||
cursor_enable:
|
||||
; set properties of overlay 31
|
||||
mov r0, 0x0200011F ; overlay 31: size
|
||||
mov.16 r1, [overlay_31_height]
|
||||
sla r1, 16
|
||||
mov.16 r1, [overlay_31_width]
|
||||
out r0, r1
|
||||
mov r0, 0x0200021F ; overlay 31: framebuffer pointer
|
||||
mov r1, [overlay_31_framebuffer_ptr]
|
||||
out r0, r1
|
||||
|
||||
; enable overlay 31 (cursor)
|
||||
mov r0, 0x0200031F
|
||||
out r0, 1
|
||||
|
||||
mov r0, background_color
|
||||
call fill_background
|
||||
|
||||
menu_bar_enable:
|
||||
; set properties of overlay 30
|
||||
mov r0, 0x0200001E ; overlay 30: position
|
||||
mov.16 r1, [overlay_30_position_y]
|
||||
sla r1, 16
|
||||
mov.16 r1, [overlay_30_position_x]
|
||||
out r0, r1
|
||||
mov r0, 0x0200011E ; overlay 30: size
|
||||
mov.16 r1, [overlay_30_height]
|
||||
sla r1, 16
|
||||
mov.16 r1, [overlay_30_width]
|
||||
out r0, r1
|
||||
mov r0, 0x0200021E ; overlay 30: framebuffer pointer
|
||||
mov r1, [overlay_30_framebuffer_ptr]
|
||||
out r0, r1
|
||||
|
||||
; enable overlay 30 (menu bar)
|
||||
mov r0, 0x0200031E
|
||||
out r0, 1
|
||||
|
||||
call clear_menu_bar
|
||||
mov r0, menu_items_root
|
||||
mov r1, 0xFFFFFFFF
|
||||
call draw_menu_bar_root_items
|
||||
|
||||
draw_startup_text:
|
||||
mov r0, 252
|
||||
mov r1, 229
|
||||
mov r2, 136
|
||||
mov r3, 40
|
||||
mov r4, 0xFF505C60
|
||||
;mov r4, 0xFFFFFFFF
|
||||
call draw_filled_rectangle_to_background
|
||||
mov r0, 253
|
||||
mov r1, 230
|
||||
mov r2, 134
|
||||
mov r3, 38
|
||||
mov r4, 0xFFFFFFFF
|
||||
;mov r4, 0xFF000000
|
||||
call draw_filled_rectangle_to_background
|
||||
mov r0, 254
|
||||
mov r1, 231
|
||||
mov r2, 132
|
||||
mov r3, 36
|
||||
mov r4, 0xFF505C60
|
||||
;mov r4, 0xFFFFFFFF
|
||||
call draw_filled_rectangle_to_background
|
||||
|
||||
mov r0, startup_str_1
|
||||
mov r1, 256
|
||||
mov r2, 232
|
||||
mov r3, 0xFFFFFFFF
|
||||
mov r4, 0x00000000
|
||||
call draw_str_to_background
|
||||
|
||||
mov r0, startup_str_2
|
||||
mov r1, 256
|
||||
mov r2, 248
|
||||
call draw_str_to_background
|
||||
|
||||
ise
|
||||
event_loop:
|
||||
call wait_for_event
|
||||
|
||||
; was the mouse clicked?
|
||||
cmp r0, mouse_click_event_type
|
||||
;ifz call mouse_click_event
|
||||
|
||||
; did the user click the menu bar?
|
||||
cmp r0, menu_bar_click_event_type
|
||||
ifz mov r0, menu_items_root
|
||||
ifz call menu_bar_click_event
|
||||
|
||||
; is the user in a submenu?
|
||||
cmp r0, submenu_update_event_type
|
||||
ifz call submenu_update_event
|
||||
|
||||
; did the user click a submenu item?
|
||||
cmp r0, submenu_click_event_type
|
||||
ifz call submenu_click_event
|
||||
|
||||
jmp event_loop
|
||||
|
||||
submenu_click_event:
|
||||
; r3 contains the clicked submenu item
|
||||
|
||||
; about
|
||||
cmp r3, 0
|
||||
;
|
||||
|
||||
; halt
|
||||
cmp r3, 3
|
||||
ifz icl
|
||||
ifz halt
|
||||
|
||||
ret
|
||||
|
||||
; code
|
||||
#include "background.asm"
|
||||
#include "overlay.asm"
|
||||
#include "menu.asm"
|
||||
#include "submenu.asm"
|
||||
#include "event.asm"
|
||||
#include "mouse.asm"
|
||||
#include "vsync.asm"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; data
|
||||
|
||||
; system jump table
|
||||
org.pad 0xF1000000
|
||||
def.32 system_vsync_handler
|
||||
def.32 get_mouse_position
|
||||
def.32 push_event
|
||||
def.32 wait_for_event
|
||||
|
||||
; background jump table
|
||||
org.pad 0xF1001000
|
||||
def.32 draw_str_to_background
|
||||
def.32 draw_font_tile_to_background
|
||||
def.32 fill_background
|
||||
|
||||
; overlay jump table
|
||||
org.pad 0xF1002000
|
||||
def.32 draw_str_to_overlay
|
||||
def.32 draw_font_tile_to_overlay
|
||||
def.32 fill_overlay
|
||||
def.32 find_overlay_covering_position
|
||||
def.32 check_if_overlay_covers_position
|
||||
def.32 check_if_enabled_overlay_covers_position
|
||||
|
||||
; menu bar jump table
|
||||
org.pad 0xF1003000
|
||||
def.32 menu_bar_click_event
|
||||
def.32 clear_menu_bar
|
||||
def.32 draw_menu_bar_root_items
|
||||
def.32 draw_submenu_items
|
||||
def.32 close_submenu
|
||||
|
||||
org.pad 0xF1F00000
|
||||
font:
|
||||
#include "../font/unifont-thin.inc"
|
||||
|
||||
mouse_cursor:
|
||||
#include_bin "../font/cursor2.raw"
|
||||
|
||||
; cursor overlay struct:
|
||||
overlay_31_width: def.16 8
|
||||
overlay_31_height: def.16 12
|
||||
overlay_31_position_x: def.16 0
|
||||
overlay_31_position_y: def.16 0
|
||||
overlay_31_framebuffer_ptr: def.32 0x0212D000
|
||||
|
||||
; menu bar overlay struct:
|
||||
overlay_30_width: def.16 640
|
||||
overlay_30_height: def.16 16
|
||||
overlay_30_position_x: def.16 0
|
||||
overlay_30_position_y: def.16 0
|
||||
overlay_30_framebuffer_ptr: def.32 0x0212D180
|
||||
|
||||
; submenu overlay struct:
|
||||
; this struct must be writable, so these are hard-coded addresses in shared memory
|
||||
const overlay_29_width: 0x02137180 ; 2 bytes
|
||||
const overlay_29_height: 0x02137182 ; 2 bytes
|
||||
const overlay_29_position_x: 0x02137184 ; 2 bytes
|
||||
const overlay_29_position_y: 0x02137186 ; 2 bytes
|
||||
const overlay_29_framebuffer_ptr: 0x0213718A ; 4 bytes
|
||||
const overlay_29_framebuffer: 0x0213718E
|
||||
|
||||
startup_str_1: def.str "Welcome to fox32" def.8 0
|
||||
startup_str_2: def.str "Insert boot disk" def.8 0
|
||||
|
||||
menu_items_root:
|
||||
def.8 1 ; number of submenus
|
||||
def.32 menu_items_system_list def.32 menu_items_system_name ; pointer to submenu list, pointer to submenu name
|
||||
menu_items_system_name:
|
||||
def.8 6 def.str "System" def.8 0x00 ; text length, text, null-terminator
|
||||
menu_items_system_list:
|
||||
def.8 4 ; number of items
|
||||
def.8 22 ; submenu width (usually longest item + 2)
|
||||
def.8 5 def.str "About" def.8 0x00 ; text length, text, null-terminator
|
||||
def.8 20 def.str "Mount Floppy Disk..." def.8 0x00 ; text length, text, null-terminator
|
||||
def.8 18 def.str "Mount Hard Disk..." def.8 0x00 ; text length, text, null-terminator
|
||||
def.8 4 def.str "Halt" def.8 0x00 ; text length, text, null-terminator
|
||||
|
||||
; pad out to 32 MiB
|
||||
org.pad 0xF2000000
|
||||
|
||||
; TODO: ideas:
|
||||
; rectangle drawing routine
|
||||
; fill background/overlay routine
|
||||
; seperators in submenus
|
34
rom.def
Normal file
34
rom.def
Normal file
|
@ -0,0 +1,34 @@
|
|||
; fox32 rom routine definitions
|
||||
|
||||
; system jump table entries
|
||||
system_vsync_handler: jmp [0xF1000000]
|
||||
get_mouse_position: jmp [0xF1000004]
|
||||
push_event: jmp [0xF1000008]
|
||||
wait_for_event: jmp [0xF100000C]
|
||||
|
||||
; background jump table entries
|
||||
draw_str_to_background: jmp [0xF1001000]
|
||||
draw_font_tile_to_background: jmp [0xF1001004]
|
||||
fill_background: jmp [0xF1001008]
|
||||
|
||||
; overlay jump table entries
|
||||
draw_str_to_overlay: jmp [0xF1002000]
|
||||
draw_font_tile_to_overlay: jmp [0xF1002004]
|
||||
fill_overlay: jmp [0xF1002008]
|
||||
find_overlay_covering_position: jmp [0xF100200C]
|
||||
check_if_overlay_covers_position: jmp [0xF1002010]
|
||||
check_if_enabled_overlay_covers_position: jmp [0xF1002014]
|
||||
|
||||
; menu bar jump table entries
|
||||
menu_bar_click_event: jmp [0xF1003000]
|
||||
clear_menu_bar: jmp [0xF1003004]
|
||||
draw_menu_bar_root_items: jmp [0xF1003008]
|
||||
draw_submenu_items: jmp [0xF100300C]
|
||||
close_submenu: jmp [0xF1003010]
|
||||
|
||||
; event types
|
||||
const mouse_click_event_type: 0x00000000
|
||||
const menu_bar_click_event_type: 0x00000001
|
||||
const submenu_update_event_type: 0x00000002
|
||||
const submenu_click_event_type: 0x00000003
|
||||
const empty_event_type: 0xFFFFFFFF
|
255
submenu.asm
Normal file
255
submenu.asm
Normal file
|
@ -0,0 +1,255 @@
|
|||
; submenu routines
|
||||
|
||||
; draw submenu items
|
||||
; inputs:
|
||||
; r0: pointer to menu bar root struct
|
||||
; r1: selected root menu item
|
||||
; r2: hovering submenu item (or 0xFFFFFFFF for none)
|
||||
; outputs:
|
||||
; none
|
||||
draw_submenu_items:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
push r8
|
||||
push r29
|
||||
push r30
|
||||
push r31
|
||||
|
||||
; calculate the X position of the submenu
|
||||
mov r31, r1 ; load number of the selected item into r31 for looping
|
||||
mov r30, 16 ; X counter
|
||||
cmp r31, 0 ; we don't need to loop if this is submenu 0
|
||||
ifz jmp draw_submenu_items_calculate_x_skip
|
||||
mov r4, r0
|
||||
add r4, 5 ; point to start of root menu items text pointer
|
||||
draw_submenu_items_calculate_x_loop:
|
||||
mov r3, [r4] ; get pointer to text
|
||||
movz.8 r3, [r3] ; get text length byte
|
||||
add r3, 2 ; add 2 for the spaces on each side of the text
|
||||
mul r3, 8 ; characters are 8 pixels wide
|
||||
add r30, r3 ; add length to X counter
|
||||
add r4, 8 ; point to next text pointer
|
||||
loop draw_submenu_items_calculate_x_loop
|
||||
draw_submenu_items_calculate_x_skip:
|
||||
sub r30, 8 ; move the submenu to the left by 8 pixels
|
||||
mov.16 [overlay_29_position_x], r30
|
||||
|
||||
mov r31, r0
|
||||
inc r31 ; point to submenu list pointer
|
||||
mul r1, 8 ; point to the selected submenu
|
||||
add r31, r1
|
||||
mov r0, [r31] ; load submenu list pointer
|
||||
movz.8 r31, [r0] ; load number of submenu items
|
||||
mov r30, r2 ; r30: number of the hovered item
|
||||
mov r29, 0 ; counter of how many submenu items drawn so far
|
||||
|
||||
; calculate the required height for the submenu overlay
|
||||
; multiply the number of submenu items by 16 (the font is 16 pixels tall)
|
||||
mov r1, r31
|
||||
mul r1, 16
|
||||
mov.16 [overlay_29_height], r1
|
||||
|
||||
; calculate the required width for the submenu overlay
|
||||
; multiply the width by 8 (the font is 8 pixels wide)
|
||||
mov r1, r0
|
||||
inc r1
|
||||
movz.8 r1, [r1] ; load width of submenu
|
||||
mov r8, r1 ; save the width in characters in r8 for later
|
||||
mul r1, 8
|
||||
mov.16 [overlay_29_width], r1
|
||||
|
||||
push r0
|
||||
|
||||
; set properties of overlay 29
|
||||
mov.16 [overlay_29_position_y], 16
|
||||
mov [overlay_29_framebuffer_ptr], overlay_29_framebuffer
|
||||
mov r0, 0x0200001D ; overlay 29: position
|
||||
mov.16 r1, [overlay_29_position_y]
|
||||
sla r1, 16
|
||||
mov.16 r1, [overlay_29_position_x]
|
||||
out r0, r1
|
||||
mov r0, 0x0200011D ; overlay 29: size
|
||||
mov.16 r1, [overlay_29_height]
|
||||
sla r1, 16
|
||||
mov.16 r1, [overlay_29_width]
|
||||
out r0, r1
|
||||
mov r0, 0x0200021D ; overlay 29: framebuffer pointer
|
||||
mov r1, [overlay_29_framebuffer_ptr]
|
||||
out r0, r1
|
||||
mov r0, 0x0200031D
|
||||
out r0, 1
|
||||
|
||||
; draw empty submenu
|
||||
mov r6, r31 ; outer loop counter
|
||||
movz.8 r0, ' '
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0xFF000000
|
||||
mov r4, 0xFFFFFFFF
|
||||
mov r5, 29
|
||||
draw_empty_submenu_loop:
|
||||
mov r7, r8 ; inner loop counter
|
||||
cmp r30, r29
|
||||
ifz mov r3, 0xFFFFFFFF ; foreground color: white
|
||||
ifz mov r4, 0xFF000000 ; background color: black
|
||||
ifnz mov r3, 0xFF000000 ; foreground color: black
|
||||
ifnz mov r4, 0xFFFFFFFF ; background color: white
|
||||
draw_empty_submenu_line_loop:
|
||||
call draw_font_tile_to_overlay
|
||||
add r1, 8
|
||||
dec r7
|
||||
ifnz jmp draw_empty_submenu_line_loop
|
||||
mov r1, 0
|
||||
add r2, 16
|
||||
inc r29
|
||||
dec r6
|
||||
ifnz jmp draw_empty_submenu_loop
|
||||
mov r29, 0 ; counter of how many submenu items drawn so far
|
||||
pop r0
|
||||
|
||||
; draw submenu text
|
||||
add r0, 3 ; point to start of submenu items text
|
||||
mov r2, 0 ; Y = 0
|
||||
draw_submenu_text_loop:
|
||||
cmp r30, r29
|
||||
ifz mov r3, 0xFFFFFFFF ; foreground color: white
|
||||
ifz mov r4, 0xFF000000 ; background color: black
|
||||
ifnz mov r3, 0xFF000000 ; foreground color: black
|
||||
ifnz mov r4, 0xFFFFFFFF ; background color: white
|
||||
|
||||
mov r1, 0 ; X = 0
|
||||
call draw_str_to_overlay ; draw submenu item text
|
||||
|
||||
mov r1, r0
|
||||
dec r1 ; point to length byte of this menu item
|
||||
movz.8 r1, [r1] ; load length byte
|
||||
inc r1 ; add one to count the null-terminator
|
||||
add r0, r1 ; add length to menu item text pointer
|
||||
inc r0 ; increment past length byte
|
||||
add r2, 16 ; add 16 to Y
|
||||
inc r29
|
||||
loop draw_submenu_text_loop
|
||||
|
||||
pop r31
|
||||
pop r30
|
||||
pop r29
|
||||
pop r8
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
||||
|
||||
; hide the submenu
|
||||
; inputs:
|
||||
; r0: pointer to menu bar root struct
|
||||
; outputs:
|
||||
; none
|
||||
close_submenu:
|
||||
push r1
|
||||
|
||||
; disable overlay 29
|
||||
mov r1, 0x0200031D
|
||||
out r1, 0
|
||||
|
||||
mov r1, 0xFFFFFFFF
|
||||
call draw_menu_bar_root_items
|
||||
|
||||
pop r1
|
||||
ret
|
||||
|
||||
; update the currently open submenu
|
||||
; detects mouse movements over the submenu and handles clicks
|
||||
; this should only be called if a submenu_update_event_type event is received
|
||||
; inputs:
|
||||
; *** these inputs should already be in the required registers from the event parameters ***
|
||||
; r1: pointer to menu bar root struct
|
||||
; r2: selected root menu item
|
||||
; r3: hovering submenu item (or 0xFFFFFFFF for none)
|
||||
; outputs:
|
||||
; none
|
||||
; the event is pushed back onto the event stack if the submenu is still open
|
||||
submenu_update_event:
|
||||
push r0
|
||||
push r1
|
||||
push r2
|
||||
push r3
|
||||
push r4
|
||||
push r5
|
||||
push r8
|
||||
push r9
|
||||
|
||||
mov r8, r1 ; r8: pointer to menu bar root struct
|
||||
mov r9, r2 ; r9: selected root menu item
|
||||
mov r10, r3 ; r10: hovering submenu item (or 0xFFFFFFFF for none)
|
||||
|
||||
; get the current mouse position and check if the submenu overlay covers that position
|
||||
; if the mouse is not in the submenu, then there is nothing to do
|
||||
call get_mouse_position
|
||||
mov r2, 29
|
||||
call check_if_enabled_overlay_covers_position
|
||||
ifnz jmp submenu_update_event_end_push
|
||||
|
||||
; make the mouse position relative to the submenu overlay
|
||||
mov r2, 29
|
||||
call make_coordinates_relative_to_overlay
|
||||
|
||||
; if the currently hovered item is different than the hovered item in the event parameters,
|
||||
; then redraw the submenu with correct hovered item
|
||||
div r1, 16 ; mouse Y / 16
|
||||
cmp r1, r10 ; compare the currently hovered item to the hovered item in event parameter 2
|
||||
ifz jmp submenu_update_event_no_redraw
|
||||
mov r10, r1 ; set the hovering item to the currently hovering item
|
||||
mov r2, r1
|
||||
mov r1, r9
|
||||
mov r0, r8
|
||||
call draw_submenu_items
|
||||
submenu_update_event_no_redraw:
|
||||
; check the mouse held bit
|
||||
; this is kinda hacky but it works
|
||||
call get_mouse_button
|
||||
bts r0, 1
|
||||
ifnz jmp submenu_update_event_clicked
|
||||
|
||||
jmp submenu_update_event_end_push
|
||||
submenu_update_event_clicked:
|
||||
;div r2, 16 ; mouse Y / 16
|
||||
mov r1, r8 ; event parameter 0: pointer to menu bar root struct
|
||||
mov r2, r9 ; event parameter 1: selected root menu item
|
||||
mov r3, r10 ; event parameter 2: selected submenu item
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r0, submenu_click_event_type
|
||||
call push_event
|
||||
mov r0, r1
|
||||
call close_submenu
|
||||
jmp submenu_update_event_end_no_push
|
||||
submenu_update_event_end_push:
|
||||
; repush the submenu_update_event_type event to the event stack
|
||||
mov r1, r8 ; event parameter 0: pointer to menu bar root struct
|
||||
mov r2, r9 ; event parameter 1: selected root menu item
|
||||
mov r3, r10 ; event parameter 2: hovering submenu item (or 0xFFFFFFFF for none)
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r0, submenu_update_event_type
|
||||
call push_event
|
||||
submenu_update_event_end_no_push:
|
||||
pop r9
|
||||
pop r8
|
||||
pop r5
|
||||
pop r4
|
||||
pop r3
|
||||
pop r2
|
||||
pop r1
|
||||
pop r0
|
||||
ret
|
Loading…
Reference in New Issue
Block a user