Initial commit
This commit is contained in:
commit
dc6f7e486f
9 changed files with 427 additions and 0 deletions
135
src/Console.zig
Normal file
135
src/Console.zig
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
const std = @import("std");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init() Self {
|
||||
var self = Self{};
|
||||
self.clear();
|
||||
return self;
|
||||
}
|
||||
|
||||
const vga_width = 80;
|
||||
const vga_height = 25;
|
||||
const vga_size = vga_width * vga_height;
|
||||
|
||||
pub const ConsoleColor = enum(u8) {
|
||||
black = 0,
|
||||
blue = 1,
|
||||
green = 2,
|
||||
cyan = 3,
|
||||
red = 4,
|
||||
magenta = 5,
|
||||
brown = 6,
|
||||
lightGray = 7,
|
||||
darkGray = 8,
|
||||
lightBlue = 9,
|
||||
lightGreen = 10,
|
||||
lightCyan = 11,
|
||||
lightRed = 12,
|
||||
lightMagenta = 13,
|
||||
lightBrown = 14,
|
||||
white = 15,
|
||||
};
|
||||
|
||||
const default_color = vgaEntryColor(ConsoleColor.lightGray, ConsoleColor.black);
|
||||
|
||||
column: usize = 0,
|
||||
color: u8 = default_color,
|
||||
buffer: [*]volatile u16 = @ptrFromInt(0xb8000),
|
||||
|
||||
fn vgaEntryColor(fg: ConsoleColor, bg: ConsoleColor) u8 {
|
||||
return @intFromEnum(fg) | (@intFromEnum(bg) << 4);
|
||||
}
|
||||
|
||||
fn vgaEntry(uc: u8, new_color: u8) u16 {
|
||||
const c: u16 = new_color;
|
||||
return uc | (c << 8);
|
||||
}
|
||||
|
||||
fn index(x: usize, y: usize) usize {
|
||||
return y * vga_width + x;
|
||||
}
|
||||
|
||||
pub fn setColor(self: *Self, fg: ConsoleColor, bg: ConsoleColor) void {
|
||||
self.color = vgaEntryColor(fg, bg);
|
||||
}
|
||||
|
||||
pub fn resetColor(self: *Self) void {
|
||||
self.color = default_color;
|
||||
}
|
||||
|
||||
pub fn clear(self: *Self) void {
|
||||
@memset(self.buffer[0..vga_size], vgaEntry(' ', self.color));
|
||||
}
|
||||
|
||||
fn clearRow(self: *Self, y: usize) void {
|
||||
for (0..vga_width) |x| {
|
||||
const i = index(x, y);
|
||||
self.buffer[i] = vgaEntry(' ', self.color);
|
||||
}
|
||||
}
|
||||
|
||||
fn newLine(self: *Self) void {
|
||||
for (1..vga_height) |y| {
|
||||
for (0..vga_width) |x| {
|
||||
const entry = self.getEntryAt(x, y);
|
||||
self.putEntryAt(entry, x, y - 1);
|
||||
}
|
||||
}
|
||||
self.clearRow(vga_height - 1);
|
||||
self.column = 0;
|
||||
}
|
||||
|
||||
pub fn putCharAt(self: *Self, c: u8, new_color: u8, x: usize, y: usize) void {
|
||||
self.putEntryAt(vgaEntry(c, new_color), x, y);
|
||||
}
|
||||
|
||||
fn putEntryAt(self: *Self, entry: u16, x: usize, y: usize) void {
|
||||
const i = index(x, y);
|
||||
self.buffer[i] = entry;
|
||||
}
|
||||
|
||||
fn getEntryAt(self: *Self, x: usize, y: usize) u16 {
|
||||
const i = index(x, y);
|
||||
return self.buffer[i];
|
||||
}
|
||||
|
||||
pub fn putChar(self: *Self, c: u8) void {
|
||||
switch (c) {
|
||||
'\n' => self.newLine(),
|
||||
else => {
|
||||
if (self.column >= vga_width) {
|
||||
self.newLine();
|
||||
}
|
||||
const y = vga_height - 1;
|
||||
const x = self.column;
|
||||
self.putCharAt(c, self.color, x, y);
|
||||
self.column += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn puts(self: *Self, data: []const u8) void {
|
||||
for (data) |c| {
|
||||
self.putChar(c);
|
||||
}
|
||||
}
|
||||
|
||||
const Writer = std.io.Writer(
|
||||
*Self,
|
||||
error{},
|
||||
callback,
|
||||
);
|
||||
|
||||
pub fn writer(self: *Self) Writer {
|
||||
return .{ .context = self };
|
||||
}
|
||||
|
||||
fn callback(self: *Self, string: []const u8) error{}!usize {
|
||||
self.puts(string);
|
||||
return string.len;
|
||||
}
|
||||
|
||||
pub fn printf(self: *Self, comptime format: []const u8, args: anytype) void {
|
||||
std.fmt.format(self.writer(), format, args) catch unreachable;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue