1#![no_std]
35
36extern crate vga_rs;
37use vga_rs::*;
38
39extern crate cursor_rs;
40use cursor_rs::*;
41
42pub mod vga_screen {
45
46 use super::*;
47
48 pub fn reset_with((fgcolor, bgcolor): (Color, Color)) {
50 for vchar in VgaBuffer::new().as_mut_slice().iter_mut() {
51 let attribute = Attribute::new(fgcolor, bgcolor);
52 vchar.set_volatile(VgaChar::new(0u8, attribute));
53 }
54 VgaCursor::new().set(0, 0);
55 }
56
57 pub fn reset() {
59 for vchar_ref in VgaBuffer::new().as_mut_slice().iter_mut() {
60 let mut vchar = vchar_ref.get_volatile();
61 vchar.codepoint = 0u8;
62 vchar_ref.set_volatile(vchar);
63 }
64 VgaCursor::new().set(0, 0);
65 }
66
67 pub fn set_fgcolor(fgcolor: Color) {
69 for vchar_ref in VgaBuffer::new().as_mut_slice().iter_mut() {
70 let mut vchar = vchar_ref.get_volatile();
71 let mut attribute = Attribute::from_u8(vchar.attribute);
72 attribute.fgcolor = fgcolor;
73 vchar.attribute = attribute.as_u8();
74 vchar_ref.set_volatile(vchar);
75 }
76 }
77
78 pub fn set_bgcolor(bgcolor: Color) {
80 for vchar_ref in VgaBuffer::new().as_mut_slice().iter_mut() {
81 let mut vchar = vchar_ref.get_volatile();
82 let mut attribute = Attribute::from_u8(vchar.attribute);
83 attribute.bgcolor = bgcolor;
84 vchar.attribute = attribute.as_u8();
85 vchar_ref.set_volatile(vchar);
86 }
87 }
88}
89
90#[derive(Debug)]
92pub struct VgaOutStream {
93 vgabuffer: VgaBuffer,
94}
95
96impl VgaOutStream {
97 pub const HIGH: usize = VgaBuffer::HIGH;
98 pub const WIDTH: usize = VgaBuffer::WIDTH;
99
100 pub const TABSIZE: usize = 4;
101 pub const TABCHAR: u8 = b' ';
102
103 #[inline]
105 pub fn new() -> Self {
106 Self {
107 vgabuffer: VgaBuffer::new(),
108 }
109 }
110
111 fn scroll(&mut self) {
113 for y in 0usize..(Self::HIGH - 1) {
114 for x in 0usize..(Self::WIDTH) {
115 let vchar = self.vgabuffer.get(y + 1, x);
116 self.vgabuffer.set(vchar, y, x);
117 }
118 }
119
120 for x in 0..Self::WIDTH {
121 let y = Self::HIGH - 1;
122 let attribute = Attribute::from_u8(self.vgabuffer.get(y, x).attribute);
123 let vchar = VgaChar::new(0u8, attribute);
124 self.vgabuffer.set(vchar, y, x);
125 }
126 }
127}
128
129pub enum VgaStreamError {
131 OutOfRange,
132 OverBuffer,
133}
134
135pub trait VgaRead {
137 fn read(&self, y: usize, x: usize) -> Result<u8, VgaStreamError>;
138
139 fn read_buffer(&self, buffer: &mut [u8], y: usize, x: usize) -> Result<(), VgaStreamError>;
140}
141
142pub trait VgaWrite {
144 fn write(&mut self, ch: u8) -> Result<(), VgaStreamError>;
149
150 fn write_buffer(&mut self, text: &[u8]) -> Result<(), VgaStreamError> {
155 for &ch in text.iter() {
156 self.write(ch)?;
157 }
158
159 Ok(())
160 }
161}
162
163impl VgaWrite for VgaOutStream {
164 fn write(&mut self, ch: u8) -> Result<(), VgaStreamError> {
165 let (y, x) = VgaCursor::new().get();
166 let mut vchar = self.vgabuffer.get(y, x);
167
168 vchar.codepoint = ch;
169
170 let (y, x) = if ch == b'\n' {
171 (y + 1, 0usize)
172 } else if ch == b'\t' {
173 let new_x = if x + Self::TABSIZE < Self::WIDTH {
174 x + Self::TABSIZE
175 } else {
176 Self::WIDTH - 1
177 };
178
179 vchar.codepoint = Self::TABCHAR;
180 for i in x..new_x {
181 self.vgabuffer.set(vchar, y, i);
182 }
183
184 (y, new_x)
185 } else {
186 self.vgabuffer.set(vchar, y, x);
187
188 let y = y + ((x + 1) / Self::WIDTH);
189 let x = (x + 1) % Self::WIDTH;
190
191 (y, x)
192 };
193
194 let y = if y >= Self::HIGH {
195 self.scroll();
196 Self::HIGH - 1
197 } else {
198 y
199 };
200
201 VgaCursor::new().set(y, x);
202
203 Ok(())
204 }
205}
206
207use core::fmt::{Arguments, Error, Write};
208
209impl Write for VgaOutStream {
210 fn write_str(&mut self, s: &str) -> Result<(), Error> {
211 match self.write_buffer(s.as_bytes()) {
212 Ok(_) => Ok(()),
213 _ => Err(Error),
214 }
215 }
216}
217
218#[macro_export]
220macro_rules! print {
221 ($($arg:tt)*) => {{
222 let _ = core::fmt::write(&mut vgastream_rs::VgaOutStream::new(),format_args!($($arg)*));
223 }};
224 }
225
226#[macro_export]
234macro_rules! println {
235 ($($arg:tt)*) => {{
236 print!($($arg)*);
237 print!("\n");
238 }};
239 }
240
241#[macro_export]
243macro_rules! eprint {
244 ($($arg:tt)*) => {{
245 print!($($arg)*);
246 }};
247 }
248
249#[macro_export]
261macro_rules! eprintln {
262 ($($arg:tt)*) => {{
263 println!($($arg)*);
264 }};
265 }
266
267#[derive(Debug)]
269pub struct VgaOutStreamColor {
270 vgabuffer: VgaBuffer,
271 fgcolor: Color,
272 bgcolor: Color,
273 base_fgcolor: Color,
274 base_bgcolor: Color,
275}
276
277impl VgaOutStreamColor {
278 pub const HIGH: usize = VgaBuffer::HIGH;
279 pub const WIDTH: usize = VgaBuffer::WIDTH;
280
281 pub const TABSIZE: usize = 4;
282 pub const TABCHAR: u8 = b' ';
283
284 #[inline]
286 pub fn new(
287 (fgcolor, bgcolor): (Color, Color),
288 (base_fgcolor, base_bgcolor): (Color, Color),
289 ) -> Self {
290 Self {
291 vgabuffer: VgaBuffer::new(),
292 fgcolor: fgcolor,
293 bgcolor: bgcolor,
294 base_fgcolor: base_fgcolor,
295 base_bgcolor: base_bgcolor,
296 }
297 }
298
299 fn scroll(&mut self) {
301 for y in 0usize..(Self::HIGH - 1) {
302 for x in 0usize..(Self::WIDTH) {
303 let vchar = self.vgabuffer.get(y + 1, x);
304 self.vgabuffer.set(vchar, y, x);
305 }
306 }
307
308 for x in 0..Self::WIDTH {
309 let y = Self::HIGH - 1;
310 let attribute = Attribute::new(self.base_fgcolor, self.base_bgcolor);
311 let vchar = VgaChar::new(0u8, attribute);
312 self.vgabuffer.set(vchar, y, x);
313 }
314 }
315
316 #[inline]
318 pub fn set_color(&mut self, (fgcolor, bgcolor): (Color, Color)) {
319 self.fgcolor = fgcolor;
320 self.bgcolor = bgcolor;
321 }
322
323 #[inline]
325 pub fn get_color(&self) -> (Color, Color) {
326 (self.fgcolor, self.bgcolor)
327 }
328
329 #[inline]
331 pub fn get_base_color(&self) -> (Color, Color) {
332 (self.base_fgcolor, self.base_bgcolor)
333 }
334}
335
336impl VgaWrite for VgaOutStreamColor {
337 fn write(&mut self, ch: u8) -> Result<(), VgaStreamError> {
338 let (y, x) = VgaCursor::new().get();
339
340 let attribute = Attribute::new(self.fgcolor, self.bgcolor);
341 let mut vchar = VgaChar::new(ch, attribute);
342
343 let (y, x) = if ch == b'\n' {
344 (y + 1, 0usize)
345 } else if ch == b'\t' {
346 let new_x = if x + Self::TABSIZE < Self::WIDTH {
347 x + Self::TABSIZE
348 } else {
349 Self::WIDTH - 1
350 };
351
352 vchar.codepoint = Self::TABCHAR;
353 for i in x..new_x {
354 self.vgabuffer.set(vchar, y, i);
355 }
356
357 (y, new_x)
358 } else {
359 self.vgabuffer.set(vchar, y, x);
360
361 let y = y + ((x + 1) / Self::WIDTH);
362 let x = (x + 1) % Self::WIDTH;
363
364 (y, x)
365 };
366
367 let y = if y >= Self::HIGH {
368 self.scroll();
369 Self::HIGH - 1
370 } else {
371 y
372 };
373
374 VgaCursor::new().set(y, x);
375
376 Ok(())
377 }
378}
379
380impl Write for VgaOutStreamColor {
381 fn write_str(&mut self, s: &str) -> Result<(), Error> {
382 match self.write_buffer(s.as_bytes()) {
383 Ok(_) => Ok(()),
384 _ => Err(Error),
385 }
386 }
387}
388
389pub trait PrintFmt {
391 fn print_fmt(&mut self, fmt: Arguments<'_>);
407}
408
409impl<T> PrintFmt for T
410where
411 T: Write,
412{
413 #[inline]
414 fn print_fmt(&mut self, fmt: Arguments<'_>) {
415 let _ = self.write_fmt(fmt);
416 }
417}
418
419pub mod prelude {
420 pub use crate::*;
421 pub extern crate cursor_rs;
422 pub extern crate vga_rs;
423}