1#![no_std]
24
25extern crate vgainfo_rs;
26
27#[repr(transparent)]
29#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
30pub struct Color(u8);
31
32impl Color {
33 pub const BLACK: Color = Color(0u8);
34 pub const BLUE: Color = Color(1);
35 pub const GREEN: Color = Color(2);
36 pub const CYAN: Color = Color(3);
37 pub const RED: Color = Color(4);
38 pub const MAGENTA: Color = Color(5);
39 pub const BROWN: Color = Color(6);
40 pub const LIGHTGRAY: Color = Color(7);
41 pub const DARKGRAY: Color = Color(8);
42 pub const LIGHTBLUE: Color = Color(9);
43 pub const LIGHTGREEN: Color = Color(10);
44 pub const LIGHTCYAN: Color = Color(11);
45 pub const LIGHTRED: Color = Color(12);
46 pub const PINK: Color = Color(13);
47 pub const YELLOW: Color = Color(14);
48 pub const WHITE: Color = Color(15);
49
50 pub const EXTRA: Color = Color(1u8 << 3);
51}
52
53impl Color {
54 pub const fn new(b: bool, g: bool, r: bool, extra: bool) -> Self {
56 Self(
57 if b { 1u8 << 0 } else { 0u8 }
58 | if g { 1u8 << 1 } else { 0u8 }
59 | if r { 1u8 << 2 } else { 0u8 }
60 | if extra { 1u8 << 3 } else { 0u8 },
61 )
62 }
63
64 #[inline]
66 pub const fn from_u8(bit: u8) -> Self {
67 Self(bit)
68 }
69
70 pub const fn from_u8_checked(bit: u8) -> Option<Self> {
72 match bit & 0xf0 {
73 0u8 => Some(Self(bit)),
74 _ => None,
75 }
76 }
77
78 #[inline]
80 pub const fn as_u8(self) -> u8 {
81 let Self(x) = self;
82 x
83 }
84}
85
86use core::ops::BitOr;
87impl BitOr for Color {
88 type Output = Self;
89
90 fn bitor(self, rhs: Self) -> Self::Output {
91 let (Self(a), Self(b)) = (self, rhs);
92 Self(a | b)
93 }
94}
95
96#[repr(C, packed)]
98#[derive(Debug, Copy, Clone)]
99pub struct Attribute {
100 pub fgcolor: Color,
101 pub bgcolor: Color,
102}
103
104impl Attribute {
105 #[inline]
107 pub const fn new(fgcolor: Color, bgcolor: Color) -> Self {
108 Self {
109 fgcolor: fgcolor,
110 bgcolor: bgcolor,
111 }
112 }
113
114 #[inline]
116 pub const fn from_u8(bit: u8) -> Self {
117 Self {
118 fgcolor: Color::from_u8(bit & 0x0f),
119 bgcolor: Color::from_u8((bit & 0xf0) >> 4),
120 }
121 }
122
123 #[inline]
125 pub const fn as_u8(self) -> u8 {
126 self.fgcolor.as_u8() | (self.bgcolor.as_u8() << 4)
127 }
128}
129
130#[repr(C, packed)]
132#[derive(Debug, Copy, Clone)]
133pub struct VgaChar {
134 pub codepoint: u8,
135 pub attribute: u8,
136}
137
138impl VgaChar {
139 #[inline]
141 pub const fn new(cp: u8, attr: Attribute) -> Self {
142 Self {
143 codepoint: cp,
144 attribute: attr.as_u8(),
145 }
146 }
147
148 pub fn get_volatile(&self) -> Self {
154 let ptr = self as *const Self;
155 let Self {
156 codepoint,
157 attribute,
158 } = unsafe { ptr.read_volatile() };
159
160 Self::new(codepoint, Attribute::from_u8(attribute))
161 }
162
163 pub fn set_volatile(&mut self, other: Self) {
171 let ptr = self as *mut Self;
172 {
173 unsafe {
174 ptr.write_volatile(other);
175 }
176 };
177 }
178}
179
180use core::ptr::NonNull;
181
182#[derive(Debug)]
184pub struct VgaBuffer {
185 pointer: NonNull<[VgaChar]>,
186}
187
188impl VgaBuffer {
189 pub const VGA_ADDR: usize = vgainfo_rs::VGA_ADDR;
190
191 pub const WIDTH: usize = vgainfo_rs::WIDTH;
192 pub const HIGH: usize = vgainfo_rs::HIGH;
193 pub const LENGTH: usize = vgainfo_rs::LENGTH;
194
195 pub const VGA_PTR: *mut VgaChar = Self::VGA_ADDR as *mut _;
196
197 #[inline]
199 pub const fn to_index(y: usize, x: usize) -> usize {
200 y * Self::WIDTH + x
201 }
202
203 #[inline]
205 pub const fn to_yx(index: usize) -> (usize, usize) {
206 let y = index / Self::WIDTH;
207 let x = index % Self::WIDTH;
208 (y, x)
209 }
210
211 #[inline]
213 pub fn new() -> Self {
214 let nonnull = unsafe { NonNull::new_unchecked(Self::VGA_PTR) };
215 Self {
216 pointer: NonNull::slice_from_raw_parts(nonnull, Self::LENGTH),
217 }
218 }
219
220 pub unsafe fn set_vgachar(&mut self, vchar: VgaChar, y: usize, x: usize) {
222 let index = Self::to_index(y, x);
223 self.pointer
224 .as_mut()
225 .get_unchecked_mut(index)
226 .set_volatile(vchar);
227 }
228
229 pub unsafe fn get_vgachar(&self, y: usize, x: usize) -> VgaChar {
231 let index = Self::to_index(y, x);
232 self.pointer.as_ref().get_unchecked(index).get_volatile()
233 }
234
235 #[inline]
237 pub fn as_slice<'a>(&self) -> &'a [VgaChar] {
238 unsafe { self.pointer.as_ref() }
239 }
240
241 #[inline]
253 pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [VgaChar] {
254 unsafe { self.pointer.as_mut() }
255 }
256}
257
258pub trait VgaBufferHal {
260 type Item;
261
262 fn set(&mut self, item: Self::Item, y: usize, x: usize);
264
265 fn get(&self, y: usize, x: usize) -> Self::Item;
267}
268
269impl VgaBufferHal for VgaBuffer {
270 type Item = VgaChar;
271
272 #[inline]
273 fn set(&mut self, item: Self::Item, y: usize, x: usize) {
274 unsafe { self.set_vgachar(item, y, x) };
275 }
276
277 #[inline]
278 fn get(&self, y: usize, x: usize) -> Self::Item {
279 unsafe { self.get_vgachar(y, x) }
280 }
281}