// MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI) // Phase 3.5c: The Canvas - Static Framebuffer in BSS // This is our "Video RAM" living in kernel memory. const std = @import("std"); // Resolution: 800x600 @ 32bpp (ARGB) pub const WIDTH: usize = 800; pub const HEIGHT: usize = 600; pub const STRIDE: usize = WIDTH; // The Physical Backing Store (1.9MB in BSS) // Zero-initialized at boot. var fb_memory: [WIDTH * HEIGHT]u32 = [_]u32{0} ** (WIDTH * HEIGHT); // Clip rectangle (for MU_COMMAND_CLIP) var clip_x: i32 = 0; var clip_y: i32 = 0; var clip_w: i32 = WIDTH; var clip_h: i32 = HEIGHT; pub const Rect = struct { x: i32, y: i32, w: i32, h: i32, }; pub fn get_buffer() [*]u32 { return &fb_memory; } pub fn get_buffer_phys() usize { // Identity mapping for now return @intFromPtr(&fb_memory); } pub fn get_size() usize { return WIDTH * HEIGHT * @sizeOf(u32); } pub fn init() void { // Clear to dark blue (Nexus brand) clear(0xFF101030); } pub fn clear(color: u32) void { @memset(&fb_memory, color); } pub fn set_clip(r: Rect) void { clip_x = r.x; clip_y = r.y; clip_w = r.w; clip_h = r.h; } pub fn put_pixel(x: i32, y: i32, color: u32) void { if (x < 0 or y < 0) return; if (x >= @as(i32, @intCast(WIDTH)) or y >= @as(i32, @intCast(HEIGHT))) return; // Clip check if (x < clip_x or x >= clip_x + clip_w) return; if (y < clip_y or y >= clip_y + clip_h) return; const ux: usize = @intCast(x); const uy: usize = @intCast(y); fb_memory[uy * WIDTH + ux] = color; } // Optimized Rect Fill (The Workhorse for microui) pub fn fill_rect(x: i32, y: i32, w: i32, h: i32, color: u32) void { // Clipping to screen var rx = x; var ry = y; var rw = w; var rh = h; if (rx < 0) { rw += rx; rx = 0; } if (ry < 0) { rh += ry; ry = 0; } if (rx + rw > @as(i32, @intCast(WIDTH))) { rw = @as(i32, @intCast(WIDTH)) - rx; } if (ry + rh > @as(i32, @intCast(HEIGHT))) { rh = @as(i32, @intCast(HEIGHT)) - ry; } if (rw <= 0 or rh <= 0) return; // Clip to clip rect if (rx < clip_x) { rw -= (clip_x - rx); rx = clip_x; } if (ry < clip_y) { rh -= (clip_y - ry); ry = clip_y; } if (rx + rw > clip_x + clip_w) { rw = clip_x + clip_w - rx; } if (ry + rh > clip_y + clip_h) { rh = clip_y + clip_h - ry; } if (rw <= 0 or rh <= 0) return; const start_row: usize = @intCast(ry); const end_row: usize = start_row + @as(usize, @intCast(rh)); const start_col: usize = @intCast(rx); const cols: usize = @intCast(rw); var row = start_row; while (row < end_row) : (row += 1) { const offset = row * WIDTH + start_col; @memset(fb_memory[offset .. offset + cols], color); } } // THE FADE (Optimization: Dim pixels instead of clearing) // This creates the "Ghost Trail" effect cheaply. pub fn fade_screen(factor: u8) void { for (&fb_memory) |*pixel| { if (pixel.* == 0) continue; // Extract Green Channel (Assuming 0xAARRGGBB) // We only care about green for the matrix effect var g = (pixel.* >> 8) & 0xFF; if (g > factor) { g -= factor; } else { g = 0; } // Reconstruct: Keep it mostly green but allow it to fade to black // We zero out Red and Blue for the matrix look during fade. pixel.* = (@as(u32, g) << 8) | 0xFF000000; } }