Microkernel thing OS experiment (Zig ⚡)

QoL: replace diy terminal with flanterm

I noticed the existing implementation had issues scrolling in some cases

pci.express 981b0d81 98b9dd04

verified
+2 -3
components/ukernel/arch/aarch64/boot.zig
···
const std = @import("std");
const arch = @import("root.zig");
const common = @import("common");
-
const console = @import("console");
const log = std.log.scoped(.aarch64_init);
pub const limine_requests = struct {
···
pub fn bsp_init() callconv(.c) noreturn {
if (limine_requests.framebuffer.response) |fb_response| {
if (fb_response.framebuffer_count > 0) {
-
const fb = console.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
+
const fb = common.aux.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
common.init_data.framebuffer = fb;
@memset(fb.address[0..64], 0xFF);
}
···
fn initConsole() void {
if (limine_requests.framebuffer.response) |fb_response| {
if (fb_response.framebuffer_count > 0) {
-
const fb = console.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
+
const fb = common.aux.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
common.init_data.framebuffer = fb;
// At this point, log becomes usable
common.init_data.console = console.Console.from_font(fb, console.DefaultFont);
+42 -5
components/ukernel/arch/amd64/boot.zig
···
const arch = @import("root.zig");
const common = @import("common");
const console = @import("console");
+
const flanterm = @import("flanterm");
const log = std.log.scoped(.amd64_init);
const Idt = arch.structures.Idt;
const StandardGdt = arch.structures.gdt.StandardGdt;
···
fn initConsole() void {
if (limine_requests.framebuffer.response) |fb_response| {
if (fb_response.framebuffer_count > 0) {
-
const fb = console.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
+
const fb = common.aux.Framebuffer.from_limine(fb_response.getFramebuffers()[0]);
common.init_data.framebuffer = fb;
-
// At this point, log becomes usable
-
common.init_data.console = console.Console.from_font(fb, console.DefaultFont);
-
common.init_data.console.?.setColor(0x3bcf1d, 0);
+
+
common.init_data.console = flanterm.init(
+
//malloc and free
+
null,
+
null,
+
// fb info
+
fb.address,
+
fb.width,
+
fb.height,
+
fb.pitch,
+
fb.red_mask_size,
+
fb.red_mask_shift,
+
fb.green_mask_size,
+
fb.green_mask_shift,
+
fb.blue_mask_size,
+
fb.blue_mask_shift,
+
// canvas
+
null,
+
// colors
+
flanterm.ansi_colors,
+
flanterm.bold_ansi_colors,
+
// default bg and fg
+
null,
+
null,
+
// default bright bg and fg
+
null,
+
null,
+
// font
+
null,
+
// font width and height
+
0,
+
0,
+
// font spacing
+
1,
+
// font scale x and y
+
0,
+
0,
+
// margin
+
0,
+
);
}
}
}
···
}
pub fn double_fault(stack_frame: *Idt.InterruptStackFrame, err_code: u64) callconv(.{ .x86_64_interrupt = .{} }) noreturn {
-
common.init_data.console.?.setColor(0xf40d17, 0);
log.err("FATAL DOUBLE FAULT @ 0x{x:0>16}, code 0x{x}!!!!!!!!!!!", .{ stack_frame.instruction_pointer, err_code });
log.err("dying...", .{});
arch.instructions.die();
+1 -1
components/ukernel/arch/amd64/interrupts/apic.zig
···
}
pub fn periodic_handler(_: *arch.structures.Idt.InterruptStackFrame) callconv(.{ .x86_64_interrupt = .{} }) void {
-
log.warn("Got an ACPI timer interrupt!", .{});
+
log.warn("Got an APIC timer interrupt!", .{});
singleton.setRegister(.eoi, 0);
}
+10 -6
components/ukernel/build.zig
···
.api_revision = 3,
});
const spinlock_dep = b.dependency("spinlock", .{});
-
const console_dep = b.dependency("console", .{});
+
const flanterm_dep = b.dependency("flanterm", .{});
const limine_mod = limine_dep.module("limine");
-
const console_mod = console_dep.module("console");
const spinlock_mod = spinlock_dep.module("spinlock");
+
const flanterm_mod = b.createModule(.{
+
.root_source_file = b.path("common/aux/flanterm.zig"),
+
});
+
flanterm_mod.addIncludePath(flanterm_dep.path("src"));
+
flanterm_mod.addCSourceFile(.{ .file = flanterm_dep.path("src/flanterm.c") });
+
flanterm_mod.addCSourceFile(.{ .file = flanterm_dep.path("src/flanterm_backends/fb.c") });
const common_mod = b.createModule(.{
.root_source_file = b.path("common/root.zig"),
});
arch_module.addImport("limine", limine_mod);
-
arch_module.addImport("console", console_mod);
+
arch_module.addImport("flanterm", flanterm_mod);
arch_module.addImport("common", common_mod);
-
console_mod.addImport("limine", limine_mod);
-
common_mod.addImport("arch", arch_module);
-
common_mod.addImport("console", console_mod);
common_mod.addImport("spinlock", spinlock_mod);
+
common_mod.addImport("flanterm", flanterm_mod);
+
common_mod.addImport("limine", limine_mod);
const kernel = b.addExecutable(.{
.name = "ukernel",
+4
components/ukernel/build.zig.zon
···
.spinlock = .{ .path = "deps/spinlock" },
.console = .{ .path = "deps/console" },
.build_helpers = .{ .path = "../build_helpers" },
+
.flanterm = .{
+
.url = "git+https://codeberg.org/Mintsuki/Flanterm.git?ref=trunk#55d228ff16234513b0df0dd12de8bc58160fc196",
+
.hash = "N-V-__8AAIPRAQD-ppISTB_g_r_WTCC2e2vDOaJYZc5uhy4w",
+
},
},
.paths = .{
"build.zig",
-73
components/ukernel/common/aux.zig
···
-
const console = @import("console");
-
const common = @import("root.zig");
-
const mm = common.mm;
-
const std = @import("std");
-
const arch = @import("arch");
-
const spinlock = @import("spinlock");
-
-
// Types
-
pub const HardwareDescription = union(enum) {
-
/// Physical address of ACPI RSDP
-
acpi_rsdp: usize,
-
/// Virtual pointer to DTB
-
dtb: *anyopaque,
-
none,
-
};
-
-
pub const InitState = struct {
-
bootmem: mm.bootmem.BootPmm = .{},
-
console: ?console.Console = null,
-
framebuffer: ?console.Framebuffer = null,
-
hardware_description: HardwareDescription = .none,
-
root_task: []align(4096) u8 = undefined,
-
hhdm_slide: usize = 0,
-
};
-
-
var stdout_lock: spinlock.Spinlock = .{};
-
-
pub fn logFn(
-
comptime message_level: std.log.Level,
-
comptime scope: @TypeOf(.enum_literal),
-
comptime format: []const u8,
-
args: anytype,
-
) void {
-
if (common.init_data.console == null) return;
-
-
// Use the same naming as the default logger
-
const level, const color = switch (message_level) {
-
.debug => .{ "D", 0x3bcf1d },
-
.err => .{ "E", 0xff0000 },
-
.info => .{ "I", 0x00bbbb },
-
.warn => .{ "W", 0xfee409 },
-
};
-
// Use same format as default once again
-
const scope_text = switch (scope) {
-
.default => "",
-
else => "<" ++ @tagName(scope) ++ ">",
-
};
-
const prefix = std.fmt.comptimePrint("{s}{s}: ", .{ level, scope_text });
-
-
{
-
stdout_lock.lock();
-
defer stdout_lock.unlock();
-
-
const cons = &common.init_data.console.?;
-
-
cons.setColor(color, 0);
-
cons.writer().print(prefix ++ format ++ "\n", args) catch return;
-
}
-
}
-
-
pub fn panic(msg: []const u8, first_trace_addr: ?usize) noreturn {
-
_ = first_trace_addr;
-
const log = std.log.scoped(.panic);
-
common.init_data.console.?.setColor(0xff0000, 0);
-
log.err("PANIC: {s}", .{msg});
-
var it = std.debug.StackIterator.init(@returnAddress(), @frameAddress());
-
defer it.deinit();
-
while (it.next()) |addr| {
-
if (addr == 0) break;
-
log.err("Addr: 0x{x:0>16}", .{addr});
-
}
-
arch.instructions.die();
-
}
+54
components/ukernel/common/aux/flanterm.zig
···
+
pub const c = @cImport({
+
@cInclude("flanterm.h");
+
@cInclude("flanterm_backends/fb.h");
+
});
+
+
pub const ctx = c.struct_flanterm_context;
+
+
pub const init = c.flanterm_fb_init;
+
+
pub const Color = enum(u8) {
+
black = 30,
+
red = 31,
+
green = 32,
+
yellow = 33,
+
blue = 34,
+
magenta = 35,
+
cyan = 36,
+
white = 37,
+
default = 39,
+
bright_black = 90,
+
bright_red = 91,
+
bright_green = 92,
+
bright_yellow = 93,
+
bright_blue = 94,
+
bright_magenta = 95,
+
bright_cyan = 96,
+
bright_white = 97,
+
};
+
+
var ansi_colors_backing = [8]u32{
+
0x000000, // Black
+
0xff0000, // Red
+
0x37dd21, // Green
+
0xfee409, // Yellow
+
0x1460d2, // Blue
+
0xff005d, // Magenta
+
0x00bbbb, // Cyan
+
0xbbbbbb, // White
+
};
+
pub const ansi_colors: [*]u32 = @ptrCast(&ansi_colors_backing);
+
+
var bold_ansi_colors_backing = [8]u32{
+
0x545454, // Black
+
0xf40d17, // Red
+
0x3bcf1d, // Green
+
0xecc809, // Yellow
+
0x5555ff, // Blue
+
0xff55ff, // Magenta
+
0x6ae3f9, // Cyan
+
0xffffff, // White
+
};
+
pub const bold_ansi_colors: [*]u32 = @ptrCast(&ansi_colors_backing);
+
+
pub const esc_end = "\x1b[0m";
+108
components/ukernel/common/aux/root.zig
···
+
const console = @import("console");
+
const flanterm = @import("flanterm");
+
const common = @import("../root.zig");
+
const mm = common.mm;
+
const std = @import("std");
+
const arch = @import("arch");
+
const spinlock = @import("spinlock");
+
const limine = @import("limine");
+
+
// Types
+
pub const HardwareDescription = union(enum) {
+
/// Physical address of ACPI RSDP
+
acpi_rsdp: usize,
+
/// Virtual pointer to DTB
+
dtb: *anyopaque,
+
none,
+
};
+
+
pub const InitState = struct {
+
bootmem: mm.bootmem.BootPmm = .{},
+
console: ?*flanterm.ctx = null,
+
framebuffer: ?common.aux.Framebuffer = null,
+
hardware_description: HardwareDescription = .none,
+
root_task: []align(4096) u8 = undefined,
+
hhdm_slide: usize = 0,
+
};
+
+
pub const Framebuffer = struct {
+
const Self = @This();
+
address: [*]u32,
+
width: u64,
+
height: u64,
+
pitch: u64,
+
bypp: u16,
+
red_mask_size: u8,
+
red_mask_shift: u8,
+
green_mask_size: u8,
+
green_mask_shift: u8,
+
blue_mask_size: u8,
+
blue_mask_shift: u8,
+
+
pub fn from_limine(fb: *const limine.Framebuffer) Self {
+
return .{
+
.address = @ptrCast(@alignCast(fb.address)),
+
.width = fb.width,
+
.height = fb.height,
+
.pitch = fb.pitch,
+
.red_mask_size = fb.red_mask_size,
+
.red_mask_shift = fb.red_mask_shift,
+
.green_mask_size = fb.green_mask_size,
+
.green_mask_shift = fb.green_mask_shift,
+
.blue_mask_size = fb.blue_mask_size,
+
.blue_mask_shift = fb.blue_mask_shift,
+
.bypp = fb.bpp / 8,
+
};
+
}
+
};
+
+
var stdout_lock: spinlock.Spinlock = .{};
+
+
pub fn logFn(
+
comptime message_level: std.log.Level,
+
comptime scope: @TypeOf(.enum_literal),
+
comptime format: []const u8,
+
args: anytype,
+
) void {
+
if (common.init_data.console == null) return;
+
+
// Use the same naming as the default logger
+
const level, const color: flanterm.Color = switch (message_level) {
+
.debug => .{ "D", .green },
+
.err => .{ "E", .red },
+
.info => .{ "I", .cyan },
+
.warn => .{ "W", .yellow },
+
};
+
// Use same format as default once again
+
const scope_text = switch (scope) {
+
.default => "",
+
else => "<" ++ @tagName(scope) ++ ">",
+
};
+
const prefix = std.fmt.comptimePrint("{s}{s}: ", .{ level, scope_text });
+
+
{
+
const esc_seq = std.fmt.comptimePrint("\x1b[{}m", .{@intFromEnum(color)});
+
stdout_lock.lock();
+
defer stdout_lock.unlock();
+
+
var backing_buf = std.mem.zeroes([512]u8);
+
const buf = std.fmt.bufPrint(backing_buf[0..], esc_seq ++ prefix ++ format ++ flanterm.esc_end ++ "\n", args) catch return;
+
+
flanterm.c.flanterm_write(common.init_data.console, buf.ptr, buf.len);
+
// cons.setColor(color, 0);
+
// cons.writer().print(prefix ++ format ++ "\n", args) catch return;
+
}
+
}
+
+
pub fn panic(msg: []const u8, first_trace_addr: ?usize) noreturn {
+
_ = first_trace_addr;
+
const log = std.log.scoped(.panic);
+
log.err("PANIC: {s}", .{msg});
+
var it = std.debug.StackIterator.init(@returnAddress(), @frameAddress());
+
defer it.deinit();
+
while (it.next()) |addr| {
+
if (addr == 0) break;
+
log.err("Addr: 0x{x:0>16}", .{addr});
+
}
+
arch.instructions.die();
+
}
+1 -1
components/ukernel/common/root.zig
···
-
pub const aux = @import("aux.zig");
+
pub const aux = @import("aux/root.zig");
pub const mm = @import("mm/root.zig");
pub const loadRootTask = loader.loadRootTask;
const loader = @import("loader.zig");
-7
components/ukernel/deps/console/build.zig
···
-
const std = @import("std");
-
-
pub fn build(b: *std.Build) void {
-
_ = b.addModule("console", .{
-
.root_source_file = b.path("console.zig"),
-
});
-
}
-18
components/ukernel/deps/console/build.zig.zon
···
-
.{
-
.name = .console,
-
.fingerprint = 0x3603cfb6f7920fba,
-
.version = "0.0.1",
-
.minimum_zig_version = "0.15.1",
-
.dependencies = .{
-
.limine = .{
-
.path = "../limine-zig",
-
},
-
},
-
.paths = .{
-
"build.zig",
-
"build.zig.zon",
-
"console.zig",
-
"psf2.zig",
-
"fonts",
-
},
-
}
-195
components/ukernel/deps/console/console.zig
···
-
const limine = @import("limine");
-
const builtin = @import("builtin");
-
const psf2 = @import("psf2.zig");
-
pub const Font = psf2.Font;
-
const std = @import("std");
-
const fontdata = @embedFile("fonts/spleen-12x24.psf");
-
const are_we_le = builtin.cpu.arch.endian() == .little;
-
-
pub const DefaultFont = Font.new(fontdata) catch unreachable;
-
-
pub const Framebuffer = struct {
-
const Self = @This();
-
address: [*]u8,
-
width: u64,
-
height: u64,
-
pitch: u64,
-
bypp: u16,
-
red_mask_size: u8,
-
red_mask_shift: u8,
-
green_mask_size: u8,
-
green_mask_shift: u8,
-
blue_mask_size: u8,
-
blue_mask_shift: u8,
-
-
pub fn from_limine(fb: *const limine.Framebuffer) Self {
-
return .{
-
.address = @ptrCast(fb.address),
-
.width = fb.width,
-
.height = fb.height,
-
.pitch = fb.pitch,
-
.red_mask_size = fb.red_mask_size,
-
.red_mask_shift = fb.red_mask_shift,
-
.green_mask_size = fb.green_mask_size,
-
.green_mask_shift = fb.green_mask_shift,
-
.blue_mask_size = fb.blue_mask_size,
-
.blue_mask_shift = fb.blue_mask_shift,
-
.bypp = fb.bpp / 8,
-
};
-
}
-
};
-
-
pub const Console = struct {
-
const Self = @This();
-
const Writer = std.io.GenericWriter(*Self, error{}, write);
-
// framebuffer data
-
fb: Framebuffer,
-
// font
-
font: psf2.Font,
-
// state data
-
current_x: u64 = 0,
-
current_y: u64 = 0,
-
fg_color: u32 = 0xFFFFFFFF,
-
bg_color: u32 = 0,
-
-
pub fn from_font(fb: Framebuffer, font: psf2.Font) Self {
-
return .{
-
.fb = fb,
-
.font = font,
-
};
-
}
-
-
// places a character at the given position
-
pub fn putchar(self: *const Self, ch: u8, cx: u64, cy: u64, fg_val: u32, bg_val: u32) void {
-
// convert colors to bytes
-
const fg_bytes: [4]u8 = @bitCast(if (are_we_le) fg_val else @byteSwap(fg_val));
-
const bg_bytes: [4]u8 = @bitCast(if (are_we_le) bg_val else @byteSwap(bg_val));
-
// initial calculations
-
const bytes_per_line = self.font.hdr.bytesPerLine();
-
const mask_shamt: u5 = @intCast(bytes_per_line * 8 - 1);
-
const mask_initial: u32 = @as(u32, 1) << mask_shamt;
-
const glyph = self.font.getGlyph(ch) catch return;
-
-
// find the screen offset for the beignning of the character
-
// add pitch to go to next line...
-
var offset: u64 = (cy * self.font.hdr.height * self.fb.pitch) + (cx * (self.font.hdr.width + 0) * self.fb.bypp);
-
// run for every line
-
var y: u32 = 0;
-
var mask: u32 = 0;
-
while (y < self.font.hdr.height) : (y += 1) {
-
// initialize the mask and the current line
-
mask = mask_initial;
-
-
// get the current line
-
const line_value: u32 = psf2.readIntTo32(glyph[y * bytes_per_line ..][0..bytes_per_line]);
-
var line_offset: u64 = offset;
-
var x: u32 = 0;
-
while (x < self.font.hdr.width) : (x += 1) {
-
// write the pixel value to the correct position of the screen...
-
if (line_value & mask != 0) {
-
@memcpy(self.fb.address[line_offset..][0..self.fb.bypp], fg_bytes[0..]);
-
} else {
-
@memcpy(self.fb.address[line_offset..][0..self.fb.bypp], bg_bytes[0..]);
-
}
-
line_offset += self.fb.bypp;
-
mask >>= 1;
-
}
-
offset += self.fb.pitch;
-
}
-
}
-
-
pub fn putc(self: *Self, ch: u8) void {
-
// input can be \r, \n, or printable.
-
// ignore \r, move down for \n, and print char normally
-
// if \n, check to see if we overrun then scroll
-
// if normal, see if we overrun the end and do newline
-
if (ch == '\r') return;
-
if (ch == '\n') {
-
self.current_x = 0;
-
self.current_y += 1;
-
// go to top if we went below the bottom of the screen
-
if (self.current_y >= self.maxCharsHeight()) {
-
self.scrollUp(1);
-
self.current_y = self.maxCharsHeight() - 1;
-
}
-
return;
-
}
-
self.putchar(ch, self.current_x, self.current_y, self.fg_color, self.bg_color);
-
self.current_x += 1;
-
-
if (self.current_x < self.maxCharsWidth()) return;
-
self.current_x = 0;
-
self.current_y += 1;
-
if (self.current_y >= self.maxCharsHeight()) {
-
self.scrollUp(1);
-
self.current_y = self.maxCharsHeight() - 1;
-
}
-
}
-
-
pub fn puts(self: *Self, msg: []const u8) void {
-
for (msg) |ch| {
-
self.putc(ch);
-
}
-
}
-
-
fn convertColor(self: *const Self, color: u32) u32 {
-
const mult: u32 = blk: {
-
const width: u4 = @truncate(self.fb.red_mask_size);
-
break :blk (@as(u32, 1) << width) - 1;
-
};
-
const div = 255;
-
const red: u32 = (color >> 16) & 0xFF;
-
const green: u32 = (color >> 8) & 0xFF;
-
const blue: u32 = color & 0xFF;
-
-
const red_shift: u5 = @truncate(self.fb.red_mask_shift);
-
const green_shift: u5 = @truncate(self.fb.green_mask_shift);
-
const blue_shift: u5 = @truncate(self.fb.blue_mask_shift);
-
-
return (((red * mult) / div) << red_shift) | (((green * mult) / div) << green_shift) | (((blue * mult) / div) << blue_shift);
-
}
-
-
pub fn setColor(self: *Self, fg: u32, bg: u32) void {
-
self.fg_color = self.convertColor(fg);
-
self.bg_color = self.convertColor(bg);
-
}
-
-
pub fn writer(self: *Self) Writer {
-
return .{ .context = self };
-
}
-
-
pub fn write(self: *Self, buffer: []const u8) !usize {
-
self.puts(buffer);
-
return buffer.len;
-
}
-
-
// scroll the lines of text, without doing anything else.
-
// erase the first line of text, and memcpy the second line and on up to the first
-
pub fn scrollUp(self: *Self, amount: u64) void {
-
const num_lines = self.maxCharsHeight();
-
const h = self.font.hdr.height;
-
if (amount > num_lines) return; // later just clear the entire screen
-
var i: u64 = amount;
-
while (i < num_lines) : (i += 1) {
-
// for each run, erase the previous line and copy the current line up a line.
-
// const curr_line = self.fb.address[i * h * self.fb.pitch .. (i + 1) * h * self.fb.pitch];
-
const curr_line = self.fb.address[i * h * self.fb.pitch ..][0 .. h * self.fb.pitch];
-
const prev_line = self.fb.address[(i - amount) * h * self.fb.pitch ..][0 .. h * self.fb.pitch];
-
-
@memset(prev_line, 0);
-
@memcpy(prev_line, curr_line);
-
}
-
// finally, delete the last line (s)
-
// const last_line = self.fb.address[(num_lines - amount) * h * self.fb.pitch .. (num_lines) * h * self.fb.pitch];
-
const last_line = self.fb.address[(num_lines - amount) * h * self.fb.pitch ..][0 .. amount * h * self.fb.pitch];
-
@memset(last_line, 0);
-
}
-
-
fn maxCharsWidth(self: *const Self) u64 {
-
return self.fb.width / (self.font.hdr.width + 0);
-
}
-
-
fn maxCharsHeight(self: *const Self) u64 {
-
return self.fb.height / self.font.hdr.height;
-
}
-
};
-24
components/ukernel/deps/console/fonts/LICENSE.spleen
···
-
Copyright (c) 2018-2024, Frederic Cambus
-
All rights reserved.
-
-
Redistribution and use in source and binary forms, with or without
-
modification, are permitted provided that the following conditions are met:
-
-
* Redistributions of source code must retain the above copyright
-
notice, this list of conditions and the following disclaimer.
-
-
* Redistributions in binary form must reproduce the above copyright
-
notice, this list of conditions and the following disclaimer in the
-
documentation and/or other materials provided with the distribution.
-
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
-
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-
POSSIBILITY OF SUCH DAMAGE.
components/ukernel/deps/console/fonts/bold16x32.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/bold8x16.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-12x24.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-16x32.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-32x64.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-5x8.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-6x12.psf

This is a binary file and will not be displayed.

components/ukernel/deps/console/fonts/spleen-8x16.psf

This is a binary file and will not be displayed.

-53
components/ukernel/deps/console/psf2.zig
···
-
const std = @import("std");
-
-
pub const Font = struct {
-
const Self = @This();
-
pub const PsfHeader = extern struct {
-
magic: u32 = 0x864ab572,
-
version: u32,
-
header_size: u32,
-
flags: u32,
-
numglyph: u32,
-
bytes_per_glyph: u32,
-
height: u32,
-
width: u32,
-
-
pub fn bytesPerLine(self: *const PsfHeader) u32 {
-
return (self.width + 7) / 8;
-
}
-
};
-
-
fontdata: []const u8,
-
hdr: PsfHeader,
-
-
pub fn new(fontdata: []const u8) !Self {
-
var ret: Self = undefined;
-
ret.fontdata = fontdata;
-
-
// fill the header properly
-
const hdr_size = @sizeOf(PsfHeader);
-
if (fontdata.len < hdr_size) return error.TooSmall;
-
const hdr_ptr: [*]u8 = @ptrCast(&ret.hdr);
-
@memcpy(hdr_ptr[0..hdr_size], fontdata[0..hdr_size]);
-
-
return ret;
-
}
-
-
pub fn getGlyph(self: *const Self, ch: u8) ![]const u8 {
-
const startpos: u64 = self.hdr.header_size + ch * self.hdr.bytes_per_glyph;
-
const endpos: u64 = startpos + self.hdr.bytes_per_glyph;
-
-
if (self.fontdata.len < endpos) return error.InvalidCharacter;
-
return self.fontdata[startpos..endpos];
-
}
-
};
-
pub fn readIntTo32(buffer: []const u8) u32 {
-
const readInt = std.mem.readInt;
-
return switch (buffer.len) {
-
0 => 0,
-
1 => @intCast(readInt(u8, buffer[0..1], .big)),
-
2 => @intCast(readInt(u16, buffer[0..2], .big)),
-
3 => @intCast(readInt(u24, buffer[0..3], .big)),
-
else => @intCast(readInt(u32, buffer[0..4], .big)),
-
};
-
}