#![no_std]
extern crate vga_rs;
use vga_rs::*;
extern crate cursor_rs;
use cursor_rs::*;
#[derive(Debug)]
pub struct VgaOutStream {
vgabuffer: VgaBuffer,
}
impl VgaOutStream {
pub const HIGH: usize = VgaBuffer::HIGH;
pub const WIDTH: usize = VgaBuffer::WIDTH;
pub const TABSIZE: usize = 4;
pub const TABCHAR: u8 = b' ';
#[inline]
pub fn new_from(vgabuffer: VgaBuffer) -> Self {
Self {
vgabuffer: vgabuffer,
}
}
#[inline]
pub fn new() -> Self {
Self {
vgabuffer: VgaBuffer::new(),
}
}
pub fn reset_with(&mut self, fgcolor: vga_rs::Color, bgcolor: vga_rs::Color) {
for vchar in self.vgabuffer.as_mut_slice().iter_mut() {
let attribute = Attribute::new(fgcolor, bgcolor);
vchar.set_volatile(VgaChar::new(0u8, attribute));
}
VgaCursor::new().set(0, 0);
}
pub fn reset(&mut self) {
for vchar_ref in self.vgabuffer.as_mut_slice().iter_mut() {
let mut vchar = vchar_ref.get_volatile();
vchar.codepoint = 0u8;
vchar_ref.set_volatile(vchar);
}
VgaCursor::new().set(0, 0);
}
pub fn scroll(&mut self) {
for y in 0usize..(Self::HIGH - 1) {
for x in 0usize..(Self::WIDTH) {
let vchar = self.vgabuffer.get(y + 1, x);
self.vgabuffer.set(vchar, y, x);
}
}
for x in 0..Self::WIDTH {
let y = Self::HIGH - 1;
let attribute = Attribute::from_u8(self.vgabuffer.get(y, x).attribute);
let vchar = VgaChar::new(0u8, attribute);
self.vgabuffer.set(vchar, y, x);
}
}
pub fn vgabuffer(&mut self) -> &mut VgaBuffer {
&mut self.vgabuffer
}
}
pub enum VgaStreamError {
OutOfRange,
OverBuffer,
}
pub trait VgaRead {
fn read(&self, y: usize, x: usize) -> Result<u8, VgaStreamError>;
fn read_buffer(&self, buffer: &mut [u8], y: usize, x: usize) -> Result<(), VgaStreamError>;
}
pub trait VgaWrite {
fn write(&mut self, ch: u8) -> Result<(), VgaStreamError>;
fn write_buffer(&mut self, text: &[u8]) -> Result<(), VgaStreamError> {
for &ch in text.iter() {
self.write(ch)?;
}
Ok(())
}
}
impl VgaWrite for VgaOutStream {
fn write(&mut self, ch: u8) -> Result<(), VgaStreamError> {
let (y, x) = VgaCursor::new().get();
let mut vchar = self.vgabuffer.get(y, x);
vchar.codepoint = ch;
let (y, x) = if ch == b'\n' {
(y + 1, 0usize)
} else if ch == b'\t' {
let new_x = if x + Self::TABSIZE < Self::WIDTH {
x + Self::TABSIZE
} else {
Self::WIDTH - 1
};
vchar.codepoint = Self::TABCHAR;
for i in x..new_x {
self.vgabuffer.set(vchar, y, i);
}
(y, new_x)
} else {
self.vgabuffer.set(vchar, y, x);
let y = y + ((x + 1) / Self::WIDTH);
let x = (x + 1) % Self::WIDTH;
(y, x)
};
let y = if y >= Self::HIGH {
self.scroll();
Self::HIGH - 1
} else {
y
};
VgaCursor::new().set(y, x);
Ok(())
}
}
use core::fmt::{Error, Write};
impl Write for VgaOutStream {
fn write_str(&mut self, s: &str) -> Result<(), Error> {
match self.write_buffer(s.as_bytes()) {
Ok(_) => Ok(()),
_ => Err(Error),
}
}
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {{
let _ = core::fmt::write(&mut vgastream_rs::VgaOutStream::new(),format_args!($($arg)*));
}};
}
#[macro_export]
macro_rules! println {
($($arg:tt)*) => {{
print!($($arg)*);
print!("\n");
}};
}
#[macro_export]
macro_rules! eprint {
($($arg:tt)*) => {{
print!($($arg)*);
}};
}
#[macro_export]
macro_rules! eprintln {
($($arg:tt)*) => {{
println!($($arg)*);
}};
}
pub mod prelude {
pub use crate::*;
pub extern crate cursor_rs;
pub extern crate vga_rs;
}