feat: change font and release greate tty output
This commit is contained in:
133
kernel/src/tty.rs
Normal file
133
kernel/src/tty.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use core::fmt;
|
||||
use limine::framebuffer::Framebuffer;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C, packed)]
|
||||
struct Psf2Header {
|
||||
magic: u32,
|
||||
version: u32,
|
||||
header_size: u32,
|
||||
flags: u32,
|
||||
num_glyphs: u32,
|
||||
bytes_per_glyph: u32,
|
||||
height: u32,
|
||||
width: u32,
|
||||
}
|
||||
|
||||
pub struct Console<'a> {
|
||||
framebuffer: &'a Framebuffer<'a>,
|
||||
font: &'static [u8],
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
pub fg_color: u32,
|
||||
pub bg_color: u32,
|
||||
}
|
||||
|
||||
impl<'a> Console<'a> {
|
||||
pub fn new(framebuffer: &'a Framebuffer<'a>, font: &'static [u8]) -> Self {
|
||||
Self {
|
||||
framebuffer,
|
||||
font,
|
||||
x: 0,
|
||||
y: 0,
|
||||
fg_color: 0xFFFFFF, // White
|
||||
bg_color: 0x000000, // Black
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_color(&mut self, fg: u32) {
|
||||
self.fg_color = fg;
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
let fb = self.framebuffer;
|
||||
unsafe {
|
||||
core::ptr::write_bytes(fb.addr(), 0, (fb.pitch() * fb.height()) as usize);
|
||||
}
|
||||
self.x = 0;
|
||||
self.y = 0;
|
||||
}
|
||||
|
||||
fn header(&self) -> &Psf2Header {
|
||||
unsafe { &*(self.font.as_ptr() as *const Psf2Header) }
|
||||
}
|
||||
|
||||
fn scroll(&mut self) {
|
||||
let header = self.header();
|
||||
let font_height = header.height as usize;
|
||||
let fb = self.framebuffer;
|
||||
let pitch = fb.pitch() as usize;
|
||||
let height = fb.height() as usize;
|
||||
|
||||
let shift = font_height * pitch;
|
||||
let size = pitch * (height - font_height);
|
||||
|
||||
unsafe {
|
||||
let addr = fb.addr();
|
||||
core::ptr::copy(addr.add(shift), addr, size);
|
||||
core::ptr::write_bytes(addr.add(size), 0, shift);
|
||||
}
|
||||
self.y -= font_height;
|
||||
}
|
||||
|
||||
fn draw_glyph(&mut self, glyph_index: u32, x: usize, y: usize) {
|
||||
let header = self.header();
|
||||
let bytes_per_line = (header.width + 7) / 8;
|
||||
let glyph_offset = header.header_size + (glyph_index * header.bytes_per_glyph);
|
||||
|
||||
let fb = self.framebuffer;
|
||||
let fb_pitch = fb.pitch() as usize;
|
||||
let fb_addr = fb.addr();
|
||||
|
||||
for cy in 0..header.height {
|
||||
let glyph_row = self.font[(glyph_offset + cy * bytes_per_line) as usize];
|
||||
for cx in 0..header.width {
|
||||
if (glyph_row & (0x80 >> cx)) != 0 {
|
||||
let offset = ((y + cy as usize) * fb_pitch) + ((x + cx as usize) * 4);
|
||||
unsafe {
|
||||
fb_addr.add(offset).cast::<u32>().write_volatile(self.fg_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_char(&mut self, c: char) {
|
||||
let (font_width, font_height, num_glyphs) = {
|
||||
let h = self.header();
|
||||
(h.width as usize, h.height as usize, h.num_glyphs)
|
||||
};
|
||||
|
||||
if c == '\n' {
|
||||
self.x = 0;
|
||||
self.y += font_height;
|
||||
} else {
|
||||
if self.x + font_width > self.framebuffer.width() as usize {
|
||||
self.x = 0;
|
||||
self.y += font_height;
|
||||
}
|
||||
|
||||
let glyph_index = if (c as u32) < num_glyphs {
|
||||
c as u32
|
||||
} else {
|
||||
0 // symbol placeholder
|
||||
};
|
||||
|
||||
self.draw_glyph(glyph_index, self.x, self.y);
|
||||
self.x += font_width;
|
||||
}
|
||||
|
||||
if self.y + font_height > self.framebuffer.height() as usize {
|
||||
self.scroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for Console<'_> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
self.write_char(c);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user