This commit is contained in:
boreddevnl 2026-02-27 16:19:11 +01:00
parent f9d84d434e
commit 8c6d751254
25 changed files with 237 additions and 166 deletions

BIN
.DS_Store vendored

Binary file not shown.

View file

@ -32,7 +32,7 @@ LDFLAGS = -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker \
NASMFLAGS = -f elf64 NASMFLAGS = -f elf64
# Limine Version # Limine Version
LIMINE_VERSION = 10.8.2 LIMINE_VERSION = 7.0.0
LIMINE_URL_BASE = https://github.com/limine-bootloader/limine/raw/v$(LIMINE_VERSION) LIMINE_URL_BASE = https://github.com/limine-bootloader/limine/raw/v$(LIMINE_VERSION)
.PHONY: all clean run limine-setup .PHONY: all clean run limine-setup
@ -86,25 +86,26 @@ $(KERNEL_ELF): $(OBJ_FILES)
$(MAKE) -C $(SRC_DIR)/userland $(MAKE) -C $(SRC_DIR)/userland
# Create ISO # Create ISO
$(ISO_IMAGE): $(KERNEL_ELF) limine.conf limine-setup $(ISO_IMAGE): $(KERNEL_ELF) limine.cfg limine-setup
rm -rf $(ISO_DIR) rm -rf $(ISO_DIR)
mkdir -p $(ISO_DIR) mkdir -p $(ISO_DIR)
mkdir -p $(ISO_DIR)/EFI/BOOT mkdir -p $(ISO_DIR)/EFI/BOOT
# Copy Kernel and Config # Copy Kernel and Config
cp $(KERNEL_ELF) $(ISO_DIR)/ cp $(KERNEL_ELF) $(ISO_DIR)/
# Build ISO limine.conf natively with modules # Build ISO limine.cfg natively with modules
cp limine.conf $(ISO_DIR)/ cp limine.cfg $(ISO_DIR)/
mkdir -p $(ISO_DIR)/bin mkdir -p $(ISO_DIR)/bin
@for f in $(SRC_DIR)/userland/*.elf; do \ @for f in $(SRC_DIR)/userland/*.elf; do \
if [ -f "$$f" ]; then \ if [ -f "$$f" ]; then \
basename=$$(basename "$$f"); \ basename=$$(basename "$$f"); \
cp "$$f" $(ISO_DIR)/bin/; \ cp "$$f" $(ISO_DIR)/bin/; \
echo " module_path: boot():/bin/$$basename" >> $(ISO_DIR)/limine.conf; \ echo " MODULE_PATH=boot:///bin/$$basename" >> $(ISO_DIR)/limine.cfg; \
fi \ fi \
done done
# Copy README # Copy README
@if [ -f README.md ]; then cp README.md $(ISO_DIR)/; fi
# Copy Wallpaper (if it exists) # Copy Wallpaper (if it exists)
@if [ -f src/kernel/wallpaper.ppm ]; then cp src/kernel/wallpaper.ppm $(ISO_DIR)/; fi @if [ -f src/kernel/wallpaper.ppm ]; then cp src/kernel/wallpaper.ppm $(ISO_DIR)/; fi
@ -133,11 +134,8 @@ clean:
rm -rf $(BUILD_DIR) $(ISO_DIR) $(ISO_IMAGE) rm -rf $(BUILD_DIR) $(ISO_DIR) $(ISO_IMAGE)
run: $(ISO_IMAGE) run: $(ISO_IMAGE)
dd if=/dev/zero of=disk.img bs=1M count=64
mformat -i disk.img -F ::
qemu-system-x86_64 -m 2G -serial stdio -cdrom $< -boot d \ qemu-system-x86_64 -m 2G -serial stdio -cdrom $< -boot d \
-audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \ -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \
-netdev user,id=net0,hostfwd=udp::12345-:12345 -device e1000,netdev=net0 \ -netdev user,id=net0,hostfwd=udp::12345-:12345 -device e1000,netdev=net0 \
-vga std -global VGA.xres=1920 -global VGA.yres=1080 \ -vga std -global VGA.xres=1920 -global VGA.yres=1080 \
-drive file=disk.img,format=raw \
-no-reboot -d int -D qemu-debug.log

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
disk.img

Binary file not shown.

2
limine

@ -1 +1 @@
Subproject commit 38ff2c855aabb92e4cfa2cc7ef0c8af665ecba94 Subproject commit 36783ec43af4db4841a1e80770355fd1e98f091b

8
limine.cfg Normal file
View file

@ -0,0 +1,8 @@
TIMEOUT=3
TERM_PALETTE=ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff
TERM_BACKGROUND=00000000
WALLPAPER=splash.jpg
:BoredOS
PROTOCOL=limine
KERNEL_PATH=boot:///boredos.elf

View file

@ -1,11 +0,0 @@
timeout: 3
# Graphics mode and Splash screen
term_palette: ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff;ffffff
term_background: #00000000
wallpaper: boot():/splash.jpg
/BoredOS
protocol: limine
kernel_path: boot():/boredos.elf

View file

@ -731,50 +731,6 @@ static const CommandEntry commands[] = {
{NULL, NULL} {NULL, NULL}
}; };
// Helper to build full path with cmd window's drive context
static void cmd_build_full_path(const char *relative_path, char *full_path) {
if (!cmd_state) {
if (relative_path[0]) {
cmd_strcpy(full_path, relative_path);
} else {
full_path[0] = 'A';
full_path[1] = ':';
full_path[2] = '/';
full_path[3] = 0;
}
return;
}
// If path already has drive letter, use it as-is
if (relative_path && relative_path[1] == ':') {
cmd_strcpy(full_path, relative_path);
return;
}
// Build path with cmd_state's drive and directory
int i = 0;
full_path[i++] = cmd_state->current_drive;
full_path[i++] = ':';
// Add current directory
const char *dir = cmd_state->current_dir;
while (*dir && i < 509) {
full_path[i++] = *dir++;
}
// Add path argument
if (relative_path && relative_path[0]) {
if (i > 2 && full_path[i-1] != '/') {
full_path[i++] = '/';
}
const char *p = relative_path;
while (*p && i < 509) {
full_path[i++] = *p++;
}
}
full_path[i] = 0;
}
// Helper to sync cmd window directory after cd // Helper to sync cmd window directory after cd
static void cmd_update_dir(const char *path) { static void cmd_update_dir(const char *path) {

View file

@ -93,11 +93,12 @@ static int ata_identify(uint16_t port_base, bool slave) {
if (status == 0) return 0; if (status == 0) return 0;
// Wait until BSY clears // Wait until BSY clears
while (inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY) { int timeout = 10000;
// Simple timeout could be added here while ((inb(port_base + ATA_REG_STATUS) & ATA_SR_BSY) && --timeout > 0) {
status = inb(port_base + ATA_REG_STATUS); status = inb(port_base + ATA_REG_STATUS);
if (status == 0) return 0; // Check again if (status == 0) return 0; // Check again
} }
if (timeout <= 0) return 0; // Hardware didn't respond
// Check for error // Check for error
if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) { if (inb(port_base + ATA_REG_STATUS) & ATA_SR_ERR) {

View file

@ -43,7 +43,7 @@ static int dropdown_menu_item_height = 25;
#define CONTEXT_MENU_ITEM_HEIGHT 25 #define CONTEXT_MENU_ITEM_HEIGHT 25
// Clipboard state // Clipboard state
static char clipboard_path[256] = ""; static char clipboard_path[FAT32_MAX_PATH] = "";
static int clipboard_action = 0; // 0=None, 1=Copy, 2=Cut static int clipboard_action = 0; // 0=None, 1=Copy, 2=Cut
#define FILE_CONTEXT_ITEMS 2 // "Open with Text Editor" and "Open with Markdown Viewer" #define FILE_CONTEXT_ITEMS 2 // "Open with Text Editor" and "Open with Markdown Viewer"
@ -259,7 +259,7 @@ static void dialog_confirm_create_file(Window *win) {
if (!check_desktop_limit_explorer(win)) return; if (!check_desktop_limit_explorer(win)) return;
char full_path[256]; char full_path[FAT32_MAX_PATH];
explorer_strcpy(full_path, state->dialog_creation_path); explorer_strcpy(full_path, state->dialog_creation_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') { if (full_path[explorer_strlen(full_path) - 1] != '/') {
explorer_strcat(full_path, "/"); explorer_strcat(full_path, "/");
@ -283,7 +283,7 @@ static void dialog_confirm_create_file(Window *win) {
static void dialog_force_create_file(Window *win) { static void dialog_force_create_file(Window *win) {
ExplorerState *state = (ExplorerState*)win->data; ExplorerState *state = (ExplorerState*)win->data;
char full_path[256]; char full_path[FAT32_MAX_PATH];
explorer_strcpy(full_path, state->dialog_creation_path); explorer_strcpy(full_path, state->dialog_creation_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') { if (full_path[explorer_strlen(full_path) - 1] != '/') {
explorer_strcat(full_path, "/"); explorer_strcat(full_path, "/");
@ -304,7 +304,7 @@ static void dialog_confirm_create_folder(Window *win) {
if (!check_desktop_limit_explorer(win)) return; if (!check_desktop_limit_explorer(win)) return;
char full_path[256]; char full_path[FAT32_MAX_PATH];
explorer_strcpy(full_path, state->dialog_creation_path); explorer_strcpy(full_path, state->dialog_creation_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') { if (full_path[explorer_strlen(full_path) - 1] != '/') {
explorer_strcat(full_path, "/"); explorer_strcat(full_path, "/");
@ -331,7 +331,7 @@ bool explorer_delete_permanently(const char *path) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (explorer_strcmp(entries[i].name, ".") == 0 || explorer_strcmp(entries[i].name, "..") == 0) continue; if (explorer_strcmp(entries[i].name, ".") == 0 || explorer_strcmp(entries[i].name, "..") == 0) continue;
char child_path[256]; char child_path[FAT32_MAX_PATH];
explorer_strcpy(child_path, path); explorer_strcpy(child_path, path);
if (child_path[explorer_strlen(child_path) - 1] != '/') { if (child_path[explorer_strlen(child_path) - 1] != '/') {
explorer_strcat(child_path, "/"); explorer_strcat(child_path, "/");
@ -379,13 +379,13 @@ bool explorer_delete_recursive(const char *path) {
drive_prefix[0] = path[0]; drive_prefix[0] = path[0];
} }
char dest_path[256]; char dest_path[FAT32_MAX_PATH];
explorer_strcpy(dest_path, drive_prefix); explorer_strcpy(dest_path, drive_prefix);
explorer_strcat(dest_path, "/RecycleBin/"); explorer_strcat(dest_path, "/RecycleBin/");
explorer_strcat(dest_path, filename); explorer_strcat(dest_path, filename);
// Save origin // Save origin
char origin_path[256]; char origin_path[FAT32_MAX_PATH];
explorer_strcpy(origin_path, dest_path); explorer_strcpy(origin_path, dest_path);
explorer_strcat(origin_path, ".origin"); explorer_strcat(origin_path, ".origin");
FAT32_FileHandle *fh = fat32_open(origin_path, "w"); FAT32_FileHandle *fh = fat32_open(origin_path, "w");
@ -446,7 +446,7 @@ static bool explorer_copy_recursive(const char *src_path, const char *dest_path)
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (explorer_strcmp(files[i].name, ".") == 0 || explorer_strcmp(files[i].name, "..") == 0) continue; if (explorer_strcmp(files[i].name, ".") == 0 || explorer_strcmp(files[i].name, "..") == 0) continue;
char s_sub[256], d_sub[256]; char s_sub[FAT32_MAX_PATH], d_sub[FAT32_MAX_PATH];
explorer_strcpy(s_sub, src_path); explorer_strcpy(s_sub, src_path);
if (s_sub[explorer_strlen(s_sub)-1] != '/') explorer_strcat(s_sub, "/"); if (s_sub[explorer_strlen(s_sub)-1] != '/') explorer_strcat(s_sub, "/");
explorer_strcat(s_sub, files[i].name); explorer_strcat(s_sub, files[i].name);
@ -482,7 +482,7 @@ static bool explorer_copy_recursive(const char *src_path, const char *dest_path)
} }
static void explorer_copy_file_internal(const char *src_path, const char *dest_dir) { static void explorer_copy_file_internal(const char *src_path, const char *dest_dir) {
char filename[256]; char filename[FAT32_MAX_FILENAME];
int len = explorer_strlen(src_path); int len = explorer_strlen(src_path);
int i = len - 1; int i = len - 1;
while (i >= 0 && src_path[i] != '/') i--; while (i >= 0 && src_path[i] != '/') i--;
@ -490,7 +490,7 @@ static void explorer_copy_file_internal(const char *src_path, const char *dest_d
for (int k = i + 1; k < len; k++) filename[j++] = src_path[k]; for (int k = i + 1; k < len; k++) filename[j++] = src_path[k];
filename[j] = 0; filename[j] = 0;
char dest_path[256]; char dest_path[FAT32_MAX_PATH];
explorer_strcpy(dest_path, dest_dir); explorer_strcpy(dest_path, dest_dir);
if (dest_path[explorer_strlen(dest_path) - 1] != '/') { if (dest_path[explorer_strlen(dest_path) - 1] != '/') {
explorer_strcat(dest_path, "/"); explorer_strcat(dest_path, "/");
@ -565,7 +565,7 @@ void explorer_create_shortcut(Window *win, const char *target_path) {
for (int k = i + 1; k < len; k++) filename[j++] = target_path[k]; for (int k = i + 1; k < len; k++) filename[j++] = target_path[k];
filename[j] = 0; filename[j] = 0;
char shortcut_path[256]; char shortcut_path[FAT32_MAX_PATH];
explorer_strcpy(shortcut_path, state->current_path); explorer_strcpy(shortcut_path, state->current_path);
if (shortcut_path[explorer_strlen(shortcut_path)-1] != '/') explorer_strcat(shortcut_path, "/"); if (shortcut_path[explorer_strlen(shortcut_path)-1] != '/') explorer_strcat(shortcut_path, "/");
explorer_strcat(shortcut_path, filename); explorer_strcat(shortcut_path, filename);
@ -649,7 +649,7 @@ static int explorer_build_context_menu(Window *win, ExplorerContextItem *items_o
// === Explorer Logic === // === Explorer Logic ===
static uint32_t explorer_get_folder_color(const char *folder_path) { static uint32_t explorer_get_folder_color(const char *folder_path) {
char color_file_path[256]; char color_file_path[FAT32_MAX_PATH];
explorer_strcpy(color_file_path, folder_path); explorer_strcpy(color_file_path, folder_path);
if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') { if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') {
explorer_strcat(color_file_path, "/"); explorer_strcat(color_file_path, "/");
@ -669,7 +669,7 @@ static uint32_t explorer_get_folder_color(const char *folder_path) {
} }
static void explorer_set_folder_color(const char *folder_path, uint32_t color) { static void explorer_set_folder_color(const char *folder_path, uint32_t color) {
char color_file_path[256]; char color_file_path[FAT32_MAX_PATH];
explorer_strcpy(color_file_path, folder_path); explorer_strcpy(color_file_path, folder_path);
if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') { if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') {
explorer_strcat(color_file_path, "/"); explorer_strcat(color_file_path, "/");
@ -687,19 +687,19 @@ static void explorer_restore_file(Window *win, int item_idx) {
ExplorerState *state = (ExplorerState*)win->data; ExplorerState *state = (ExplorerState*)win->data;
if (item_idx < 0 || item_idx >= state->item_count) return; if (item_idx < 0 || item_idx >= state->item_count) return;
char recycle_path[256]; char recycle_path[FAT32_MAX_PATH];
explorer_strcpy(recycle_path, state->current_path); explorer_strcpy(recycle_path, state->current_path);
if (recycle_path[explorer_strlen(recycle_path) - 1] != '/') explorer_strcat(recycle_path, "/"); if (recycle_path[explorer_strlen(recycle_path) - 1] != '/') explorer_strcat(recycle_path, "/");
explorer_strcat(recycle_path, state->items[item_idx].name); explorer_strcat(recycle_path, state->items[item_idx].name);
char origin_file_path[256]; char origin_file_path[FAT32_MAX_PATH];
explorer_strcpy(origin_file_path, recycle_path); explorer_strcpy(origin_file_path, recycle_path);
explorer_strcat(origin_file_path, ".origin"); explorer_strcat(origin_file_path, ".origin");
char original_path[256] = {0}; char original_path[FAT32_MAX_PATH] = {0};
FAT32_FileHandle *fh = fat32_open(origin_file_path, "r"); FAT32_FileHandle *fh = fat32_open(origin_file_path, "r");
if (fh) { if (fh) {
int len = fat32_read(fh, original_path, 255); int len = fat32_read(fh, original_path, FAT32_MAX_PATH - 1);
if (len > 0) original_path[len] = 0; if (len > 0) original_path[len] = 0;
fat32_close(fh); fat32_close(fh);
} }
@ -725,7 +725,7 @@ static void explorer_load_directory(Window *win, const char *path) {
int count = fat32_list_directory(path, entries, EXPLORER_MAX_FILES); int count = fat32_list_directory(path, entries, EXPLORER_MAX_FILES);
state->item_count = 0; state->item_count = 0;
for (int i = 0; i < count && i < EXPLORER_MAX_FILES; i++) { for (int i = 0; i < count && state->item_count < EXPLORER_MAX_FILES; i++) {
// Skip .color files // Skip .color files
if (explorer_strcmp(entries[i].name, ".color") == 0) { if (explorer_strcmp(entries[i].name, ".color") == 0) {
continue; continue;
@ -741,8 +741,8 @@ static void explorer_load_directory(Window *win, const char *path) {
state->items[state->item_count].size = entries[i].size; state->items[state->item_count].size = entries[i].size;
if (state->items[state->item_count].is_directory) { if (state->items[state->item_count].is_directory) {
char subfolder_path[256]; char subfolder_path[FAT32_MAX_PATH];
explorer_strcpy(subfolder_path, state->current_path); explorer_strcpy(subfolder_path, path);
if (subfolder_path[explorer_strlen(subfolder_path) - 1] != '/') { if (subfolder_path[explorer_strlen(subfolder_path) - 1] != '/') {
explorer_strcat(subfolder_path, "/"); explorer_strcat(subfolder_path, "/");
} }
@ -763,7 +763,7 @@ static void explorer_load_directory(Window *win, const char *path) {
static void explorer_navigate_to(Window *win, const char *dirname) { static void explorer_navigate_to(Window *win, const char *dirname) {
ExplorerState *state = (ExplorerState*)win->data; ExplorerState *state = (ExplorerState*)win->data;
char new_path[256]; char new_path[FAT32_MAX_PATH];
if (explorer_strcmp(dirname, "..") == 0) { if (explorer_strcmp(dirname, "..") == 0) {
// Go to parent directory // Go to parent directory
@ -827,7 +827,7 @@ static void explorer_open_item(Window *win, int index) {
return; return;
} }
char full_path[256]; char full_path[FAT32_MAX_PATH];
explorer_strcpy(full_path, state->current_path); explorer_strcpy(full_path, state->current_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') { if (full_path[explorer_strlen(full_path) - 1] != '/') {
explorer_strcat(full_path, "/"); explorer_strcat(full_path, "/");
@ -863,7 +863,7 @@ static void explorer_open_item(Window *win, int index) {
// Generic shortcut // Generic shortcut
FAT32_FileHandle *fh = fat32_open(full_path, "r"); FAT32_FileHandle *fh = fat32_open(full_path, "r");
if (fh) { if (fh) {
char buf[256]; char buf[FAT32_MAX_PATH];
int len = fat32_read(fh, buf, 255); int len = fat32_read(fh, buf, 255);
fat32_close(fh); fat32_close(fh);
if (len > 0) { if (len > 0) {
@ -898,7 +898,7 @@ static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, c
draw_paint_icon(x + 5, y + 5, ""); draw_paint_icon(x + 5, y + 5, "");
} else if (explorer_str_ends_with(filename, ".jpg") || explorer_str_ends_with(filename, ".JPG")) { } else if (explorer_str_ends_with(filename, ".jpg") || explorer_str_ends_with(filename, ".JPG")) {
// Build full path for thumbnail loading // Build full path for thumbnail loading
char full_path[256]; char full_path[FAT32_MAX_PATH];
explorer_strcpy(full_path, current_path); explorer_strcpy(full_path, current_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/"); if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/");
explorer_strcat(full_path, filename); explorer_strcat(full_path, filename);
@ -922,7 +922,7 @@ static void explorer_paint(Window *win) {
draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_DARK_BG); draw_rect(offset_x, offset_y, win->w - 8, win->h - 28, COLOR_DARK_BG);
// Draw Drive Button (modern rounded style) // Draw Drive Button (modern rounded style)
char drive_label[8]; char drive_label[9]; // 8 chars + null
// Extract drive from the window's current_path instead of using global current_drive // Extract drive from the window's current_path instead of using global current_drive
char current_drv = 'A'; char current_drv = 'A';
if (state->current_path[0] && state->current_path[1] == ':') { if (state->current_path[0] && state->current_path[1] == ':') {
@ -939,6 +939,7 @@ static void explorer_paint(Window *win) {
drive_label[5] = 'v'; drive_label[5] = 'v';
drive_label[6] = ' '; drive_label[6] = ' ';
drive_label[7] = ']'; drive_label[7] = ']';
drive_label[8] = 0;
// Button at x+4, y+3, w=60 (rounded) // Button at x+4, y+3, w=60 (rounded)
draw_rounded_rect_filled(win->x + 4, offset_y + 3, 60, 22, 5, COLOR_DARK_PANEL); draw_rounded_rect_filled(win->x + 4, offset_y + 3, 60, 22, 5, COLOR_DARK_PANEL);
@ -1209,7 +1210,7 @@ static void explorer_paint(Window *win) {
if (state->file_context_menu_visible) { if (state->file_context_menu_visible) {
// Convert window-relative coordinates to screen coordinates for drawing // Convert window-relative coordinates to screen coordinates for drawing
int menu_screen_x = win->x + state->file_context_menu_x; int menu_screen_x = win->x + state->file_context_menu_x;
int menu_screen_y = win->y + state->file_context_menu_y; int menu_screen_y = win->y + state->file_context_menu_y + 20; // Adjusted for title bar (20px)
ExplorerContextItem menu_items[20]; ExplorerContextItem menu_items[20];
int count = explorer_build_context_menu(win, menu_items); int count = explorer_build_context_menu(win, menu_items);
@ -1250,7 +1251,7 @@ static void explorer_handle_click(Window *win, int x, int y) {
// Handle dialog clicks // Handle dialog clicks
if (state->dialog_state == DIALOG_CREATE_FILE || state->dialog_state == DIALOG_CREATE_FOLDER) { if (state->dialog_state == DIALOG_CREATE_FILE || state->dialog_state == DIALOG_CREATE_FOLDER) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
// Create button // Create button
if (x >= dlg_x + 50 && x < dlg_x + 130 && if (x >= dlg_x + 50 && x < dlg_x + 130 &&
@ -1279,9 +1280,10 @@ static void explorer_handle_click(Window *win, int x, int y) {
} }
return; return;
} }
return; // Clicked inside dialog but not on button - consume click
} else if (state->dialog_state == DIALOG_DELETE_CONFIRM) { } else if (state->dialog_state == DIALOG_DELETE_CONFIRM) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80; // Adjusted for title bar offset
// Delete button // Delete button
if (x >= dlg_x + 50 && x < dlg_x + 130 && if (x >= dlg_x + 50 && x < dlg_x + 130 &&
@ -1296,9 +1298,10 @@ static void explorer_handle_click(Window *win, int x, int y) {
dialog_close(win); dialog_close(win);
return; return;
} }
return; // Consume click
} else if (state->dialog_state == DIALOG_REPLACE_CONFIRM) { } else if (state->dialog_state == DIALOG_REPLACE_CONFIRM) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) {
dialog_confirm_replace(win); dialog_confirm_replace(win);
@ -1309,9 +1312,10 @@ static void explorer_handle_click(Window *win, int x, int y) {
dialog_close(win); dialog_close(win);
return; return;
} }
return;
} else if (state->dialog_state == DIALOG_REPLACE_MOVE_CONFIRM) { } else if (state->dialog_state == DIALOG_REPLACE_MOVE_CONFIRM) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) {
dialog_confirm_replace_move(win); dialog_confirm_replace_move(win);
@ -1322,9 +1326,10 @@ static void explorer_handle_click(Window *win, int x, int y) {
dialog_close(win); dialog_close(win);
return; return;
} }
return;
} else if (state->dialog_state == DIALOG_CREATE_REPLACE_CONFIRM) { } else if (state->dialog_state == DIALOG_CREATE_REPLACE_CONFIRM) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) { if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 70 && y < dlg_y + 95) {
dialog_force_create_file(win); dialog_force_create_file(win);
@ -1335,20 +1340,22 @@ static void explorer_handle_click(Window *win, int x, int y) {
dialog_close(win); dialog_close(win);
return; return;
} }
return;
} else if (state->dialog_state == DIALOG_ERROR) { } else if (state->dialog_state == DIALOG_ERROR) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
if (x >= dlg_x + 110 && x < dlg_x + 190 && y >= dlg_y + 70 && y < dlg_y + 95) { if (x >= dlg_x + 110 && x < dlg_x + 190 && y >= dlg_y + 70 && y < dlg_y + 95) {
dialog_close(win); dialog_close(win);
return; return;
} }
return;
} else if (state->dialog_state == DIALOG_RENAME) { } else if (state->dialog_state == DIALOG_RENAME) {
int dlg_x = win->w / 2 - 150; int dlg_x = win->w / 2 - 150;
int dlg_y = win->h / 2 - 60; int dlg_y = win->h / 2 - 80;
if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 65 && y < dlg_y + 90) { if (x >= dlg_x + 50 && x < dlg_x + 130 && y >= dlg_y + 65 && y < dlg_y + 90) {
char new_path[256]; char new_path[FAT32_MAX_PATH];
explorer_strcpy(new_path, state->current_path); explorer_strcpy(new_path, state->current_path);
if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/"); if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/");
explorer_strcat(new_path, state->dialog_input); explorer_strcat(new_path, state->dialog_input);
@ -1362,6 +1369,15 @@ static void explorer_handle_click(Window *win, int x, int y) {
dialog_close(win); dialog_close(win);
return; return;
} }
if (x >= dlg_x + 10 && x < dlg_x + 290 && y >= dlg_y + 35 && y < dlg_y + 55) {
state->dialog_input_cursor = (x - dlg_x - 15) / 8;
if (state->dialog_input_cursor > (int)explorer_strlen(state->dialog_input)) {
state->dialog_input_cursor = explorer_strlen(state->dialog_input);
}
return;
}
return; // Consume click
} }
// Handle Drive Menu Selection // Handle Drive Menu Selection
@ -1525,7 +1541,7 @@ static void explorer_handle_key(Window *win, char c) {
} else if (state->dialog_state == DIALOG_CREATE_FOLDER) { } else if (state->dialog_state == DIALOG_CREATE_FOLDER) {
dialog_confirm_create_folder(win); dialog_confirm_create_folder(win);
} else if (state->dialog_state == DIALOG_RENAME) { } else if (state->dialog_state == DIALOG_RENAME) {
char new_path[256]; char new_path[FAT32_MAX_PATH];
explorer_strcpy(new_path, state->current_path); explorer_strcpy(new_path, state->current_path);
if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/"); if (new_path[explorer_strlen(new_path)-1] != '/') explorer_strcat(new_path, "/");
explorer_strcat(new_path, state->dialog_input); explorer_strcat(new_path, state->dialog_input);
@ -1725,7 +1741,7 @@ static void explorer_handle_file_context_menu_click(Window *win, int x, int y) {
if (clicked_action == 0) return; if (clicked_action == 0) return;
// Execute Action // Execute Action
char full_path[256]; char full_path[FAT32_MAX_PATH];
if (state->file_context_menu_item >= 0) { if (state->file_context_menu_item >= 0) {
explorer_strcpy(full_path, state->current_path); explorer_strcpy(full_path, state->current_path);
if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/"); if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/");
@ -1943,6 +1959,8 @@ Window* explorer_create_window(const char *path) {
Window *win = (Window*)kmalloc(sizeof(Window)); Window *win = (Window*)kmalloc(sizeof(Window));
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
if (!state || !win) return NULL;
mem_memset(state, 0, sizeof(ExplorerState));
win->title = "Files"; win->title = "Files";
win->x = 300 + (explorer_win_count * 30); win->x = 300 + (explorer_win_count * 30);
@ -1962,9 +1980,6 @@ Window* explorer_create_window(const char *path) {
state->last_clicked_item = -1; state->last_clicked_item = -1;
state->explorer_scroll_row = 0; state->explorer_scroll_row = 0;
state->dialog_state = DIALOG_NONE; state->dialog_state = DIALOG_NONE;
state->dropdown_menu_visible = false;
state->drive_menu_visible = false;
state->file_context_menu_visible = false;
explorer_wins[explorer_win_count++] = win; explorer_wins[explorer_win_count++] = win;
wm_add_window(win); wm_add_window(win);
@ -1977,6 +1992,9 @@ Window* explorer_create_window(const char *path) {
void explorer_init(void) { void explorer_init(void) {
ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState)); ExplorerState *state = (ExplorerState*)kmalloc(sizeof(ExplorerState));
if (!state) return;
mem_memset(state, 0, sizeof(ExplorerState));
win_explorer.title = "Files"; win_explorer.title = "Files";
win_explorer.x = 300; win_explorer.x = 300;
win_explorer.y = 100; win_explorer.y = 100;
@ -1991,7 +2009,11 @@ void explorer_init(void) {
win_explorer.handle_right_click = explorer_handle_right_click; win_explorer.handle_right_click = explorer_handle_right_click;
win_explorer.data = state; win_explorer.data = state;
state->drive_menu_visible = false; state->selected_item = -1;
state->last_clicked_item = -1;
state->explorer_scroll_row = 0;
state->dialog_state = DIALOG_NONE;
explorer_wins[explorer_win_count++] = &win_explorer; explorer_wins[explorer_win_count++] = &win_explorer;
explorer_load_directory(&win_explorer, "A:/"); explorer_load_directory(&win_explorer, "A:/");
} }

View file

@ -2,6 +2,7 @@
#define EXPLORER_H #define EXPLORER_H
#include "wm.h" #include "wm.h"
#include "fat32.h"
#include <stddef.h> #include <stddef.h>
// External windows references (for opening other apps) // External windows references (for opening other apps)
@ -15,7 +16,7 @@ extern Window win_markdown;
#define DIALOG_INPUT_MAX 256 #define DIALOG_INPUT_MAX 256
typedef struct { typedef struct {
char name[256]; char name[FAT32_MAX_FILENAME];
bool is_directory; bool is_directory;
uint32_t size; uint32_t size;
uint32_t color; uint32_t color;
@ -25,7 +26,7 @@ typedef struct {
ExplorerItem items[EXPLORER_MAX_FILES]; ExplorerItem items[EXPLORER_MAX_FILES];
int item_count; int item_count;
int selected_item; int selected_item;
char current_path[256]; char current_path[FAT32_MAX_PATH];
int last_clicked_item; int last_clicked_item;
uint32_t last_click_time; uint32_t last_click_time;
int explorer_scroll_row; int explorer_scroll_row;
@ -34,11 +35,11 @@ typedef struct {
int dialog_state; int dialog_state;
char dialog_input[DIALOG_INPUT_MAX]; char dialog_input[DIALOG_INPUT_MAX];
int dialog_input_cursor; int dialog_input_cursor;
char dialog_target_path[256]; char dialog_target_path[FAT32_MAX_PATH];
bool dialog_target_is_dir; bool dialog_target_is_dir;
char dialog_dest_dir[256]; char dialog_dest_dir[FAT32_MAX_PATH];
char dialog_creation_path[256]; char dialog_creation_path[FAT32_MAX_PATH];
char dialog_move_src[256]; char dialog_move_src[FAT32_MAX_PATH];
// Dropdown menu state // Dropdown menu state
bool dropdown_menu_visible; bool dropdown_menu_visible;

View file

@ -4,6 +4,7 @@
#include "disk.h" #include "disk.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "wm.h"
#define MAX_FILES 256 #define MAX_FILES 256
@ -87,14 +88,8 @@ static void fs_strcat(char *dest, const char *src) {
fs_strcpy(dest, src); fs_strcpy(dest, src);
} }
static bool fs_ends_with(const char *str, const char *suffix) {
int str_len = fs_strlen(str);
int suffix_len = fs_strlen(suffix);
if (suffix_len > str_len) return false;
return fs_strcmp(str + str_len - suffix_len, suffix) == 0;
}
static bool fs_starts_with(const char *str, const char *prefix) { bool fs_starts_with(const char *str, const char *prefix) {
while (*prefix) { while (*prefix) {
if (*prefix++ != *str++) return false; if (*prefix++ != *str++) return false;
} }
@ -147,8 +142,6 @@ static char parse_drive_from_path(const char **path_ptr) {
// Normalize path (remove .., ., etc) // Normalize path (remove .., ., etc)
void fat32_normalize_path(const char *path, char *normalized) { void fat32_normalize_path(const char *path, char *normalized) {
char temp[FAT32_MAX_PATH]; char temp[FAT32_MAX_PATH];
int temp_len = 0; int temp_len = 0;
const char *p = path; const char *p = path;
@ -167,9 +160,9 @@ void fat32_normalize_path(const char *path, char *normalized) {
while (p[i]) { while (p[i]) {
while (p[i] == '/') i++; while (p[i] == '/') i++;
if (!p[i]) break; if (!p[i]) break;
char component[256]; char component[FAT32_MAX_FILENAME];
int j = 0; int j = 0;
while (p[i] && p[i] != '/' && j < 255) { while (p[i] && p[i] != '/' && j < (FAT32_MAX_FILENAME - 1)) {
component[j++] = p[i++]; component[j++] = p[i++];
} }
component[j] = 0; component[j] = 0;
@ -183,12 +176,15 @@ void fat32_normalize_path(const char *path, char *normalized) {
temp[temp_len] = 0; temp[temp_len] = 0;
} }
} else { } else {
if (temp[temp_len - 1] != '/') { int comp_len = fs_strlen(component);
temp[temp_len++] = '/'; if (temp_len + comp_len + 2 < FAT32_MAX_PATH) {
temp[temp_len] = 0; if (temp[temp_len - 1] != '/') {
temp[temp_len++] = '/';
temp[temp_len] = 0;
}
fs_strcat(temp, component);
temp_len = fs_strlen(temp);
} }
fs_strcat(temp, component);
temp_len = fs_strlen(temp);
} }
} }
if (temp_len > 1 && temp[temp_len - 1] == '/') temp[--temp_len] = 0; if (temp_len > 1 && temp[temp_len - 1] == '/') temp[--temp_len] = 0;
@ -368,6 +364,7 @@ static int ramfs_write(FAT32_FileHandle *handle, const void *buffer, int size) {
break; break;
} }
} }
wm_notify_fs_change();
return bytes_written; return bytes_written;
} }
@ -1137,6 +1134,17 @@ static int realfs_list_directory(char drive, const char *path, FAT32_FileInfo *e
// === Public API (Dispatch) === // === Public API (Dispatch) ===
void fat32_init(void) { void fat32_init(void) {
// Explicitly zero out all structures for RAMFS safety
for (int i = 0; i < MAX_FILES; i++) {
files[i].used = false;
files[i].full_path[0] = 0;
files[i].filename[0] = 0;
files[i].parent_path[0] = 0;
files[i].size = 0;
files[i].attributes = 0;
files[i].start_cluster = 0;
}
// Initialize FAT table for RAMFS // Initialize FAT table for RAMFS
for (int i = 0; i < MAX_CLUSTERS; i++) { for (int i = 0; i < MAX_CLUSTERS; i++) {
fat_table[i] = 0; fat_table[i] = 0;
@ -1144,6 +1152,13 @@ void fat32_init(void) {
fat_table[0] = 0xFFFFFFF8; fat_table[0] = 0xFFFFFFF8;
fat_table[1] = 0xFFFFFFFF; fat_table[1] = 0xFFFFFFFF;
// Zero out cluster data
for (int i = 0; i < MAX_CLUSTERS; i++) {
for (int j = 0; j < FAT32_CLUSTER_SIZE; j++) {
cluster_data[i][j] = 0;
}
}
// Create root directory entry for RAMFS // Create root directory entry for RAMFS
FileEntry *root = ramfs_find_free_entry(); FileEntry *root = ramfs_find_free_entry();
if (root) { if (root) {
@ -1353,6 +1368,7 @@ bool fat32_mkdir(const char *path) {
entry->size = 0; entry->size = 0;
entry->attributes = ATTR_DIRECTORY; entry->attributes = ATTR_DIRECTORY;
wm_notify_fs_change();
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));
return true; return true;
} }
@ -1372,6 +1388,7 @@ bool fat32_rmdir(const char *path) {
} }
entry->used = false; entry->used = false;
wm_notify_fs_change();
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));
return true; return true;
} }
@ -1397,6 +1414,7 @@ bool fat32_delete(const char *path) {
} }
entry->used = false; entry->used = false;
wm_notify_fs_change();
result = true; result = true;
} else { } else {
// Real FAT32 deletion // Real FAT32 deletion
@ -1445,7 +1463,7 @@ bool fat32_rename(const char *old_path, const char *new_path) {
// Check destination // Check destination
if (ramfs_find_file(new_path)) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; } if (ramfs_find_file(new_path)) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; }
int old_len = fs_strlen(old_path); size_t old_len = fs_strlen(old_path);
// Logic from original rename... // Logic from original rename...
for (int i = 0; i < MAX_FILES; i++) { for (int i = 0; i < MAX_FILES; i++) {
if (!files[i].used) continue; if (!files[i].used) continue;
@ -1472,6 +1490,7 @@ bool fat32_rename(const char *old_path, const char *new_path) {
fs_strcat(files[i].parent_path, suffix); fs_strcat(files[i].parent_path, suffix);
} }
} }
wm_notify_fs_change();
asm volatile("push %0; popfq" : : "r"(rflags)); asm volatile("push %0; popfq" : : "r"(rflags));
return true; return true;
} }
@ -1516,16 +1535,14 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
if (drive == 'A') { if (drive == 'A') {
char normalized[FAT32_MAX_PATH]; char normalized[FAT32_MAX_PATH];
fat32_normalize_path(p, normalized); fat32_normalize_path(p, normalized);
FileEntry *dir = ramfs_find_file(normalized);
if (dir && (dir->attributes & ATTR_DIRECTORY)) { for (int i = 0; i < MAX_FILES && count < max_entries; i++) {
for (int i = 0; i < MAX_FILES && count < max_entries; i++) { if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) {
if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) { fs_strcpy(entries[count].name, files[i].filename);
fs_strcpy(entries[count].name, files[i].filename); entries[count].size = files[i].size;
entries[count].size = files[i].size; entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) != 0;
entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) != 0; entries[count].start_cluster = files[i].start_cluster;
entries[count].start_cluster = files[i].start_cluster; count++;
count++;
}
} }
} }
} else { } else {

View file

@ -129,6 +129,7 @@ char fat32_get_current_drive(void);
// Utilities // Utilities
void fat32_normalize_path(const char *path, char *normalized); void fat32_normalize_path(const char *path, char *normalized);
bool fs_starts_with(const char *str, const char *prefix);
// Desktop Limit // Desktop Limit
void fat32_set_desktop_limit(int limit); void fat32_set_desktop_limit(int limit);

View file

@ -75,6 +75,19 @@ void serial_write(const char *str) {
} }
} }
void serial_write_num(uint32_t n) {
if (n >= 10) serial_write_num(n / 10);
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, '0' + (n % 10));
}
void serial_write_hex(uint64_t n) {
char *hex = "0123456789ABCDEF";
if (n >= 16) serial_write_hex(n / 16);
while ((inb(0x3F8 + 5) & 0x20) == 0);
outb(0x3F8, hex[n % 16]);
}
// Kernel Entry Point // Kernel Entry Point
void kmain(void) { void kmain(void) {
init_serial(); init_serial();
@ -83,11 +96,38 @@ void kmain(void) {
platform_init(); platform_init();
serial_write("[DEBUG] platform_init OK\n"); serial_write("[DEBUG] platform_init OK\n");
extern uint64_t hhdm_offset;
extern uint64_t kernel_phys_base;
extern uint64_t kernel_virt_base;
serial_write("[DEBUG] HHDM Offset: 0x");
serial_write_hex(hhdm_offset);
serial_write("\n");
serial_write("[DEBUG] Kernel Phys: 0x");
serial_write_hex(kernel_phys_base);
serial_write("\n");
serial_write("[DEBUG] Kernel Virt: 0x");
serial_write_hex(kernel_virt_base);
serial_write("\n");
uint64_t heap_phys_addr = 0; uint64_t heap_phys_addr = 0;
size_t heap_size = 0; size_t heap_size = 0;
if (memmap_request.response != NULL) { if (memmap_request.response != NULL) {
serial_write("[DEBUG] Memory Map entries: ");
serial_write_num(memmap_request.response->entry_count);
serial_write("\n");
for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) { for (uint64_t i = 0; i < memmap_request.response->entry_count; i++) {
struct limine_memmap_entry *entry = memmap_request.response->entries[i]; struct limine_memmap_entry *entry = memmap_request.response->entries[i];
serial_write("[DEBUG] Map entry ");
serial_write_num(i);
serial_write(": base=");
serial_write_hex(entry->base);
serial_write(" len=");
serial_write_hex(entry->length);
serial_write(" type=");
serial_write_num(entry->type);
serial_write("\n");
if (entry->type == LIMINE_MEMMAP_USABLE) { if (entry->type == LIMINE_MEMMAP_USABLE) {
if (entry->length > heap_size) { if (entry->length > heap_size) {
heap_size = entry->length; heap_size = entry->length;
@ -100,10 +140,15 @@ void kmain(void) {
if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024; if (heap_size > 512 * 1024 * 1024) heap_size = 512 * 1024 * 1024;
if (heap_phys_addr != 0) { if (heap_phys_addr != 0) {
serial_write("[DEBUG] Selected heap base (Phys): 0x");
serial_write_hex(heap_phys_addr);
serial_write(", Size: ");
serial_write_num(heap_size / 1024 / 1024);
serial_write(" MB\n");
memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size); memory_manager_init_at((void*)p2v(heap_phys_addr), heap_size);
serial_write("[DEBUG] memory_manager_init OK\n"); serial_write("[DEBUG] memory_manager_init OK\n");
} else { } else {
serial_write("[DEBUG] ERROR: No usable memory for heap!\n"); serial_write("[DEBUG] ERROR: No usable memory for heap! Check Limine memmap.\n");
hcf(); hcf();
} }
@ -135,26 +180,51 @@ void kmain(void) {
serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n"); serial_write("[DEBUG] Skipping user mode test, proceeding with normal boot.\n");
fat32_init(); fat32_init();
if (module_request.response != NULL) { serial_write("[DEBUG] fat32_init OK\n");
fat32_mkdir("/bin");
serial_write("[DEBUG] /bin directory created/checked\n");
if (module_request.response == NULL) {
serial_write("[DEBUG] ERROR: Limine Module Response is NULL!\n");
} else {
serial_write("[DEBUG] Limine Module Response found. Count: ");
serial_write_num(module_request.response->module_count);
serial_write("\n");
for (uint64_t i = 0; i < module_request.response->module_count; i++) { for (uint64_t i = 0; i < module_request.response->module_count; i++) {
struct limine_file *mod = module_request.response->modules[i]; struct limine_file *mod = module_request.response->modules[i];
FAT32_FileHandle *fh = fat32_open(mod->path, "w"); serial_write("[DEBUG] Found module: ");
serial_write(mod->path);
serial_write(" adr=0x");
serial_write_hex((uint64_t)mod->address);
serial_write(" size=");
serial_write_num(mod->size);
serial_write("\n");
const char *clean_path = mod->path;
// Strip boot():/ or boot:/// prefixes common in different Limine versions
if (fs_starts_with(clean_path, "boot():")) clean_path += 7;
else if (fs_starts_with(clean_path, "boot:///")) clean_path += 8;
serial_write("[DEBUG] Stripped module path: ");
serial_write(clean_path);
serial_write("\n");
FAT32_FileHandle *fh = fat32_open(clean_path, "w");
if (fh && fh->valid) { if (fh && fh->valid) {
fat32_write(fh, mod->address, mod->size); int written = fat32_write(fh, mod->address, mod->size);
fat32_close(fh); fat32_close(fh);
serial_write("[DEBUG] Limine Module loaded into RAMFS: "); serial_write("[DEBUG] Module successfully copied to RAMFS. Written bytes: ");
serial_write(mod->path); serial_write_num(written);
serial_write("\n");
} else {
serial_write("[DEBUG] ERROR: Failed to create file in RAMFS for module: ");
serial_write(clean_path);
serial_write("\n"); serial_write("\n");
} }
} }
} }
int ENABLE_USER_TEST = 1;
#ifdef ENABLE_USER_TEST
process_init();
#endif
asm("cli"); asm("cli");
ps2_init(); ps2_init();
asm("sti"); asm("sti");

View file

@ -11,9 +11,9 @@ static volatile struct limine_kernel_address_request kernel_addr_request __attri
.revision = 0, .revision = 0,
.response = NULL .response = NULL
}; };
static uint64_t hhdm_offset = 0; uint64_t hhdm_offset = 0;
static uint64_t kernel_phys_base = 0; uint64_t kernel_phys_base = 0;
static uint64_t kernel_virt_base = 0; uint64_t kernel_virt_base = 0;
void platform_init(void) { void platform_init(void) {
if (hhdm_request.response) { hhdm_offset = hhdm_request.response->offset; } if (hhdm_request.response) { hhdm_offset = hhdm_request.response->offset; }
if (kernel_addr_request.response) { if (kernel_addr_request.response) {

View file

@ -61,7 +61,7 @@ static int drag_offset_y = 0;
// File Dragging State // File Dragging State
bool is_dragging_file = false; bool is_dragging_file = false;
static char drag_file_path[256]; static char drag_file_path[FAT32_MAX_PATH];
static int drag_icon_type = 0; static int drag_icon_type = 0;
static int drag_start_x = 0; static int drag_start_x = 0;
static int drag_start_y = 0; static int drag_start_y = 0;
@ -83,6 +83,8 @@ static bool cursor_visible = true;
static int last_cursor_x = 400; static int last_cursor_x = 400;
static int last_cursor_y = 300; static int last_cursor_y = 300;
static bool periodic_refresh_pending = false;
// --- Desktop State --- // --- Desktop State ---
#define MAX_DESKTOP_ICONS 32 #define MAX_DESKTOP_ICONS 32
typedef struct { typedef struct {
@ -509,7 +511,7 @@ void draw_elf_icon(int x, int y, const char *label) {
#define THUMB_CACHE_SIZE 8 #define THUMB_CACHE_SIZE 8
#define THUMB_PIXELS (48 * 48) #define THUMB_PIXELS (48 * 48)
static struct { static struct {
char path[256]; char path[FAT32_MAX_PATH];
uint32_t pixels[THUMB_PIXELS]; uint32_t pixels[THUMB_PIXELS];
bool valid; bool valid;
bool failed; // Mark as failed so we don't retry bool failed; // Mark as failed so we don't retry
@ -518,7 +520,7 @@ static int thumb_cache_next = 0; // Round-robin eviction
// Deferred Thumbnail Request Queue // Deferred Thumbnail Request Queue
#define THUMB_QUEUE_SIZE 16 #define THUMB_QUEUE_SIZE 16
static char thumb_request_queue[THUMB_QUEUE_SIZE][256]; static char thumb_request_queue[THUMB_QUEUE_SIZE][FAT32_MAX_PATH];
static int thumb_queue_head = 0; static int thumb_queue_head = 0;
static int thumb_queue_tail = 0; static int thumb_queue_tail = 0;
@ -2318,6 +2320,15 @@ void wm_handle_key(char c) {
} }
void wm_process_input(void) { void wm_process_input(void) {
if (periodic_refresh_pending) {
if (!is_dragging && !is_dragging_file) {
refresh_desktop_icons();
explorer_refresh_all();
force_redraw = true;
}
periodic_refresh_pending = false;
}
uint64_t rflags; uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags)); asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
while (key_head != key_tail) { while (key_head != key_tail) {
@ -2399,17 +2410,9 @@ void wm_timer_tick(void) {
timer_ticks++; timer_ticks++;
if (!is_dragging && !is_dragging_file) { if (!is_dragging && !is_dragging_file) {
desktop_refresh_timer++; // Periodic refresh removed - now triggered by FS events
if (desktop_refresh_timer >= 300) {
refresh_desktop_icons();
explorer_refresh_all();
desktop_refresh_timer = 0;
force_redraw = true;
}
} }
static uint8_t last_second = 0xFF; static uint8_t last_second = 0xFF;
outb(0x70, 0x00); outb(0x70, 0x00);
@ -2432,3 +2435,7 @@ void wm_timer_tick(void) {
graphics_clear_dirty(); graphics_clear_dirty();
} }
} }
void wm_notify_fs_change(void) {
periodic_refresh_pending = true;
}

View file

@ -79,6 +79,7 @@ void wm_timer_tick(void);
uint32_t wm_get_ticks(void); uint32_t wm_get_ticks(void);
int wm_get_desktop_icon_count(void); int wm_get_desktop_icon_count(void);
void wm_show_message(const char *title, const char *message); void wm_show_message(const char *title, const char *message);
void wm_notify_fs_change(void);
// Hook for external rendering (e.g. VM overlay) // Hook for external rendering (e.g. VM overlay)
extern void (*wm_custom_paint_hook)(void); extern void (*wm_custom_paint_hook)(void);