Fetcher: Initial commit

This commit includes needed kernel changes and additions.
main
Ry 2023-07-12 00:00:08 -07:00
parent 460b0be997
commit df9e7eb311
16 changed files with 405 additions and 23 deletions

View File

@ -24,6 +24,15 @@ base_image/barclock.fxf: applications/barclock/main.asm
base_image/terminal.fxf: applications/terminal/main.asm $(wildcard applications/terminal/*.asm)
$(FOX32ASM) $< $@
base_image/fetcher.fxf: applications/fetcher/Fetcher.okm $(wildcard applications/fetcher/*.okm)
lua $(OKAMERON) -arch=fox32 -startup=applications/fetcher/start.asm $< \
applications/fetcher/Browser.okm \
applications/fetcher/Desktop.okm \
applications/fetcher/OS.okm \
> applications/fetcher/fetcher.asm
$(FOX32ASM) applications/fetcher/fetcher.asm $@
rm applications/fetcher/fetcher.asm
base_image/serial.fxf: applications/serial/main.asm $(wildcard applications/terminal/*.asm)
$(FOX32ASM) $< $@
@ -62,6 +71,7 @@ FILES = \
base_image/sh.fxf \
base_image/barclock.fxf \
base_image/terminal.fxf \
base_image/fetcher.fxf \
base_image/serial.fxf \
base_image/foxpaint.fxf \
base_image/okmpaint.fxf \
@ -75,6 +85,7 @@ ROM_FILES = \
base_image/sh.fxf \
base_image/barclock.fxf \
base_image/terminal.fxf \
base_image/fetcher.fxf \
base_image/serial.fxf \
base_image/bg.fxf \
base_image/launcher.fxf

View File

@ -0,0 +1,43 @@
MODULE Browser;
IMPORT OS;
VAR browserRunning: CHAR;
browserWindow: ARRAY 36 OF CHAR;
browserIcons: ARRAY 31 OF Fox32OSButtonWidget;
PROCEDURE BrowserMain(diskId: INT;);
BEGIN
browserRunning := 1;
(* create the window and fill it with white *)
new_window(PTROF(browserWindow), "Fetcher", 384, 192, 64, 64, 0, PTROF(browserIcons));
fill_window(0FFFFFFFFH, PTROF(browserWindow));
(*draw_widgets_to_window(PTROF(browserWindow));*)
WHILE browserRunning DO
GetNextWindowEvent(PTROF(browserWindow));
(* mouse click event *)
IF eventArgs[0] = PTROF(EVENT_TYPE_MOUSE_CLICK) THEN
IF (eventArgs[1] <| 8) & (eventArgs[2] <| 16) THEN
destroy_window(PTROF(browserWindow));
browserRunning := 0;
ELSIF eventArgs[2] <| 16 THEN
start_dragging_window(PTROF(browserWindow));
END;
handle_widget_click(PTROF(browserWindow), eventArgs[1], eventArgs[2]);
(* mouse click event *)
ELSIF eventArgs[0] = PTROF(EVENT_TYPE_BUTTON_CLICK) THEN
HandleIconClick(eventArgs[1]);
END;
save_state_and_yield_task();
END;
END;
PROCEDURE HandleIconClick(buttonId: INT;);
BEGIN
(* TODO *)
END;
END.

View File

@ -0,0 +1,112 @@
MODULE Desktop;
IMPORT OS;
VAR desktopRunning: CHAR;
desktopWindow: ARRAY 36 OF CHAR;
desktopIcons: ARRAY 5 OF Fox32OSButtonWidget;
PROCEDURE DesktopMain();
BEGIN
desktopRunning := 1;
(* set up the desktop icon widgets *)
SetupDesktopIconStructs();
(* create the window and make it fully transparent, draw the button widgets to it, and mark it as "always background *)
new_window(PTROF(desktopWindow), "Desktop", 640, 448, 0, 16, 0, PTROF(desktopIcons));
fill_overlay(000000000H, get_window_overlay_number(PTROF(desktopWindow)));
draw_widgets_to_window(PTROF(desktopWindow));
set_window_flags(000000001H, PTROF(desktopWindow));
WHILE desktopRunning DO
GetNextWindowEvent(PTROF(desktopWindow));
(* mouse click event *)
IF eventArgs[0] = PTROF(EVENT_TYPE_MOUSE_CLICK) THEN
handle_widget_click(PTROF(desktopWindow), eventArgs[1], eventArgs[2]);
(* mouse click event *)
ELSIF eventArgs[0] = PTROF(EVENT_TYPE_BUTTON_CLICK) THEN
HandleDesktopIconClick(eventArgs[1]);
END;
save_state_and_yield_task();
END;
END;
PROCEDURE HandleDesktopIconClick(buttonId: INT;);
BEGIN
IF launch_fxf_from_disk("fetcher.fxf", get_boot_disk_id(), 0FFFFFFFFH, buttonId, 0, 0, 0) = 0FFFFFFFFH THEN
new_messagebox("Failed to start new", "instance of fetcher.fxf", 0, 64, 64, 200);
END;
END;
PROCEDURE SetupDesktopIconStructs();
VAR desktopIcon: POINTER TO Fox32OSButtonWidget;
prevDesktopIcon: POINTER TO Fox32OSButtonWidget;
BEGIN
desktopIcon := PTROF(desktopIcons[0]);
desktopIcon^.type := WIDGET_TYPE_BUTTON;
desktopIcon^.next := PTROF(desktopIcons[1]);
desktopIcon^.id := 0;
desktopIcon^.text := "Disk 0";
desktopIcon^.fgColor := 0FF000000H;
desktopIcon^.bgColor := 0FFFFFFFFH;
desktopIcon^.width := 32;
desktopIcon^.height := 32 + 16;
desktopIcon^.x := 592;
desktopIcon^.y := 16;
prevDesktopIcon := desktopIcon;
desktopIcon := PTROF(desktopIcons[1]);
desktopIcon^.type := WIDGET_TYPE_BUTTON;
desktopIcon^.next := PTROF(desktopIcons[2]);
desktopIcon^.id := 1;
desktopIcon^.text := "Disk 1";
desktopIcon^.fgColor := 0FF000000H;
desktopIcon^.bgColor := 0FFFFFFFFH;
desktopIcon^.width := 32;
desktopIcon^.height := 32 + 16;
desktopIcon^.x := 592;
desktopIcon^.y := prevDesktopIcon^.y + 32 + 32;
prevDesktopIcon := desktopIcon;
desktopIcon := PTROF(desktopIcons[2]);
desktopIcon^.type := WIDGET_TYPE_BUTTON;
desktopIcon^.next := PTROF(desktopIcons[3]);
desktopIcon^.id := 1;
desktopIcon^.text := "Disk 2";
desktopIcon^.fgColor := 0FF000000H;
desktopIcon^.bgColor := 0FFFFFFFFH;
desktopIcon^.width := 32;
desktopIcon^.height := 32 + 16;
desktopIcon^.x := 592;
desktopIcon^.y := prevDesktopIcon^.y + 32 + 32;
prevDesktopIcon := desktopIcon;
desktopIcon := PTROF(desktopIcons[3]);
desktopIcon^.type := WIDGET_TYPE_BUTTON;
desktopIcon^.next := PTROF(desktopIcons[4]);
desktopIcon^.id := 1;
desktopIcon^.text := "Disk 3";
desktopIcon^.fgColor := 0FF000000H;
desktopIcon^.bgColor := 0FFFFFFFFH;
desktopIcon^.width := 32;
desktopIcon^.height := 32 + 16;
desktopIcon^.x := 592;
desktopIcon^.y := prevDesktopIcon^.y + 32 + 32;
prevDesktopIcon := desktopIcon;
desktopIcon := PTROF(desktopIcons[4]);
desktopIcon^.type := WIDGET_TYPE_BUTTON;
desktopIcon^.next := 0;
desktopIcon^.id := 1;
desktopIcon^.text := "Disk 4";
desktopIcon^.fgColor := 0FF000000H;
desktopIcon^.bgColor := 0FFFFFFFFH;
desktopIcon^.width := 32;
desktopIcon^.height := 32 + 16;
desktopIcon^.x := 592;
desktopIcon^.y := prevDesktopIcon^.y + 32 + 32;
END;
END.

View File

@ -0,0 +1,20 @@
MODULE Fetcher;
IMPORT OS, Browser, Desktop;
EXTERN terminalStreamPtr: POINTER TO CHAR;
EXTERN arg0Ptr: POINTER TO CHAR;
PROCEDURE Main();
BEGIN
IF (terminalStreamPtr = 0) & (arg0Ptr = 0) THEN
(* probably launched from startup.cfg *)
DesktopMain();
ELSIF arg0Ptr <|= 5 THEN
(* launched from an existing instance of fetcher *)
BrowserMain(arg0Ptr);
ELSE
(* probably launched from the terminal *)
BrowserMain(string_to_int(arg0Ptr, 10));
END;
END;
END.

View File

@ -0,0 +1,25 @@
MODULE OS;
EXTERN PROCEDURE new_window, destroy_window, draw_str_to_overlay, get_window_overlay_number,
draw_widgets_to_window, draw_filled_rectangle_to_overlay, GetNextWindowEvent, DrawPixel,
save_state_and_yield_task, start_dragging_window, handle_widget_click, fill_window, fill_overlay,
set_window_flags, menu_update_event, menu_bar_click_event, close_menu, new_messagebox,
launch_fxf_from_disk, get_boot_disk_id, string_to_int: INT;
EXTERN PROCEDURE brk: INT;
EXTERN EVENT_TYPE_MOUSE_CLICK,
EVENT_TYPE_MOUSE_RELEASE,
EVENT_TYPE_BUTTON_CLICK,
EVENT_TYPE_MENU_BAR_CLICK,
EVENT_TYPE_MENU_UPDATE,
EVENT_TYPE_MENU_CLICK,
EVENT_TYPE_MENU_ACK,
WIDGET_TYPE_BUTTON: INT;
EXTERN eventArgs: ARRAY 8 OF INT;
TYPE Fox32OSButtonWidget = RECORD
next, id, type, text, fgColor, bgColor: INT;
width, height, x, y: SHORT;
END;
END.

View File

@ -0,0 +1,38 @@
pop [terminalStreamPtr]
pop [arg0Ptr]
call Main
call end_current_task
GetNextWindowEvent:
push r8
call get_next_window_event
mov r8, eventArgs
mov [r8], r0
add r8, 4
mov [r8], r1
add r8, 4
mov [r8], r2
add r8, 4
mov [r8], r3
add r8, 4
mov [r8], r4
add r8, 4
mov [r8], r5
add r8, 4
mov [r8], r6
add r8, 4
mov [r8], r7
pop r8
ret
brk:
brk
ret
eventArgs: data.fill 0, 32
terminalStreamPtr: data.32 0
arg0Ptr: data.32 0
#include "../../../fox32rom/fox32rom.def"
#include "../../fox32os.def"

View File

@ -1,4 +1,5 @@
bg fxf
barclockfxf
fetcher fxf
launcherfxf
terminalfxf

View File

@ -5,10 +5,12 @@ get_os_version: jmp [0x00000810]
get_os_api_version: jmp [0x00000814]
get_current_disk_id: jmp [0x00000818]
set_current_disk_id: jmp [0x0000081C]
get_boot_disk_id: jmp [0x00000820]
; FXF jump table
parse_fxf_binary: jmp [0x00000910]
launch_fxf_from_disk: jmp [0x00000914]
launch_fxf_from_open_file: jmp [0x00000918]
; task jump table
new_task: jmp [0x00000A10]
@ -35,6 +37,7 @@ get_window_overlay_number: jmp [0x00000C2C]
start_dragging_window: jmp [0x00000C30]
new_messagebox: jmp [0x00000C34]
get_active_window_struct: jmp [0x00000C38]
set_window_flags: jmp [0x00000C3C]
; VFS jump table
open: jmp [0x00000D10]
@ -53,3 +56,6 @@ const EVENT_TYPE_BUTTON_CLICK: 0x80000000
; widget types
const WIDGET_TYPE_BUTTON: 0x00000000
; window flags
const WINDOW_FLAG_ALWAYS_BACKGROUND: 1

View File

@ -23,6 +23,7 @@ jump_table:
data.32 get_os_api_version
data.32 get_current_disk_id
data.32 set_current_disk_id
data.32 get_boot_disk_id
; FXF jump table
org.pad 0x00000110
@ -58,6 +59,7 @@ jump_table:
data.32 start_dragging_window
data.32 new_messagebox
data.32 get_active_window_struct
data.32 set_window_flags
; VFS jump table
org.pad 0x00000510
@ -101,6 +103,7 @@ entry_ok:
mov rsp, SYSTEM_STACK
; save the boot disk id that the bootloader passed in r0
mov.8 [boot_disk_id], r0
mov.8 [current_disk_id], r0
; clear the background
@ -344,6 +347,10 @@ api_version_too_low_error:
call draw_format_str_to_background
rjmp 0
get_boot_disk_id:
movz.8 r0, [boot_disk_id]
ret
get_current_disk_id:
movz.8 r0, [current_disk_id]
ret
@ -415,6 +422,7 @@ bottom_bar_patterns:
next_task: data.8 0
current_disk_id: data.8 0
boot_disk_id: data.8 0
startup_cfg: data.str "startup cfg"
startup_cfg_struct: data.fill 0, 32
startup_file: data.str " "

View File

@ -24,7 +24,7 @@ new_task:
call task_store
mov [task_queue_ptr], r0
; fall-through
jmp save_state_and_yield_task
; switch to the next task in the queue
; no registers are saved upon task yield

View File

@ -8,7 +8,7 @@
; data.32 foreground_color - text foreground color
; data.32 background_color - button background color
; data.16 width - width of this button
; data.16 reserved
; data.16 height - height of this button
; data.16 x_pos - X coordinate of this widget
; data.16 y_pos - Y coordinate of this widget
@ -24,6 +24,7 @@ const BUTTON_WIDGET_STRUCT_SIZE: 32 ; 8 words = 32 bytes
; r4: button width
; r5: X coordinate
; r6: Y coordinate
; r7: button height
draw_button_widget:
push r0
push r1
@ -31,6 +32,7 @@ draw_button_widget:
push r3
push r4
push r5
push r7
push r10
push r20
push r30
@ -64,7 +66,9 @@ draw_button_widget_strlen_loop:
mov r5, r0
mov r2, r31
mov r4, r3
mov r3, 16
cmp r7, 16
iflt mov r7, 16
mov r3, r7
mov r0, r30
mov r1, r6
call draw_filled_rectangle_to_overlay
@ -79,6 +83,8 @@ draw_button_widget_strlen_loop:
mov r3, r2
mov r1, r5
mov r2, r6
add r2, r7
sub r2, 16
mov r5, r10
call draw_str_to_overlay
@ -86,6 +92,7 @@ draw_button_widget_strlen_loop:
pop r30
pop r20
pop r10
pop r7
pop r5
pop r4
pop r3

View File

@ -43,6 +43,7 @@ draw_widgets_to_window_button:
push r4
push r5
push r6
push r7
push r10
; put button parameters in registers for the drawing routine
@ -54,13 +55,16 @@ draw_widgets_to_window_button:
mov r3, [r10] ; background_color
add r10, 4
movz.16 r4, [r10] ; width
add r10, 4
add r10, 2
movz.16 r7, [r10] ; height
add r10, 2
movz.16 r5, [r10] ; x_pos
add r10, 2
movz.16 r6, [r10] ; y_pos
call draw_button_widget
pop r10
pop r7
pop r6
pop r5
pop r4
@ -115,6 +119,7 @@ handle_widget_click_button:
push r10
push r11
push r12
push r13
push r21
push r22
@ -122,8 +127,14 @@ handle_widget_click_button:
add r0, 16
movz.16 r10, [r0]
; get button height
add r0, 2
movz.16 r13, [r0]
cmp r13, 16
iflt mov r13, 16
; get button X coordinate
add r0, 4
add r0, 2
movz.16 r11, [r0]
; get button Y coordinate
@ -136,7 +147,7 @@ handle_widget_click_button:
; calculate button's bottom right corner coordinate
mov r22, r12
add r22, 16
add r22, r13
; check if r1 is between r11 and r21
; and if r2 is between r12 and r22
@ -152,6 +163,7 @@ handle_widget_click_button:
; if we reach this point then the button was clicked!!
pop r22
pop r21
pop r13
pop r12
pop r11
pop r10
@ -174,6 +186,7 @@ handle_widget_click_button:
handle_widget_click_button_no_click:
pop r22
pop r21
pop r13
pop r12
pop r11
pop r10

View File

@ -27,6 +27,12 @@ start_event_manager_task:
event_manager_task_loop:
call get_next_event
; mouse
cmp r0, EVENT_TYPE_MOUSE_CLICK
ifz call event_manager_task_mouse_event
cmp r0, EVENT_TYPE_MOUSE_RELEASE
ifz call event_manager_task_mouse_event
cmp.8 [active_window_offset], 0xFF
ifz rjmp event_manager_task_loop_end
@ -40,12 +46,6 @@ event_manager_task_loop:
cmp r0, EVENT_TYPE_MENU_UPDATE
ifz call add_event_to_active_window
; mouse
cmp r0, EVENT_TYPE_MOUSE_CLICK
ifz call event_manager_task_mouse_event
cmp r0, EVENT_TYPE_MOUSE_RELEASE
ifz call event_manager_task_mouse_event
; keyboard
cmp r0, EVENT_TYPE_KEY_DOWN
ifz call add_event_to_active_window
@ -85,6 +85,9 @@ event_manager_task_mouse_event:
; get the overlay number of the active window
movz.8 r0, [active_window_offset]
cmp.8 r0, 0xFF
ifz pop r1
ifz jmp event_manager_task_mouse_event_inactive_window_was_clicked
call window_list_offset_to_struct
call get_window_overlay_number
@ -114,19 +117,30 @@ event_manager_task_mouse_event_inactive_window_was_clicked:
call get_window_with_overlay
mov r1, r2
; give up if a window was not found for this overlay
cmp r0, 0x00000000
ifz pop r2
ifz pop r1
ifz pop r0
ifz ret
; r0: currently active window struct
; r1: clicked window struct
; give up if a window was not found for the clicked overlay
cmp r1, 0x00000000
ifz pop r2
ifz pop r1
ifz pop r0
ifz ret
; swap the two
; if there is no active window, but we reached this point,
; then assume the click was on an inactive window marked as "always background"
; it's probably bad to assume this, more checks would be good
cmp r0, 0x00000000
ifz jmp event_manager_task_mouse_event_inactive_window_was_clicked_no_change
; swap the two, if the "always background" flag is not set for the clicked window
push r1
add r1, 25
movz.16 r1, [r1]
and r1, WINDOW_FLAG_ALWAYS_BACKGROUND
cmp r1, 0
pop r1
ifnz jmp event_manager_task_mouse_event_inactive_window_was_clicked_no_change
call swap_windows
; mark the clicked window as the active window
@ -146,4 +160,15 @@ event_manager_task_mouse_event_inactive_window_was_clicked:
pop r2
pop r1
pop r0
call add_mouse_event_to_active_window
ret
event_manager_task_mouse_event_inactive_window_was_clicked_no_change:
mov [old_r8], r8
mov r8, r1
pop r2
pop r1
pop r0
call add_mouse_event_to_inactive_window
mov r8, [old_r8]
ret
old_r8: data.32 0

View File

@ -81,7 +81,7 @@ messagebox_event_loop:
cmp r0, EVENT_TYPE_BUTTON_CLICK
ifz jmp messagebox_ok_clicked
call yield_task
call save_state_and_yield_task
jmp messagebox_event_loop
messagebox_ok_clicked:

View File

@ -11,7 +11,7 @@
; data.16 y_pos - Y coordinate of this window (top left corner of title bar)
; data.8 overlay - overlay number of this window
; data.8 reserved_1
; data.16 reserved_2
; data.16 flags - flags for this window
; data.32 menu_bar_ptr - pointer to this window's menu bar root struct, or 0 for none
; data.32 first_widget_ptr - pointer to this window's first widget
@ -19,6 +19,7 @@ const WINDOW_STRUCT_SIZE: 36 ; 9 words = 36 bytes
const TITLE_BAR_HEIGHT: 16
const TITLE_BAR_TEXT_FOREGROUND: 0xFF000000
const TITLE_BAR_TEXT_BACKGROUND: 0xFFFFFFFF
const WINDOW_FLAG_ALWAYS_BACKGROUND: 1
; create a new window and allocate memory as required
; inputs:
@ -218,6 +219,21 @@ destroy_window_no_more_windows:
pop r0
ret
; call this if the user clicks on a window's title bar
; inputs:
; r0: 16-bit flags value
; r1: pointer to window struct
; outputs:
; none
set_window_flags:
push r1
add r1, 25
mov.16 [r1], r0
pop r1
ret
; call this if the user clicks on a window's title bar
; inputs:
; r0: pointer to window struct
@ -529,6 +545,52 @@ add_mouse_event_to_active_window_end:
pop r0
ret
; add a mouse event to an inactive window if the mouse was clicked inside the window
; if so, automatically convert the X and Y coords to be relative to the window
; inputs:
; r0-r7: event
; r8: pointer to window struct
; outputs:
; none
add_mouse_event_to_inactive_window:
push r0
push r2
push r10
push r11
push r12
; save X and Y coords of the click and the event type
mov r10, r1
mov r11, r2
mov r12, r0
; get the window's overlay number
mov r0, r8
call get_window_overlay_number
; check if the window's overlay covers the clicked position
mov r2, r0
mov r0, r10
mov r1, r11
call check_if_overlay_covers_position
; if it doesn't, then end here
ifnz jmp add_mouse_event_to_inactive_window_end
; if it does, then make the X and Y coords relative to the overlay
call make_coordinates_relative_to_overlay
; add the event
mov r2, r1
mov r1, r0
mov r0, r12
call new_window_event
add_mouse_event_to_inactive_window_end:
pop r12
pop r11
pop r10
pop r2
pop r0
ret
; search for an entry in the window list
; inputs:
; r0: entry (pointer to window struct)
@ -565,6 +627,7 @@ search_for_window_list_entry_found:
ret
; search for the first non-empty entry in the window list
; this skips over items that have the "always background" flag set
; inputs:
; none
; outputs:
@ -572,6 +635,7 @@ search_for_window_list_entry_found:
search_for_nonempty_window_list_entry:
push r1
push r2
push r3
push r31
mov r1, window_list
@ -579,7 +643,14 @@ search_for_nonempty_window_list_entry:
mov r31, 31
search_for_nonempty_window_list_entry_loop:
cmp [r1], 0
ifnz jmp search_for_nonempty_window_list_entry_found
ifz jmp search_for_nonempty_window_list_entry_loop_skip
mov r3, [r1]
add r3, 25
movz.16 r3, [r3]
and r3, WINDOW_FLAG_ALWAYS_BACKGROUND
cmp r3, 0
ifz jmp search_for_nonempty_window_list_entry_found
search_for_nonempty_window_list_entry_loop_skip:
inc r2
add r1, 4
loop search_for_nonempty_window_list_entry_loop
@ -587,6 +658,7 @@ search_for_nonempty_window_list_entry_loop:
mov r0, 0xFFFFFFFF
pop r31
pop r3
pop r2
pop r1
ret
@ -595,6 +667,7 @@ search_for_nonempty_window_list_entry_found:
mov r0, r2
pop r31
pop r3
pop r2
pop r1
ret

@ -1 +1 @@
Subproject commit ea08b7048ebfbea70229e7b7e8a7cbb46fd08d74
Subproject commit 1bc51054291b3981b62b01a940e025e49412619c