const BUFFER_HEIGHT: usize = 25; const BUFFER_WIDTH: usize = 80; #[macro_export] macro_rules! print { ($($arg:tt)*) => ($crate::vga_buffer::_print(format_args!($($arg)*))); } #[macro_export] macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } pub fn clear_screen() { for _ in 0..BUFFER_HEIGHT { println!(""); } } pub fn _print(fmt: ::core::fmt::Arguments) { use core::fmt::Write; static mut WRITER: Writer = Writer::new(Color::LightGreen, Color::Black); let _ = unsafe{WRITER.write_fmt(fmt)}; } pub struct Writer { column_position: usize, color_code: ColorCode, } impl Writer { pub const fn new(foreground: Color, background: Color) -> Writer { Writer { column_position: 0, color_code: ColorCode::new(foreground, background), } } pub fn write_byte(&mut self, byte: u8) { const NEWLINE: u8 = b'\n'; match byte { NEWLINE => self.new_line(), byte => { if self.column_position >= BUFFER_WIDTH { self.new_line() } let row = BUFFER_HEIGHT - 1; let col = self.column_position; Self::buffer().chars[row][col] = ScreenChar { ascii_character: byte, color_code: self.color_code, }; self.column_position += 1; } } } fn buffer() -> &'static mut Buffer { const BUFFER: *mut Buffer = 0xb8000 as *mut _; unsafe{&mut *BUFFER} } fn new_line(&mut self) { let buffer = Self::buffer(); for row in 0..(BUFFER_HEIGHT-1) { buffer.chars[row] = buffer.chars[row + 1] } self.clear_row(BUFFER_HEIGHT-1); self.column_position = 0; } fn clear_row(&mut self, row: usize) { let blank = ScreenChar { ascii_character: ' ' as u8, color_code: self.color_code, }; Self::buffer().chars[row] = [blank; BUFFER_WIDTH]; } } impl ::core::fmt::Write for Writer { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { for byte in s.bytes() { self.write_byte(byte) } Ok(()) } } #[derive(Clone, Copy)] #[allow(dead_code)] #[repr(u8)] pub enum Color { 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, Pink = 13, Yellow = 14, White = 15, } #[derive(Clone, Copy)] struct ColorCode(u8); impl ColorCode { const fn new(foreground: Color, background: Color) -> ColorCode { ColorCode((background as u8) << 4 | (foreground as u8)) } } #[derive(Clone, Copy)] #[repr(packed)] struct ScreenChar { ascii_character: u8, color_code: ColorCode, } struct Buffer { chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], }