diff --git a/event.asm b/event.asm index 0633034..f540e5f 100644 --- a/event.asm +++ b/event.asm @@ -10,8 +10,8 @@ const EVENT_SIZE_WORDS: 8 ; 8 words per event ; 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 MENU_UPDATE_EVENT_TYPE: 0x00000002 +const MENU_CLICK_EVENT_TYPE: 0x00000003 const EMPTY_EVENT_TYPE: 0xFFFFFFFF ; block until an event is available diff --git a/fox32rom.def b/fox32rom.def index 6f3b6dc..1ffa449 100644 --- a/fox32rom.def +++ b/fox32rom.def @@ -32,12 +32,12 @@ check_if_enabled_overlay_covers_position: jmp [0xF0043018] menu_bar_click_event: jmp [0xF0044000] clear_menu_bar: jmp [0xF0044004] draw_menu_bar_root_items: jmp [0xF0044008] -draw_submenu_items: jmp [0xF004400C] -close_submenu: jmp [0xF0044010] +draw_menu_items: jmp [0xF004400C] +close_menu: jmp [0xF0044010] ; 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 MENU_UPDATE_EVENT_TYPE: 0x00000002 +const MENU_CLICK_EVENT_TYPE: 0x00000003 const EMPTY_EVENT_TYPE: 0xFFFFFFFF \ No newline at end of file diff --git a/main.asm b/main.asm index c5bbf37..af77670 100644 --- a/main.asm +++ b/main.asm @@ -124,13 +124,13 @@ event_loop: 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 + ; is the user in a menu? + cmp r0, MENU_UPDATE_EVENT_TYPE + ifz call menu_update_event - ; did the user click a submenu item? - cmp r0, SUBMENU_CLICK_EVENT_TYPE - ifz call submenu_click_event + ; did the user click a menu item? + cmp r0, MENU_CLICK_EVENT_TYPE + ifz call menu_click_event ; check if a disk is mounted as disk 0 ; if port 0x8000100n returns a non-zero value, then a disk is mounted as disk n @@ -140,8 +140,8 @@ event_loop: jmp event_loop -submenu_click_event: - ; r3 contains the clicked submenu item +menu_click_event: + ; r3 contains the clicked menu item ; about cmp r3, 0 @@ -178,9 +178,9 @@ get_rom_version: #include "event.asm" #include "memory.asm" #include "menu.asm" + #include "menu_bar.asm" #include "mouse.asm" #include "overlay.asm" - #include "submenu.asm" #include "vsync.asm" @@ -226,8 +226,8 @@ get_rom_version: data.32 menu_bar_click_event data.32 clear_menu_bar data.32 draw_menu_bar_root_items - data.32 draw_submenu_items - data.32 close_submenu + data.32 draw_menu_items + data.32 close_menu org.pad 0xF004F000 standard_font_width: @@ -254,7 +254,7 @@ overlay_30_position_x: data.16 0 overlay_30_position_y: data.16 0 overlay_30_framebuffer_ptr: data.32 0x8012D180 -; submenu overlay struct: +; menu overlay struct: ; this struct must be writable, so these are hard-coded addresses in shared memory const OVERLAY_29_WIDTH: 0x80137180 ; 2 bytes const OVERLAY_29_HEIGHT: 0x80137182 ; 2 bytes @@ -267,13 +267,13 @@ startup_str_1: data.str "Welcome to fox32" data.8 0 startup_str_2: data.str "Insert boot disk" data.8 0 menu_items_root: - data.8 1 ; number of submenus - data.32 menu_items_system_list data.32 menu_items_system_name ; pointer to submenu list, pointer to submenu name + data.8 1 ; number of menus + data.32 menu_items_system_list data.32 menu_items_system_name ; pointer to menu list, pointer to menu name menu_items_system_name: data.8 6 data.str "System" data.8 0x00 ; text length, text, null-terminator menu_items_system_list: data.8 3 ; number of items - data.8 12 ; submenu width (usually longest item + 2) + data.8 12 ; menu width (usually longest item + 2) data.8 5 data.str "About" data.8 0x00 ; text length, text, null-terminator data.8 10 data.str "Mount Disk" data.8 0x00 ; text length, text, null-terminator data.8 4 data.str "Halt" data.8 0x00 ; text length, text, null-terminator diff --git a/menu.asm b/menu.asm index 300adfd..5dbc183 100644 --- a/menu.asm +++ b/menu.asm @@ -1,112 +1,13 @@ -; menu bar routines +; menu 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 +; draw menu items ; inputs: ; r0: pointer to menu bar root struct -; r1: selected root menu item (or 0xFFFFFFFF for none) +; r1: selected root menu item +; r2: hovering 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: +draw_menu_items: push r0 push r1 push r2 @@ -115,73 +16,130 @@ menu_bar_click_event: push r5 push r6 push r7 - push r28 + push r8 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 + ; calculate the X position of the menu + 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 menu 0 + ifz jmp draw_menu_items_calculate_x_skip 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 - jmp menu_bar_click_event_end -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 +draw_menu_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_menu_items_calculate_x_loop +draw_menu_items_calculate_x_skip: + sub r30, 8 ; move the menu to the left by 8 pixels + mov.16 [OVERLAY_29_POSITION_X], r30 + + mov r31, r0 + inc r31 ; point to menu list pointer + mul r1, 8 ; point to the selected menu + add r31, r1 + mov r0, [r31] ; load menu list pointer + movz.8 r31, [r0] ; load number of menu items + mov r30, r2 ; r30: number of the hovered item + mov r29, 0 ; counter of how many menu items drawn so far + + ; calculate the required height for the menu overlay + ; multiply the number of menu 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 menu overlay + ; multiply the width by 8 (the font is 8 pixels wide) + mov r1, r0 + inc r1 + movz.8 r1, [r1] ; load width of menu + 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, 0x8000001D ; 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, 0x8000011D ; overlay 29: size + mov.16 r1, [OVERLAY_29_HEIGHT] + sla r1, 16 + mov.16 r1, [OVERLAY_29_WIDTH] + out r0, r1 + mov r0, 0x8000021D ; overlay 29: framebuffer pointer + mov r1, [OVERLAY_29_FRAMEBUFFER_PTR] + out r0, r1 + mov r0, 0x8000031D + out r0, 1 + + ; draw empty menu + 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_menu_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_menu_line_loop: + call draw_font_tile_to_overlay + add r1, 8 + dec r7 + ifnz jmp draw_empty_menu_line_loop + mov r1, 0 + add r2, 16 + inc r29 + dec r6 + ifnz jmp draw_empty_menu_loop + mov r29, 0 ; counter of how many menu items drawn so far + pop r0 + + ; draw menu text + add r0, 3 ; point to start of menu items text + mov r2, 0 ; Y = 0 +draw_menu_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 menu 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_menu_text_loop - ; add a submenu_update_event_type event to the event queue - 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 r6, 0 - mov r7, 0 - mov r0, SUBMENU_UPDATE_EVENT_TYPE - call new_event -menu_bar_click_event_end: pop r31 pop r30 pop r29 - pop r28 + pop r8 pop r7 pop r6 pop r5 @@ -192,31 +150,120 @@ menu_bar_click_event_end: pop r0 ret -;menu_items_root: -; data.8 3 ; number of submenus -; data.32 menu_items_file_list data.32 menu_items_file_name ; pointer to submenu list, pointer to submenu name -; data.32 menu_items_edit_list data.32 menu_items_edit_name ; pointer to submenu list, pointer to submenu name -; data.32 menu_items_system_list data.32 menu_items_system_name ; pointer to submenu list, pointer to submenu name -;menu_items_file_name: -; data.8 4 data.str "File" data.8 0x00 ; text length, text, null-terminator -;menu_items_file_list: -; data.8 2 ; number of items -; data.8 6 ; submenu width (in number of characters) -; data.8 6 data.str "Test 1" data.8 0x00 ; text length, text, null-terminator -; data.8 6 data.str "Test 2" data.8 0x00 ; text length, text, null-terminator -;menu_items_edit_name: -; data.8 4 data.str "Edit" data.8 0x00 ; text length, text, null-terminator -;menu_items_edit_list: -; data.8 2 ; number of items -; data.8 6 ; submenu width (in number of characters) -; data.8 6 data.str "Test 3" data.8 0x00 ; text length, text, null-terminator -; data.8 6 data.str "Test 4" data.8 0x00 ; text length, text, null-terminator -;menu_items_system_name: -; data.8 6 data.str "System" data.8 0x00 ; text length, text, null-terminator -;menu_items_system_list: -; data.8 4 ; number of items -; data.8 6 ; submenu width (in number of characters) -; data.8 6 data.str "Test 5" data.8 0x00 ; text length, text, null-terminator -; data.8 6 data.str "Test 6" data.8 0x00 ; text length, text, null-terminator -; data.8 6 data.str "Test 7" data.8 0x00 ; text length, text, null-terminator -; data.8 6 data.str "Test 8" data.8 0x00 ; text length, text, null-terminator \ No newline at end of file +; hide the menu +; inputs: +; r0: pointer to menu bar root struct +; outputs: +; none +close_menu: + push r1 + + ; disable overlay 29 + mov r1, 0x8000031D + out r1, 0 + + mov r1, 0xFFFFFFFF + call draw_menu_bar_root_items + + pop r1 + ret + +; update the currently open menu +; detects mouse movements over the menu and handles clicks +; this should only be called if a menu_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 menu item (or 0xFFFFFFFF for none) +; outputs: +; none +; the event is added back into the event queue if the menu is still open +menu_update_event: + push r0 + push r1 + push r2 + push r3 + push r4 + push r5 + push r6 + push r7 + 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 menu item (or 0xFFFFFFFF for none) + + ; check if the menu overlay is enabled + ; if the menu was closed then exit without readding the update event to the event queue + in r0, 0x8000031D + cmp r0, 0 + ifz jmp menu_update_event_end_no_add + + ; get the current mouse position and check if the menu overlay covers that position + ; if the mouse is not in the menu, then there is nothing to do + call get_mouse_position + mov r2, 29 + call check_if_enabled_overlay_covers_position + ifnz jmp menu_update_event_end_add + + ; make the mouse position relative to the menu 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 menu 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 menu_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_menu_items +menu_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 menu_update_event_clicked + + jmp menu_update_event_end_add +menu_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 menu item + mov r4, 0 + mov r5, 0 + mov r6, 0 + mov r7, 0 + mov r0, MENU_CLICK_EVENT_TYPE + call new_event + mov r0, r1 + call close_menu + jmp menu_update_event_end_no_add +menu_update_event_end_add: + ; readd the menu_update_event_type event to the event queue + 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 menu item (or 0xFFFFFFFF for none) + mov r4, 0 + mov r5, 0 + mov r6, 0 + mov r7, 0 + mov r0, MENU_UPDATE_EVENT_TYPE + call new_event +menu_update_event_end_no_add: + pop r9 + pop r8 + pop r7 + pop r6 + pop r5 + pop r4 + pop r3 + pop r2 + pop r1 + pop r0 + ret \ No newline at end of file diff --git a/menu_bar.asm b/menu_bar.asm new file mode 100644 index 0000000..3b56128 --- /dev/null +++ b/menu_bar.asm @@ -0,0 +1,222 @@ +; 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 r6 + push r7 + 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_menu already calls this + call close_menu + jmp menu_bar_click_event_end +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_menu_items + + ; add a menu_update_event_type event to the event queue + 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 menu item (or 0xFFFFFFFF for none) + mov r4, 0 + mov r5, 0 + mov r6, 0 + mov r7, 0 + mov r0, MENU_UPDATE_EVENT_TYPE + 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 + pop r2 + pop r1 + pop r0 + ret + +;menu_items_root: +; data.8 3 ; number of menus +; data.32 menu_items_file_list data.32 menu_items_file_name ; pointer to menu list, pointer to menu name +; data.32 menu_items_edit_list data.32 menu_items_edit_name ; pointer to menu list, pointer to menu name +; data.32 menu_items_system_list data.32 menu_items_system_name ; pointer to menu list, pointer to menu name +;menu_items_file_name: +; data.8 4 data.str "File" data.8 0x00 ; text length, text, null-terminator +;menu_items_file_list: +; data.8 2 ; number of items +; data.8 6 ; menu width (in number of characters) +; data.8 6 data.str "Test 1" data.8 0x00 ; text length, text, null-terminator +; data.8 6 data.str "Test 2" data.8 0x00 ; text length, text, null-terminator +;menu_items_edit_name: +; data.8 4 data.str "Edit" data.8 0x00 ; text length, text, null-terminator +;menu_items_edit_list: +; data.8 2 ; number of items +; data.8 6 ; menu width (in number of characters) +; data.8 6 data.str "Test 3" data.8 0x00 ; text length, text, null-terminator +; data.8 6 data.str "Test 4" data.8 0x00 ; text length, text, null-terminator +;menu_items_system_name: +; data.8 6 data.str "System" data.8 0x00 ; text length, text, null-terminator +;menu_items_system_list: +; data.8 4 ; number of items +; data.8 6 ; menu width (in number of characters) +; data.8 6 data.str "Test 5" data.8 0x00 ; text length, text, null-terminator +; data.8 6 data.str "Test 6" data.8 0x00 ; text length, text, null-terminator +; data.8 6 data.str "Test 7" data.8 0x00 ; text length, text, null-terminator +; data.8 6 data.str "Test 8" data.8 0x00 ; text length, text, null-terminator \ No newline at end of file diff --git a/mouse.asm b/mouse.asm index 5f6f47b..35f2ab8 100644 --- a/mouse.asm +++ b/mouse.asm @@ -65,7 +65,7 @@ mouse_update: cmp r1, 17 ifc jmp mouse_update_menu_was_clicked - ; if a submenu is open, don't push a click event + ; if a menu is open, don't push a click event ; this is hacky as fuck in r3, 0x8000031D ; overlay 29: enable status cmp r3, 0 diff --git a/submenu.asm b/submenu.asm deleted file mode 100644 index 038c871..0000000 --- a/submenu.asm +++ /dev/null @@ -1,269 +0,0 @@ -; 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, 0x8000001D ; 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, 0x8000011D ; overlay 29: size - mov.16 r1, [OVERLAY_29_HEIGHT] - sla r1, 16 - mov.16 r1, [OVERLAY_29_WIDTH] - out r0, r1 - mov r0, 0x8000021D ; overlay 29: framebuffer pointer - mov r1, [OVERLAY_29_FRAMEBUFFER_PTR] - out r0, r1 - mov r0, 0x8000031D - 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, 0x8000031D - 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 added back into the event queue if the submenu is still open -submenu_update_event: - push r0 - push r1 - push r2 - push r3 - push r4 - push r5 - push r6 - push r7 - 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) - - ; check if the submenu overlay is enabled - ; if the submenu was closed then exit without readding the update event to the event queue - in r0, 0x8000031D - cmp r0, 0 - ifz jmp submenu_update_event_end_no_add - - ; 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_add - - ; 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_add -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 r6, 0 - mov r7, 0 - mov r0, SUBMENU_CLICK_EVENT_TYPE - call new_event - mov r0, r1 - call close_submenu - jmp submenu_update_event_end_no_add -submenu_update_event_end_add: - ; readd the submenu_update_event_type event to the event queue - 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 r6, 0 - mov r7, 0 - mov r0, SUBMENU_UPDATE_EVENT_TYPE - call new_event -submenu_update_event_end_no_add: - pop r9 - pop r8 - pop r7 - pop r6 - pop r5 - pop r4 - pop r3 - pop r2 - pop r1 - pop r0 - ret \ No newline at end of file