fox32os/kernel/main.asm

426 lines
10 KiB
NASM

; fox32os kernel
const LOAD_ADDRESS: 0x03000000
const FOX32OS_VERSION_MAJOR: 0
const FOX32OS_VERSION_MINOR: 2
const FOX32OS_VERSION_PATCH: 0
const FOX32OS_API_VERSION: 1
const REQUIRED_FOX32ROM_API_VERSION: 1
const SYSTEM_STACK: 0x01FFF800
const BACKGROUND_COLOR: 0xFF674764
const TEXT_COLOR: 0xFFFFFFFF
jmp entry
; system jump table
org.pad 0x00000010
jump_table:
data.32 get_os_version
data.32 get_os_api_version
data.32 get_current_disk_id
data.32 set_current_disk_id
; FXF jump table
org.pad 0x00000110
data.32 parse_fxf_binary
data.32 launch_fxf_from_disk
data.32 launch_fxf_from_open_file
; task jump table
org.pad 0x00000210
data.32 new_task
data.32 yield_task
data.32 end_current_task
data.32 get_current_task_id
data.32 get_unused_task_id
data.32 is_task_id_used
data.32 save_state_and_yield_task
; memory jump table
org.pad 0x00000310
data.32 allocate_memory
data.32 free_memory
; window jump table
org.pad 0x00000410
data.32 new_window
data.32 destroy_window
data.32 new_window_event
data.32 get_next_window_event
data.32 draw_title_bar_to_window
data.32 move_window
data.32 fill_window
data.32 get_window_overlay_number
data.32 start_dragging_window
data.32 new_messagebox
data.32 get_active_window_struct
; VFS jump table
org.pad 0x00000510
data.32 open
data.32 seek
data.32 tell
data.32 read
data.32 write
data.32 get_size
; widget jump table
org.pad 0x00000610
data.32 draw_widgets_to_window
data.32 handle_widget_click
jump_table_end:
; initialization code
entry:
; before doing anything, check if we are running on top of an existing instance of the kernel
; we can do this by comparing our load address to the known load address that the bootloader loads us to
; only the high 16 bits are checked
rcall 6
pop r1
mov.16 r1, 0
cmp r1, LOAD_ADDRESS
ifz jmp entry_ok
; if it appears that we're running on top of an existing kernel, then show a messagebox and exit
; call the messagebox routines of the existing kernel
mov r0, 0
mov r1, kernelception_error_str
mov r2, 0
mov r3, 64
mov r4, 64
mov r5, 184
call [0x00000C34] ; new_messagebox
call [0x00000A18] ; end_current_task
rjmp 0
entry_ok:
mov rsp, SYSTEM_STACK
; save the boot disk id that the bootloader passed in r0
mov.8 [current_disk_id], r0
; clear the background
mov r0, BACKGROUND_COLOR
call fill_background
; check for the required fox32rom API version
mov r0, get_rom_api_version
add r0, 2
mov r0, [r0]
cmp [r0], 0
ifz jmp api_version_too_low_error
call get_rom_api_version
cmp r0, REQUIRED_FOX32ROM_API_VERSION
iflt jmp api_version_too_low_error
; initialize the memory allocator
call initialize_allocator
; draw the bottom bar
mov r0, bottom_bar_str_0
mov r1, 8
mov r2, 448
mov r3, TEXT_COLOR
mov r4, 0x00000000
call draw_str_to_background
mov r0, bottom_bar_patterns
mov r1, 1
mov r2, 16
call set_tilemap
mov r1, 0
mov r2, 464
mov r31, 640
draw_bottom_bar_loop:
mov r4, r31
rem r4, 2
cmp r4, 0
ifz mov r0, 0
ifnz mov r0, 1
call draw_tile_to_background
inc r1
loop draw_bottom_bar_loop
mov r0, 10
mov r1, 464
mov r2, 20
mov r3, 16
mov r4, 0xFFFFFFFF
call draw_filled_rectangle_to_background
mov r0, bottom_bar_str_1
mov r1, 12
mov r2, 464
mov r3, 0xFF000000
mov r4, 0xFFFFFFFF
call draw_str_to_background
mov r0, bottom_bar_str_2
mov r1, 488
mov r2, 464
mov r3, 0xFF000000
mov r4, 0xFFFFFFFF
mov r10, FOX32OS_VERSION_MAJOR
mov r11, FOX32OS_VERSION_MINOR
mov r12, FOX32OS_VERSION_PATCH
call draw_format_str_to_background
; copy the jump table to 0x00000810
mov r0, jump_table
mov r1, 0x00000810
mov r2, jump_table_end
sub r2, jump_table
call copy_memory_bytes
; check if a disk is inserted as disk 1
; if so, skip checking startup.cfg and just run disk 1
in r31, 0x80001001
cmp r31, 0
ifnz jmp boot_disk_1
try_startup:
; open startup.cfg
call get_current_disk_id
mov r1, r0
mov r0, startup_cfg
mov r2, startup_cfg_struct
call ryfs_open
cmp r0, 0
ifz jmp startup_error
; load a startup task
load_startup_task:
; load 11 bytes of startup.cfg into startup_file
mov r0, 11
mov r1, startup_cfg_struct
mov r2, startup_file
call ryfs_read
; open the actual startup file
call get_current_disk_id
mov r1, r0
mov r0, startup_file
mov r2, startup_file_struct
call ryfs_open
cmp r0, 0
ifz jmp startup_error
; create a new task and yield to it
mov r0, startup_file_struct
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
call launch_fxf_from_open_file
; when the startup file yields for the first time, we'll end up back here
; now, check to see if startup.cfg has any other entries
; we do this by checking to see if the size of startup.cfg is less than or equal to 12 * next_task bytes
inc.8 [next_task]
mov r0, startup_cfg_struct
call get_size
movz.8 r1, [next_task]
mul r1, 12
cmp r0, r1
iflteq jmp no_other_tasks
; seek forward one byte to skip the linefeed
mov r0, startup_cfg_struct
call ryfs_tell
inc r0
mov r1, startup_cfg_struct
call ryfs_seek
; load the next task
jmp load_startup_task
no_other_tasks:
; start the event manager task
call start_event_manager_task
; jump back to it without adding this "task" (not really a task) into the queue.
; end_current_task_no_mark_no_free is used specifically because it doesn't mark
; the current task (still set to 0) as unused, and it doesn't free the memory
; block.
; this does not return.
call end_current_task_no_mark_no_free
; try loading the raw contents of disk 1 as an FXF binary
; if disk 1 is not inserted, then fail
boot_disk_1:
; check if a disk is inserted as disk 1
in r31, 0x80001001
cmp r31, 0
ifz jmp startup_error
; a disk is inserted, load it!!
; allocate memory for the startup file
; r31 contains disk size
mov r0, r31
call allocate_memory
cmp r0, 0
ifz jmp memory_error
div r31, 512
inc r31
mov r2, r0 ; destination pointer
mov r5, r0
mov r0, 0 ; sector counter
mov r3, 0x80003001 ; command to read a sector from disk 1 into memory
mov r4, 0x80002000 ; command to set the location of the buffer
boot_disk_1_loop:
out r4, r2 ; set the memory buffer location
out r3, r0 ; read the current sector into memory
inc r0 ; increment sector counter
add r2, 512 ; increment the destination pointer
loop boot_disk_1_loop
mov r1, r5
mov r0, r5
call parse_fxf_binary
cmp r0, 0
ifz jmp disk_1_is_not_fxf
mov r3, r1
mov r1, r0
movz.8 r0, 0
mov r2, rsp
sub r2, 4
mov r4, 0 ; don't attempt to free any stack block if the task ends
call new_task
jmp no_other_tasks
; disk 1 was found to not be a valid FXF binary
; free the memory allocated for it and instead just keep it mounted as a disk
disk_1_is_not_fxf:
mov r0, r5
call free_memory
jmp try_startup
startup_error:
mov r0, BACKGROUND_COLOR
call fill_background
mov r0, startup_error_str
mov r1, 16
mov r2, 464
mov r3, TEXT_COLOR
mov r4, 0x00000000
mov r10, FOX32OS_VERSION_MAJOR
mov r11, FOX32OS_VERSION_MINOR
mov r12, FOX32OS_VERSION_PATCH
call draw_format_str_to_background
rjmp 0
memory_error:
mov r0, BACKGROUND_COLOR
call fill_background
mov r0, memory_error_str
mov r1, 16
mov r2, 464
mov r3, TEXT_COLOR
mov r4, 0x00000000
mov r10, FOX32OS_VERSION_MAJOR
mov r11, FOX32OS_VERSION_MINOR
mov r12, FOX32OS_VERSION_PATCH
call draw_format_str_to_background
rjmp 0
api_version_too_low_error:
mov r0, BACKGROUND_COLOR
call fill_background
mov r0, api_error_str
mov r1, 16
mov r2, 464
mov r3, TEXT_COLOR
mov r4, 0x00000000
mov r10, FOX32OS_VERSION_MAJOR
mov r11, FOX32OS_VERSION_MINOR
mov r12, FOX32OS_VERSION_PATCH
call draw_format_str_to_background
rjmp 0
get_current_disk_id:
movz.8 r0, [current_disk_id]
ret
set_current_disk_id:
mov.8 [current_disk_id], r0
ret
get_os_version:
mov r0, FOX32OS_VERSION_MAJOR
mov r1, FOX32OS_VERSION_MINOR
mov r2, FOX32OS_VERSION_PATCH
ret
get_os_api_version:
mov r0, FOX32OS_API_VERSION
ret
#include "allocator.asm"
#include "fxf/fxf.asm"
#include "task.asm"
#include "vfs/vfs.asm"
#include "widget/widget.asm"
#include "window/window.asm"
bottom_bar_str_0: data.strz "FOX"
bottom_bar_str_1: data.strz "32"
bottom_bar_str_2: data.strz " OS version %u.%u.%u "
startup_error_str: data.strz "fox32 - OS version %u.%u.%u - startup.cfg is invalid!"
memory_error_str: data.strz "fox32 - OS version %u.%u.%u - not enough memory to perform operation!"
api_error_str: data.strz "fox32 - OS version %u.%u.%u - fox32rom API version too low!"
kernelception_error_str: data.strz "Error: kernelception?"
bottom_bar_patterns:
; 1x16 tile
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
; 1x16 tile
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
data.32 0xFFFFFFFF
data.32 0xFF674764
next_task: data.8 0
current_disk_id: data.8 0
startup_cfg: data.str "startup cfg"
startup_cfg_struct: data.fill 0, 32
startup_file: data.str " "
startup_file_struct: data.fill 0, 32
#include "../../fox32rom/fox32rom.def"
kernel_bottom: