summaryrefslogtreecommitdiff
path: root/src/vga/buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/vga/buffer.rs')
-rw-r--r--src/vga/buffer.rs257
1 files changed, 128 insertions, 129 deletions
diff --git a/src/vga/buffer.rs b/src/vga/buffer.rs
index 4ca001c..1ae4ff8 100644
--- a/src/vga/buffer.rs
+++ b/src/vga/buffer.rs
@@ -1,14 +1,14 @@
use super::*;
+use crate::sync::interface::Mutex;
+use crate::sync::NullLock;
use core::fmt;
use volatile::Volatile;
-use crate::sync::NullLock;
-use crate::sync::interface::Mutex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
struct ScreenChar {
- ascii_character: u8,
- color_code: ColorCode,
+ ascii_character: u8,
+ color_code: ColorCode,
}
const BUFFER_HEIGHT: usize = 25;
@@ -16,128 +16,127 @@ const BUFFER_WIDTH: usize = 80;
#[repr(transparent)]
struct Buffer {
- chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
+ chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
pub struct VgaWriter {
- column_position: usize,
- color_code: ColorCode,
- buffer: Option<&'static mut Buffer>,
+ column_position: usize,
+ color_code: ColorCode,
+ buffer: Option<&'static mut Buffer>,
}
impl VgaWriter {
- pub fn write_byte(&mut self, byte: u8) {
- match byte {
- b'\n' => self.new_line(),
- byte => {
- if self.column_position >= BUFFER_WIDTH {
- self.new_line();
- }
-
- let row = BUFFER_HEIGHT - 1;
- let col = self.column_position;
-
- let color_code = self.color_code;
- if let Some(buffer) = &mut self.buffer {
- buffer.chars[row][col].write(ScreenChar {
-ascii_character: byte,
-color_code,
-});
- }
- self.column_position += 1;
- }
- }
- }
-
- fn new_line(&mut self) {
- for row in 1..BUFFER_HEIGHT {
- for col in 0..BUFFER_WIDTH {
- if let Some(buffer) = &mut self.buffer {
- let character = buffer.chars[row][col].read();
- buffer.chars[row - 1][col].write(character);
- }
- }
- }
- self.clear_row(BUFFER_HEIGHT - 1);
- self.column_position = 0;
- }
-
- fn clear_row(&mut self, row: usize) {
- let blank = ScreenChar {
- ascii_character: b' ',
- color_code: self.color_code,
- };
- for col in 0..BUFFER_WIDTH {
- if let Some(buffer) = &mut self.buffer {
- buffer.chars[row][col].write(blank);
- }
- }
- }
-
- pub fn write_string(&mut self, s: &str) {
- for byte in s.bytes() {
- match byte {
- // printable ASCII byte or newline
- 0x20..=0x7e | b'\n' => self.write_byte(byte),
- // not part of printable ASCII range
- _ => self.write_byte(0xfe),
- }
-
- }
- }
+ pub fn write_byte(&mut self, byte: u8) {
+ match byte {
+ b'\n' => self.new_line(),
+ byte => {
+ if self.column_position >= BUFFER_WIDTH {
+ self.new_line();
+ }
+
+ let row = BUFFER_HEIGHT - 1;
+ let col = self.column_position;
+
+ let color_code = self.color_code;
+ if let Some(buffer) = &mut self.buffer {
+ buffer.chars[row][col].write(ScreenChar {
+ ascii_character: byte,
+ color_code,
+ });
+ }
+ self.column_position += 1;
+ }
+ }
+ }
+
+ fn new_line(&mut self) {
+ for row in 1..BUFFER_HEIGHT {
+ for col in 0..BUFFER_WIDTH {
+ if let Some(buffer) = &mut self.buffer {
+ let character = buffer.chars[row][col].read();
+ buffer.chars[row - 1][col].write(character);
+ }
+ }
+ }
+ self.clear_row(BUFFER_HEIGHT - 1);
+ self.column_position = 0;
+ }
+
+ fn clear_row(&mut self, row: usize) {
+ let blank = ScreenChar {
+ ascii_character: b' ',
+ color_code: self.color_code,
+ };
+ for col in 0..BUFFER_WIDTH {
+ if let Some(buffer) = &mut self.buffer {
+ buffer.chars[row][col].write(blank);
+ }
+ }
+ }
+
+ pub fn write_string(&mut self, s: &str) {
+ for byte in s.bytes() {
+ match byte {
+ // printable ASCII byte or newline
+ 0x20..=0x7e | b'\n' => self.write_byte(byte),
+ // not part of printable ASCII range
+ _ => self.write_byte(0xfe),
+ }
+ }
+ }
}
impl NullLock<VgaWriter> {
- #[allow(dead_code)]
- pub fn write_byte(&self, byte: u8) {
- self.lock(|writer| {
- writer.write_byte(byte);
- });
- }
-
- #[allow(dead_code)]
- fn new_line(&self) {
- self.lock(|writer| {
- writer.new_line();
- });
- }
-
- #[allow(dead_code)]
- fn clear_row(&self, row: usize) {
- self.lock(|writer| {
- writer.clear_row(row);
- });
- }
-
- #[allow(dead_code)]
- pub fn write_string(&self, s: &str) {
- self.lock(|writer| {
- writer.write_string(s);
- });
- }
+ #[allow(dead_code)]
+ pub fn write_byte(&self, byte: u8) {
+ self.lock(|writer| {
+ writer.write_byte(byte);
+ });
+ }
+
+ #[allow(dead_code)]
+ fn new_line(&self) {
+ self.lock(|writer| {
+ writer.new_line();
+ });
+ }
+
+ #[allow(dead_code)]
+ fn clear_row(&self, row: usize) {
+ self.lock(|writer| {
+ writer.clear_row(row);
+ });
+ }
+
+ #[allow(dead_code)]
+ pub fn write_string(&self, s: &str) {
+ self.lock(|writer| {
+ writer.write_string(s);
+ });
+ }
}
impl fmt::Write for VgaWriter {
- fn write_str(&mut self, s: &str) -> fmt::Result {
- self.write_string(s);
- Ok(())
- }
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.write_string(s);
+ Ok(())
+ }
}
impl NullLock<VgaWriter> {
- pub fn init(&self) {
- self.lock(|writer| {
- writer.buffer = Some(unsafe { &mut *(0xb8000 as *mut Buffer) });
- })
- }
+ pub fn init(&self) {
+ self.lock(|writer| {
+ writer.buffer = Some(unsafe { &mut *(0xb8000 as *mut Buffer) });
+ })
+ }
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
- use core::fmt::Write;
- WRITER.lock(|writer| {
- writer.write_fmt(args).unwrap();
- });
+ use core::fmt::Write;
+ WRITER.lock(|writer| {
+ writer.write_fmt(args).unwrap();
+ });
}
#[macro_export]
@@ -152,38 +151,38 @@ macro_rules! println {
}
pub static WRITER: NullLock<VgaWriter> = NullLock::new(VgaWriter {
- column_position: 0,
- color_code: ColorCode::new(Color::LightBlue, Color::Black),
- buffer: None,
+ column_position: 0,
+ color_code: ColorCode::new(Color::LightBlue, Color::Black),
+ buffer: None,
});
#[test_case]
fn test_println_simple() {
- println!("test_println_simple output");
+ println!("test_println_simple output");
}
#[test_case]
fn test_println_many() {
- for _ in 0..200 {
- println!("test_println_many output");
- }
+ for _ in 0..200 {
+ println!("test_println_many output");
+ }
}
#[test_case]
fn test_println_output() {
- let s = "Some test string that fits on a single line";
- println!("{}", s);
- for (i, c) in s.chars().enumerate() {
- let screen_char = WRITER.lock(|writer| {
- if let Some(buffer) = &writer.buffer {
- return buffer.chars[BUFFER_HEIGHT - 2][i].read();
- } else {
- return ScreenChar {
- ascii_character: b' ',
- color_code: ColorCode::new(Color::LightBlue, Color::Black),
- };
- }
- });
- assert_eq!(char::from(screen_char.ascii_character), c);
- }
+ let s = "Some test string that fits on a single line";
+ println!("{}", s);
+ for (i, c) in s.chars().enumerate() {
+ let screen_char = WRITER.lock(|writer| {
+ if let Some(buffer) = &writer.buffer {
+ return buffer.chars[BUFFER_HEIGHT - 2][i].read();
+ } else {
+ return ScreenChar {
+ ascii_character: b' ',
+ color_code: ColorCode::new(Color::LightBlue, Color::Black),
+ };
+ }
+ });
+ assert_eq!(char::from(screen_char.ascii_character), c);
+ }
}