#![no_std]
extern crate vga_rs;
use vga_rs::*;
extern crate cursor_rs;
use cursor_rs::*;
pub mod vga_screen {
use super::*;
pub fn reset_with((fgcolor, bgcolor): (Color, Color)) {
for vchar in VgaBuffer::new().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() {
for vchar_ref in VgaBuffer::new().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 set_fgcolor(fgcolor: Color) {
for vchar_ref in VgaBuffer::new().as_mut_slice().iter_mut() {
let mut vchar = vchar_ref.get_volatile();
let mut attribute = Attribute::from_u8(vchar.attribute);
attribute.fgcolor = fgcolor;
vchar.attribute = attribute.as_u8();
vchar_ref.set_volatile(vchar);
}
}
pub fn set_bgcolor(bgcolor: Color) {
for vchar_ref in VgaBuffer::new().as_mut_slice().iter_mut() {
let mut vchar = vchar_ref.get_volatile();
let mut attribute = Attribute::from_u8(vchar.attribute);
attribute.bgcolor = bgcolor;
vchar.attribute = attribute.as_u8();
vchar_ref.set_volatile(vchar);
}
}
}
#[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(crate) 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::{Arguments, 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)*);
}};
}
#[derive(Debug)]
pub struct VgaOutStreamColor {
vgabuffer: VgaBuffer,
fgcolor: Color,
bgcolor: Color,
base_fgcolor: Color,
base_bgcolor: Color,
}
impl VgaOutStreamColor {
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,
(fgcolor, bgcolor): (Color, Color),
(base_fgcolor, base_bgcolor): (Color, Color),
) -> Self {
Self {
vgabuffer: vgabuffer,
fgcolor: fgcolor,
bgcolor: bgcolor,
base_fgcolor: base_fgcolor,
base_bgcolor: base_bgcolor,
}
}
#[inline]
pub fn new(
(fgcolor, bgcolor): (Color, Color),
(base_fgcolor, base_bgcolor): (Color, Color),
) -> Self {
Self::new_from(
VgaBuffer::new(),
(fgcolor, bgcolor),
(base_fgcolor, base_bgcolor),
)
}
pub(crate) 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::new(self.base_fgcolor, self.base_bgcolor);
let vchar = VgaChar::new(0u8, attribute);
self.vgabuffer.set(vchar, y, x);
}
}
pub fn vgabuffer(&mut self) -> &mut VgaBuffer {
&mut self.vgabuffer
}
#[inline]
pub fn set_color(&mut self, (fgcolor, bgcolor): (Color, Color)) {
self.fgcolor = fgcolor;
self.bgcolor = bgcolor;
}
#[inline]
pub fn get_color(&self) -> (Color, Color) {
(self.fgcolor, self.bgcolor)
}
#[inline]
pub fn get_base_color(&self) -> (Color, Color) {
(self.base_fgcolor, self.base_bgcolor)
}
}
impl VgaWrite for VgaOutStreamColor {
fn write(&mut self, ch: u8) -> Result<(), VgaStreamError> {
let (y, x) = VgaCursor::new().get();
let attribute = Attribute::new(self.fgcolor, self.bgcolor);
let mut vchar = VgaChar::new(ch, attribute);
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(())
}
}
impl Write for VgaOutStreamColor {
fn write_str(&mut self, s: &str) -> Result<(), Error> {
match self.write_buffer(s.as_bytes()) {
Ok(_) => Ok(()),
_ => Err(Error),
}
}
}
pub trait PrintFmt {
fn print_fmt(&mut self, fmt: Arguments<'_>);
}
impl<T> PrintFmt for T
where
T: Write,
{
#[inline]
fn print_fmt(&mut self, fmt: Arguments<'_>) {
let _ = self.write_fmt(fmt);
}
}
pub mod prelude {
pub use crate::*;
pub extern crate cursor_rs;
pub extern crate vga_rs;
}