From 705593697b7c733f892560dc3a35552af5135a73 Mon Sep 17 00:00:00 2001 From: ry755 Date: Wed, 26 Jan 2022 22:21:21 -0800 Subject: [PATCH] Initial commit I should've made a git repo for this much sooner, oops :p --- background.asm | 166 ++ event.asm | 93 + font/cursor2.png | Bin 0 -> 625 bytes font/cursor2.raw | Bin 0 -> 384 bytes font/cursor2.xcf | Bin 0 -> 846 bytes font/unifont-thin.inc | 4352 +++++++++++++++++++++++++++++++++++++++++ font/unifont-thin.png | Bin 0 -> 13989 bytes font/unifont-thin.xcf | Bin 0 -> 17891 bytes menu.asm | 227 +++ mouse.asm | 95 + overlay.asm | 357 ++++ rom.asm | 245 +++ rom.def | 34 + submenu.asm | 255 +++ vsync.asm | 5 + 15 files changed, 5829 insertions(+) create mode 100644 background.asm create mode 100644 event.asm create mode 100644 font/cursor2.png create mode 100644 font/cursor2.raw create mode 100644 font/cursor2.xcf create mode 100644 font/unifont-thin.inc create mode 100644 font/unifont-thin.png create mode 100644 font/unifont-thin.xcf create mode 100644 menu.asm create mode 100644 mouse.asm create mode 100644 overlay.asm create mode 100644 rom.asm create mode 100644 rom.def create mode 100644 submenu.asm create mode 100644 vsync.asm diff --git a/background.asm b/background.asm new file mode 100644 index 0000000..e9a9c82 --- /dev/null +++ b/background.asm @@ -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 diff --git a/event.asm b/event.asm new file mode 100644 index 0000000..a9072ba --- /dev/null +++ b/event.asm @@ -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 diff --git a/font/cursor2.png b/font/cursor2.png new file mode 100644 index 0000000000000000000000000000000000000000..821a4727b94a3dc133c66a2025de58aa8e2cfca5 GIT binary patch literal 625 zcmV-%0*?KOP)EX>4Tx04R}tkv&MmP!xqvQ>CI62P=p;WT;LSMMWH?ibb$c+6t{Yn7s54nlvOS zE{=k0!NH%!s)LKOt`4q(Aov5~=H{g6A|>9J6k5c1;qgAsyXWxUeSlCeGu7;v094H~ zlCh|m$*zilSM*>2K8!<@n5oB8i)nb)*FAMo-9>noci*4YtK>`u_(bA4rW+RV2Jy_M zrE}gV4zZ%75T6r|8FWG7N3P2*zi}=&Ebz>bkxtGNhls^O8_R9XiiS!&O&nHKjq-(z z%L?Z$&T6^Jn)l={4Cb_z6xV4DBZei!k$?ypRg_SMg$V5$DJGJ19`*1KIsOE>WO9|j z$gzM5R7j2={11N5*33^$x=Fz((D`E9A0t3u7iiRM`}^3o8z+GO8Mx9~{z@H~{Up8C z(!xhT-!^b@-O}Ve;Bp5Te9|RDawI=3A)g1{&*+=7K>sb!z2?rXd5+TuAWgGcz5xyn zfzbkGuY0_^t9@?&_B7}B1EimFyH4P8F#rGn24YJ`L;wH)0002_L%V+f000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2jvSD0tYf4SfvC2000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0000;NklA00000 LNkvXXu0mjf?0*G5 literal 0 HcmV?d00001 diff --git a/font/cursor2.raw b/font/cursor2.raw new file mode 100644 index 0000000000000000000000000000000000000000..b9859d43d509afe892b3d80ff8a694a21394139d GIT binary patch literal 384 zcmaKmK@I>Q2*dXOPopDh0Aah3&_V{lphK=4V}#>eIFAob;*In1;v{~0#=g$EFL!(8 OY26FUoPI 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 literal 0 HcmV?d00001 diff --git a/font/unifont-thin.xcf b/font/unifont-thin.xcf new file mode 100644 index 0000000000000000000000000000000000000000..25528a1da855a5e97a1a7b97a463abe31b77e985 GIT binary patch literal 17891 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 P-~q~A6kc~xG8FSKTC_mS literal 0 HcmV?d00001 diff --git a/menu.asm b/menu.asm new file mode 100644 index 0000000..02d8a12 --- /dev/null +++ b/menu.asm @@ -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 \ No newline at end of file diff --git a/mouse.asm b/mouse.asm new file mode 100644 index 0000000..d7589ea --- /dev/null +++ b/mouse.asm @@ -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 \ No newline at end of file diff --git a/overlay.asm b/overlay.asm new file mode 100644 index 0000000..a92061f --- /dev/null +++ b/overlay.asm @@ -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 \ No newline at end of file diff --git a/rom.asm b/rom.asm new file mode 100644 index 0000000..ed31568 --- /dev/null +++ b/rom.asm @@ -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 \ No newline at end of file diff --git a/rom.def b/rom.def new file mode 100644 index 0000000..0862f94 --- /dev/null +++ b/rom.def @@ -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 \ No newline at end of file diff --git a/submenu.asm b/submenu.asm new file mode 100644 index 0000000..7790c18 --- /dev/null +++ b/submenu.asm @@ -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 \ No newline at end of file diff --git a/vsync.asm b/vsync.asm new file mode 100644 index 0000000..5dd4cf1 --- /dev/null +++ b/vsync.asm @@ -0,0 +1,5 @@ +; vsync interrupt routine + +system_vsync_handler: + call mouse_update + reti