]> git.lizzy.rs Git - loadnothing.git/blob - stage2/src/vga.rs
Volatile VGA buffer access
[loadnothing.git] / stage2 / src / vga.rs
1 use core::ops::{AddAssign, Deref, DerefMut, Shl};
2
3 use volatile::Volatile;
4
5 #[allow(dead_code)]
6 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
7 #[repr(u8)]
8 pub enum Color {
9     Black = 0,
10     Blue = 1,
11     Green = 2,
12     Cyan = 3,
13     Red = 4,
14     Magenta = 5,
15     Brown = 6,
16     LightGray = 7,
17     DarkGray = 8,
18     LightBlue = 9,
19     LightGreen = 10,
20     LightCyan = 11,
21     LightRed = 12,
22     Pink = 13,
23     Yellow = 14,
24     White = 15,
25 }
26
27 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
28 #[repr(transparent)]
29 pub struct ColorCode(u8);
30
31 impl ColorCode {
32     pub fn new(foreground: Color, background: Color) -> ColorCode {
33         ColorCode((background as u8).shl(4) | (foreground as u8))
34     }
35 }
36
37 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
38 #[repr(C)]
39 struct ScreenChar {
40     ascii_character: u8,
41     color_code: ColorCode,
42 }
43
44 impl Deref for ScreenChar {
45     type Target = ScreenChar;
46
47     fn deref(&self) -> &Self::Target {
48         self
49     }
50 }
51
52 impl DerefMut for ScreenChar {
53     fn deref_mut(&mut self) -> &mut Self::Target {
54         self
55     }
56 }
57
58 const BUFFER_WIDTH: usize = 80;
59 const BUFFER_HEIGHT: usize = 25;
60
61 #[repr(transparent)]
62 struct Buffer {
63     chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
64 }
65
66 pub struct Writer {
67     row_position: usize,
68     column_position: usize,
69     color_code: ColorCode,
70     buffer: &'static mut Buffer,
71 }
72
73 impl Writer {
74     pub fn write_byte(&mut self, byte: u8) {
75         match byte {
76             b'\n' => self.new_line(),
77             byte => {
78                 if self.column_position >= BUFFER_WIDTH {
79                     self.new_line();
80                 }
81
82                 let row = self.row_position;
83                 let col = self.column_position;
84
85                 let color_code = self.color_code;
86                 self.buffer.chars[row][col].write(ScreenChar {
87                     ascii_character: byte,
88                     color_code,
89                 });
90
91                 self.column_position.add_assign(1);
92             },
93         }
94     }
95
96     pub fn write_string(&mut self, s: &str) {
97         for byte in s.bytes() {
98             match byte {
99                 // Printable ASCII character or \n
100                 0x20..=0x7e | b'\n' => self.write_byte(byte),
101                 // Not printable, write error char instead
102                 _ => self.write_byte(0xfe),
103             }
104         }
105     }
106
107     fn new_line(&mut self) {
108
109     }
110 }
111
112 pub fn test_print() {
113     let mut writer = Writer {
114         row_position: 1,
115         column_position: 0,
116         color_code: ColorCode::new(Color::Yellow, Color::Black),
117         buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
118     };
119
120     writer.write_string("Hello Stage2!");
121 }