From e55291a32a8b3f7b5c105cd79e86f3c19f19b3d4 Mon Sep 17 00:00:00 2001 From: hachem Date: Wed, 7 Oct 2026 21:43:38 +0200 Subject: feat: tty and ttf, you'd think somethn starting with tt would be fun to do... --- boot/boot.zig | 38 ++++++++++++++++++++++++++++++++++++++ boot/fonts.zig | 11 +++++++++++ boot/heap.zig | 46 +++++++++++++++++++++++++++++++--------------- boot/limine.conf | 1 + 4 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 boot/fonts.zig (limited to 'boot') diff --git a/boot/boot.zig b/boot/boot.zig index 4918881..267fc3f 100644 --- a/boot/boot.zig +++ b/boot/boot.zig @@ -9,6 +9,7 @@ const heap = @import("heap.zig"); const vmm = @import("vmm.zig"); const user = @import("user.zig"); const elf = @import("elf.zig"); +const fontdata = @import("fonts.zig"); const keyboard = @import("keyboard.zig"); const timer = @import("timer.zig"); const sched = @import("sched.zig"); @@ -160,6 +161,38 @@ fn kTaskMax() u64 { return sched.taskMax(); } +// i dont actually like implementing fonts in any project +// it be revel or any opengl or vulkan or whatever the fuck +// fonts are always the ugh parts of a projects +// just so much boilerplate +const FontBlob = struct { name: []const u8, phys: u64, size: u64 }; +var g_fonts: [fontdata.fonts.len]FontBlob = undefined; + +fn loadFonts() void { + for (fontdata.fonts, 0..) |f, i| { + const pages = (f.bytes.len + 4095) / 4096; + const phys = pmm.allocContig(pages) orelse @panic("no room for an embedded font"); + @memcpy(@as([*]u8, @ptrFromInt(pmm.physToVirt(phys)))[0..f.bytes.len], f.bytes); + g_fonts[i] = .{ .name = f.name, .phys = phys, .size = f.bytes.len }; + } +} + +fn kFontCount() u64 { + return g_fonts.len; +} + +fn kFontPhys(i: u64) u64 { + return g_fonts[i].phys; +} + +fn kFontName(i: u64) []const u8 { + return g_fonts[i].name; +} + +fn kFontSize(i: u64) u64 { + return g_fonts[i].size; +} + fn kTaskState(i: u64) u64 { return sched.taskState(i); } @@ -206,6 +239,7 @@ export fn _start() callconv(.c) noreturn { ata.init(); loadPrograms(); + loadFonts(); // the event loop below is scheduler task 0 (the kernel), running in the // current cr3. user tasks spawned by `run` get time fucked against it sched.init(vmm.activePml4()); @@ -236,6 +270,10 @@ export fn _start() callconv(.c) noreturn { .disk_read = &kDiskRead, .disk_write = &kDiskWrite, .alloc_contig = &kAllocContig, + .font_count = &kFontCount, + .font_phys = &kFontPhys, + .font_name = &kFontName, + .font_size = &kFontSize, }; // hand the kernel heap + framebuffer + low level ops to revo and bring up the vm diff --git a/boot/fonts.zig b/boot/fonts.zig new file mode 100644 index 0000000..5db8123 --- /dev/null +++ b/boot/fonts.zig @@ -0,0 +1,11 @@ +// js loading fonts from host disk +pub const Font = struct { name: []const u8, bytes: []const u8 }; +pub const fonts = [_]Font{ + .{ .name = "vga16.psf", .bytes = @embedFile("font_vga16") }, + .{ .name = "vga8.psf", .bytes = @embedFile("font_vga8") }, + .{ .name = "sun16.psf", .bytes = @embedFile("font_sun16") }, + .{ .name = "acorn8.psf", .bytes = @embedFile("font_acorn8") }, + .{ .name = "pearl8.psf", .bytes = @embedFile("font_pearl8") }, + .{ .name = "dejavu.ttf", .bytes = @embedFile("font_dejavu") }, + .{ .name = "terminess.ttf", .bytes = @embedFile("font_terminess") }, +}; diff --git a/boot/heap.zig b/boot/heap.zig index badf506..b232585 100644 --- a/boot/heap.zig +++ b/boot/heap.zig @@ -11,6 +11,9 @@ const MIN_BLOCK: usize = 32; // header + a usable scrap, dont split below this var heap_start: usize = 0; var heap_end: usize = 0; +// next fit rover optimization. essentially its resume scanning where hte last +// alloc landed instead of heap_start everytime. it was O(n) before +var rover: usize = 0; inline fn word(b: usize) *usize { return @ptrFromInt(b); @@ -48,25 +51,38 @@ fn allocImpl(_: *anyopaque, len: usize, alignment: std.mem.Alignment, _: usize) if (alignment.toByteUnits() > ALIGN) return null; const need = alignUp(HEADER + len, ALIGN); - var b = heap_start; - while (b < heap_end) { - if (!blkUsed(b)) { - // lazy coalesce - var size = blkSize(b); - while (b + size < heap_end and !blkUsed(b + size)) size += blkSize(b + size); - setBlk(b, size, false); + if (rover < heap_start or rover >= heap_end) rover = heap_start; - if (size >= need) { - if (size >= need + MIN_BLOCK) { - setBlk(b, need, true); - setBlk(b + need, size - need, false); // the leftover tail - } else { - setBlk(b, size, true); + // next fit bull shit + var b = rover; + var limit = heap_end; + var pass: u8 = 0; + while (pass < 2) : (pass += 1) { + while (b < limit) { + if (!blkUsed(b)) { + // lazy coalesce + var size = blkSize(b); + while (b + size < heap_end and !blkUsed(b + size)) size += blkSize(b + size); + setBlk(b, size, false); + + if (size >= need) { + if (size >= need + MIN_BLOCK) { + setBlk(b, need, true); + setBlk(b + need, size - need, false); // the leftover tail + rover = b + need; + } else { + setBlk(b, size, true); + rover = b + size; + } + if (rover >= heap_end) rover = heap_start; + return @ptrFromInt(b + HEADER); } - return @ptrFromInt(b + HEADER); } + b += blkSize(b); } - b += blkSize(b); + // wrap + b = heap_start; + limit = rover; } return null; } diff --git a/boot/limine.conf b/boot/limine.conf index 7398dca..ffeb3b5 100644 --- a/boot/limine.conf +++ b/boot/limine.conf @@ -2,4 +2,5 @@ timeout: 0 /Revel protocol: limine + resolution: 1920x1080x32 path: boot():/boot/revel -- cgit v1.3