98 lines
1.9 KiB
Rust
98 lines
1.9 KiB
Rust
use crate::lazy_static;
|
|
use core::fmt::{Arguments, Write};
|
|
use spin::Mutex;
|
|
use x86_64::instructions::interrupts::without_interrupts;
|
|
|
|
#[repr(u8)]
|
|
pub enum Color {
|
|
Black = 0x0,
|
|
Blue = 0x1,
|
|
Green = 0x2,
|
|
Cyan = 0x3,
|
|
Red = 0x4,
|
|
Magenta = 0x5,
|
|
Brown = 0x6,
|
|
Gray = 0x7,
|
|
}
|
|
|
|
const VGA_COLUMNS: usize = 80;
|
|
const VGA_ROWS: usize = 25;
|
|
|
|
#[repr(transparent)]
|
|
struct Buffer([[(u8, u8); VGA_COLUMNS]; VGA_ROWS]);
|
|
|
|
pub struct VgaWriter {
|
|
buf: &'static mut Buffer,
|
|
row: usize,
|
|
col: usize,
|
|
}
|
|
|
|
impl VgaWriter {
|
|
fn write_byte(&mut self, c: u8) {
|
|
self.buf.0[self.row][self.col] = (c, 0xb);
|
|
self.col += 1;
|
|
if self.col == VGA_COLUMNS {
|
|
self.new_line()
|
|
}
|
|
}
|
|
|
|
fn new_line(&mut self) {
|
|
if self.row == VGA_ROWS - 1 {
|
|
for i in 0..(VGA_ROWS - 1) {
|
|
self.buf.0[i] = self.buf.0[i + 1];
|
|
}
|
|
self.buf.0[VGA_ROWS - 1] = [(0, 0); VGA_COLUMNS];
|
|
} else {
|
|
self.row += 1;
|
|
}
|
|
self.col = 0;
|
|
}
|
|
}
|
|
|
|
impl Write for VgaWriter {
|
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
|
for byte in s.bytes() {
|
|
if byte == b'\n' {
|
|
self.new_line();
|
|
} else {
|
|
self.write_byte(byte);
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
lazy_static! {
|
|
static ref VGA_TEXT: Mutex<VgaWriter> = {
|
|
Mutex::new(VgaWriter {
|
|
buf: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
|
row: 0,
|
|
col: 0,
|
|
})
|
|
};
|
|
}
|
|
|
|
pub fn _print(args: Arguments) {
|
|
without_interrupts(|| {
|
|
write!(VGA_TEXT.lock(), "{}", args).unwrap();
|
|
})
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! print {
|
|
($($t:tt)+) => {
|
|
$crate::vga_text::_print(::core::format_args!($($t)+))
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! println {
|
|
() => {
|
|
$crate::print!("\n")
|
|
};
|
|
($($t:tt)+) => {
|
|
$crate::print!("{}\n", ::core::format_args!($($t)+))
|
|
};
|
|
}
|