1 use core::ops::{AddAssign, BitOr, Deref, DerefMut, Shl, Sub};
3 use lazy_static::lazy_static;
5 use volatile::Volatile;
8 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
29 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
31 pub struct ColorCode(u8);
34 pub fn new(foreground: Color, background: Color) -> ColorCode {
35 ColorCode(((background as u8).shl(4) as u8).bitor(foreground as u8))
39 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
43 color_code: ColorCode,
46 impl Deref for ScreenChar {
47 type Target = ScreenChar;
49 fn deref(&self) -> &Self::Target {
54 impl DerefMut for ScreenChar {
55 fn deref_mut(&mut self) -> &mut Self::Target {
60 const BUFFER_WIDTH: usize = 80;
61 const BUFFER_HEIGHT: usize = 25;
65 chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
70 column_position: usize,
71 color_code: ColorCode,
72 buffer: &'static mut Buffer,
76 pub fn write_byte(&mut self, byte: u8) {
78 b'\n' => self.new_line(),
80 if self.column_position >= BUFFER_WIDTH {
84 let row = self.row_position;
85 let col = self.column_position;
87 let color_code = self.color_code;
88 self.buffer.chars[row][col].write(ScreenChar {
89 ascii_character: byte,
93 self.column_position.add_assign(1);
98 pub fn write_string(&mut self, s: &str) {
99 for byte in s.bytes() {
101 // Printable ASCII character or \n
102 0x20..=0x7e | b'\n' => self.write_byte(byte),
103 // Not printable, write error char instead
104 _ => self.write_byte(0xfe),
109 fn new_line(&mut self) {
110 if self.row_position >= BUFFER_HEIGHT {
111 for row in 1..BUFFER_HEIGHT {
112 for col in 0..BUFFER_WIDTH {
113 let character = self.buffer.chars[row][col].read();
114 self.buffer.chars[row.sub(1)][col].write(character);
118 self.clear_row(BUFFER_HEIGHT.sub(1));
121 self.row_position.add_assign(1);
122 self.column_position = 0;
125 fn clear_row(&mut self, row: usize) {
126 let blank = ScreenChar {
127 ascii_character: b' ',
128 color_code: self.color_code,
131 for col in 0..BUFFER_WIDTH {
132 self.buffer.chars[row][col].write(blank);
138 pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
141 color_code: ColorCode::new(Color::LightGray, Color::Black),
142 buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },