mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
DOCS
This commit is contained in:
78
docs/appdev/custom_apps.md
Normal file
78
docs/appdev/custom_apps.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Creating a Custom App (Step-by-Step)
|
||||
|
||||
This guide explains how to write a new "Hello World" application locally, compile it as an `.elf` binary into the `bin/` folder, and launch it inside BoredOS.
|
||||
|
||||
## Step 1: Write the C Source
|
||||
|
||||
Applications reside entirely in the `src/userland/` directory. Create a new file, for example, `src/userland/gui/hello.c`.
|
||||
|
||||
> [!TIP]
|
||||
> Group CLI apps into `src/userland/cli/` and windowed apps into `src/userland/gui/` for organization.
|
||||
|
||||
```c
|
||||
// src/userland/gui/hello.c
|
||||
#include <stdlib.h>
|
||||
#include <libui.h>
|
||||
|
||||
int main(void) {
|
||||
// Attempt to open a 300x200 window
|
||||
int wid = ui_create_window("My Custom App", 300, 200, 0);
|
||||
if (wid < 0) {
|
||||
printf("Error creating window!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write text in center
|
||||
ui_draw_string(wid, "Hello, BoredOS!!", 50, 90, 0xFFFFFFFF);
|
||||
|
||||
// Commit drawing to screen
|
||||
ui_swap_buffers(wid);
|
||||
|
||||
ui_event_t event;
|
||||
while (1) {
|
||||
if (ui_poll_event(&event)) {
|
||||
if (event.window_id == wid && event.type == UI_EVENT_WINDOW_CLOSE) {
|
||||
break; // Exit loop if 'X' is clicked
|
||||
}
|
||||
}
|
||||
|
||||
syscall1(SYSTEM_CMD_YIELD, 0);
|
||||
}
|
||||
|
||||
return 0; // Returning 0 smoothly exits the process via crt0.asm
|
||||
}
|
||||
```
|
||||
|
||||
## Step 2: Edit the Makefile
|
||||
|
||||
Now you need to tell the build system to compile `hello.c`. Fortunately, the `src/userland/Makefile` is designed to detect new C files largely automatically!
|
||||
|
||||
1. Open `src/userland/Makefile`.
|
||||
2. Find the line specifying `APP_SOURCES_FULL`:
|
||||
```make
|
||||
APP_SOURCES_FULL = $(wildcard cli/*.c gui/*.c sys/*.c games/*.c *.c)
|
||||
```
|
||||
Since you placed the file in `gui/hello.c`, the wildcard logic will pick it up automatically.
|
||||
3. The Makefile will generate `bin/hello.elf` during the build phase.
|
||||
|
||||
## Step 3: Bundle it into the OS
|
||||
|
||||
The main overarching `Makefile` (in the project root) takes binaries from `src/userland/bin/*.elf` and places them into the `iso_root/bin/` directory, while also adding them to `limine.conf` as loadable boot modules.
|
||||
|
||||
1. Go back to the root of the OS:
|
||||
```sh
|
||||
cd ../..
|
||||
```
|
||||
2. Compile the entire project to build the ISO and test in QEMU:
|
||||
```sh
|
||||
make clean && make run
|
||||
```
|
||||
|
||||
## Step 4: Run it inside BoredOS
|
||||
|
||||
1. When BoredOS boots, launch the **Terminal** application.
|
||||
2. The OS automatically maps built applications to standard shell commands. Simply type your application's filename (without the `.elf` extension).
|
||||
3. Type `hello` in the terminal and press Enter.
|
||||
4. Your custom window will appear!
|
||||
|
||||
*you can also open your app by opening the file explorer and navigating to the bin directory and double clicking the executable.*
|
||||
36
docs/appdev/sdk_reference.md
Normal file
36
docs/appdev/sdk_reference.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Userland SDK Reference
|
||||
|
||||
BoredOS provides a custom `libc` implementation necessary for writing userland applications (`.elf` binaries). By avoiding a full-blown standard library like `glibc`, the OS ensures a minimal executable footprint tailored strictly to the existing kernel features.
|
||||
|
||||
## The Custom libc Structure (`src/userland/libc/`)
|
||||
|
||||
The SDK comprises a few key files containing wrappers around kernel system calls:
|
||||
|
||||
- `stdlib.h` / `stdlib.c`: Memory allocation (`malloc`, `free`), integer conversion (`itoa`, `atoi`), printing (`printf`, `sprintf`), and random numbers (`rand`, `srand`).
|
||||
- `string.h` / `string.c`: String manipulation utilities (`strlen`, `strcpy`, `strcmp`, `memset`, `memcpy`).
|
||||
- `syscall.h` / `syscall.c`: The raw interface to issue `syscall` assembly instructions, routing requests to the kernel.
|
||||
- `libui.h` / `libui.c`: Graphical interface commands (creating windows, drawing pixels, events).
|
||||
|
||||
## System Calls Overview
|
||||
|
||||
When a userland application wants to interact with the hardware (print to screen, read a file, create a window), it must ask the kernel via a **System Call**.
|
||||
|
||||
In BoredOS (`x86_64`), system calls are issued using the `syscall` instruction. The kernel intercepts this instruction and inspects the processor's RAX register to figure out *what* the application wants to do.
|
||||
|
||||
The custom `libc` provides `syscallX` wrapper functions that abstract the assembly details:
|
||||
```c
|
||||
// Example: Performing a minimal system call from userland
|
||||
int sys_write(int fd, const char *buf, int len) {
|
||||
return syscall3(SYS_WRITE, fd, (uint64_t)buf, len);
|
||||
}
|
||||
```
|
||||
|
||||
### Notable System Calls
|
||||
|
||||
- **`SYS_WRITE` (1)**: Currently acts as a generic output mechanism for `printf`, typically routing text to the kernel's serial output for debugging, or to an active text-mode console.
|
||||
- **`SYS_GUI` (3)**: The primary multiplexer for all window manager operations. The arguments define subcommands (like `UI_CREATE_WINDOW`, `UI_FILL_RECT`).
|
||||
- **`SYS_FS` (4)**: Interacts with the virtual filesystem (e.g., `FS_CMD_OPEN`, `FS_CMD_READ`). Under the hood, this reads from the loaded RAMFS or an attached physical ATA disk via the native FAT32 driver.
|
||||
- **`SYS_EXIT` (60)**: Terminates the current process and returns control to the kernel.
|
||||
- **`SYSTEM_CMD_YIELD` (43)**: Instructs the process scheduler to pause the current process and let another process run.
|
||||
|
||||
If you are developing a new application, **do not invoke syscalls manually**. Instead, include `stdlib.h` and use the C functions provided.
|
||||
85
docs/appdev/ui_api.md
Normal file
85
docs/appdev/ui_api.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# UI API (`libui.h`)
|
||||
|
||||
For an application to be visible on the screen, it must interact with the BoredOS Window Manager (WM). The tools required for this are located in `src/userland/libc/libui.h` and `libui.c`.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
The UI library sends requests (via `SYS_GUI`) to the kernel to reserve an area on the screen (a `Window`) and then issues commands to color specific pixels within that area. The kernel is responsible for compositing this area over other windows.
|
||||
|
||||
## Example: Creating a Window
|
||||
|
||||
First, include the library and define an event structure:
|
||||
|
||||
```c
|
||||
#include <libui.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void) {
|
||||
// 1. Create the window
|
||||
// Arguments: Title, Width, Height, Flags (e.g. 0 for bordered window)
|
||||
int window_id = ui_create_window("Hello World App", 400, 300, 0);
|
||||
|
||||
if (window_id < 0) {
|
||||
printf("Failed to create window!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ... Event loop will go here ...
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Drawing Primitives
|
||||
|
||||
The library offers functions to mutate the window's internal buffer. After issuing drawing commands, you **must** instruct the kernel to push the changes onto the screen.
|
||||
|
||||
```c
|
||||
// Fill the entire window with a solid blue background
|
||||
// Arguments: Window ID, X, Y, Width, Height, ARGB Color value
|
||||
ui_fill_rect(window_id, 0, 0, 400, 300, 0xFF0000FF);
|
||||
|
||||
// Tell the kernel to commit the drawing commands to the screen
|
||||
ui_swap_buffers(window_id);
|
||||
```
|
||||
|
||||
Available rendering methods:
|
||||
- `ui_fill_rect(id, x, y, w, h, color)`: Draw a solid rectangle.
|
||||
- `ui_draw_rect(id, x, y, w, h, color)`: Draw an outline of a rectangle.
|
||||
- `ui_draw_line(id, x0, y0, x1, y1, color)`: Bresenham line algorithm.
|
||||
- `ui_draw_string(id, string, x, y, color)`: Render text using the kernel's built-in font.
|
||||
- `ui_update_region(id, x, y, w, h)`: A targeted version of `ui_swap_buffers` that only updates a specific area, saving performance.
|
||||
|
||||
## Handling the Event Loop
|
||||
|
||||
Graphical applications are event-driven. They stay alive inside a `while (1)` loop, periodically asking the kernel if the user clicked the mouse or pressed a key inside their window.
|
||||
|
||||
```c
|
||||
ui_event_t event;
|
||||
|
||||
// Main UI Loop
|
||||
while (1) {
|
||||
// ui_poll_event is non-blocking. It returns 1 if an event occurred, 0 otherwise.
|
||||
if (ui_poll_event(&event)) {
|
||||
|
||||
// The WM dispatch sets event.window_id
|
||||
// We only care about events meant for our specific window
|
||||
if (event.window_id == window_id) {
|
||||
|
||||
if (event.type == UI_EVENT_MOUSE_DOWN) {
|
||||
printf("User clicked at X:%d Y:%d\n", event.mouse_x, event.mouse_y);
|
||||
|
||||
// Respond visually to the click
|
||||
ui_fill_rect(window_id, event.mouse_x, event.mouse_y, 10, 10, 0xFFFF0000); // Red dot
|
||||
ui_swap_buffers(window_id);
|
||||
}
|
||||
else if (event.type == UI_EVENT_WINDOW_CLOSE) {
|
||||
// Start tearing down the application safely
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent 100% CPU usage by yielding execution time back to the OS scheduler
|
||||
syscall1(SYSTEM_CMD_YIELD, 0);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user