fox32os/kernel/main.asm

421 lines
10 KiB
NASM

; fox32os kernel
opton
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
data.32 get_boot_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
data.32 sleep_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
data.32 set_window_flags
; 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
; resource jump table
org.pad 0x00000710
data.32 get_resource
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 [boot_disk_id], 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.bat and just run disk 1
in r31, 0x80001001
cmp r31, 0
ifnz jmp boot_disk_1
try_startup:
mov r0, serial_stream
mov r2, serial_stream_struct
call open
mov r0, startup_bat
movz.8 r1, [boot_disk_id]
mov r2, startup_bat_check_struct
call open
cmp r0, 0
ifz jmp emergency_shell
; run `sh startup.bat` with IO redirected to :serial
mov r0, sh_fxf
movz.8 r1, [boot_disk_id]
mov r2, serial_stream_struct
mov r3, startup_bat
mov r4, 0
mov r5, 0
mov r6, 0
call launch_fxf_from_disk
cmp r0, 0xFFFFFFFF
ifz jmp startup_error
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
emergency_shell:
mov r0, sh_fxf
movz.8 r1, [boot_disk_id]
mov r2, serial_stream_struct
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
call launch_fxf_from_disk
cmp r0, 0xFFFFFFFF
ifz jmp startup_error
jmp no_other_tasks
; 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
mov 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_boot_disk_id:
movz.8 r0, [boot_disk_id]
ret
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 "res.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 - sh.fxf is missing?"
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
current_disk_id: data.8 0
boot_disk_id: data.8 0
sh_fxf: data.strz "sh.fxf"
startup_bat: data.strz "startup.bat"
startup_bat_check_struct: data.fill 0, 32
serial_stream: data.strz ":serial"
serial_stream_struct: data.fill 0, 32
#include "../fox32rom/fox32rom.def"
kernel_bottom: