Initial commit

I should've made a git repo for this much sooner, oops :p
This commit is contained in:
ry755 2022-01-26 22:21:21 -08:00 committed by Ry
commit 705593697b
15 changed files with 5829 additions and 0 deletions

166
background.asm Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

BIN
font/cursor2.raw Normal file

Binary file not shown.

BIN
font/cursor2.xcf Normal file

Binary file not shown.

4352
font/unifont-thin.inc Normal file

File diff suppressed because it is too large Load Diff

BIN
font/unifont-thin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
font/unifont-thin.xcf Normal file

Binary file not shown.

227
menu.asm Normal file
View 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
View 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
View 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
View 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
View 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
View 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

5
vsync.asm Normal file
View File

@ -0,0 +1,5 @@
; vsync interrupt routine
system_vsync_handler:
call mouse_update
reti