Code cleanup

This commit is contained in:
Ryan Kennedy 2020-03-16 17:03:43 -05:00
parent 855c6b8658
commit ac8da132e5
4 changed files with 143 additions and 222 deletions

View file

@ -4,16 +4,112 @@ mod text_40x25;
mod text_40x50; mod text_40x50;
mod text_80x25; mod text_80x25;
use super::colors::TextModeColor; use super::{
colors::{Color16Bit, TextModeColor},
registers::CrtcControllerIndex,
vga::{Vga, VGA},
};
use spinning_top::SpinlockGuard;
pub use graphics_640x480x16::Graphics640x480x16; pub use graphics_640x480x16::Graphics640x480x16;
pub use text_40x25::Text40x25; pub use text_40x25::Text40x25;
pub use text_40x50::Text40x50; pub use text_40x50::Text40x50;
pub use text_80x25::Text80x25; pub use text_80x25::Text80x25;
/// Represents a `ScreenCharacter` in vga text modes.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(C)] #[repr(C)]
struct ScreenCharacter { pub struct ScreenCharacter {
character: u8, character: u8,
color: TextModeColor, color: TextModeColor,
} }
impl ScreenCharacter {
/// Creates a new `ScreenCharacter` with the specified `character`
/// and a `TextModeColor` with the specified `foreground` and `background`.
pub fn new(character: u8, foreground: Color16Bit, background: Color16Bit) -> ScreenCharacter {
let color = TextModeColor::new(foreground, background);
ScreenCharacter { character, color }
}
}
static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
character: b' ',
color: TextModeColor::new(Color16Bit::Yellow, Color16Bit::Black),
};
/// A helper trait used to interact with various vga text modes.
pub trait TextWriter {
/// Returns the width of the `TextWriter`.
fn get_width(&self) -> usize;
/// Returns the height of the `TextWriter`.
fn get_height(&self) -> usize;
/// Sets the graphics device to a video mode as determined by
/// the `TextWriter` implementation.
fn set_mode(&self);
/// Returns the start of the `FrameBuffer` as `*mut ScreenCharacter`
/// as well as a lock to the vga driver. This ensures the vga
/// driver stays locked while the frame buffer is in use.
fn get_frame_buffer(&self) -> (SpinlockGuard<Vga>, *mut ScreenCharacter) {
let mut vga = VGA.lock();
let frame_buffer = vga.get_frame_buffer();
(vga, u32::from(frame_buffer) as *mut ScreenCharacter)
}
/// Clears the screen by setting all cells to `b' '` with
/// a background color of `Color16Bit::Black` and a foreground
/// color of `Color16Bit::Yellow`.
fn clear_screen(&self) {
let (_vga, frame_buffer) = self.get_frame_buffer();
let screen_size = self.get_width() * self.get_height();
for i in 0..screen_size {
unsafe {
frame_buffer.add(i).write_volatile(BLANK_CHARACTER);
}
}
}
/// Sets the current text cursor to the position specified by
/// `x` and `y`.
///
/// Panics if `x >= se.lf.get_width()` or `y >= self.get_height()`.
fn set_cursor_position(&self, x: usize, y: usize) {
let width = self.get_width();
let height = self.get_height();
assert!(x < width, "x >= {}", width);
assert!(y < height, "y >= {}", height);
let offset = width * y + x;
let (mut vga, _frame_buffer) = self.get_frame_buffer();
let emulation_mode = vga.get_emulation_mode();
let cursor_start = offset & 0xFF;
let cursor_end = (offset >> 8) & 0xFF;
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationLow,
cursor_start as u8,
);
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationHigh,
cursor_end as u8,
);
}
/// Prints the given `character` and `color` at `(x, y)`.
///
/// Panics if `x >= self.get_width()` or `y >= self.get_height()`.
fn write_character(&self, x: usize, y: usize, screen_character: ScreenCharacter) {
let width = self.get_width();
let height = self.get_height();
assert!(x < width, "x >= {}", width);
assert!(y < height, "y >= {}", height);
let (_vga, frame_buffer) = self.get_frame_buffer();
let offset = width * y + x;
unsafe {
frame_buffer.add(offset).write_volatile(screen_character);
}
}
}

View file

@ -1,20 +1,12 @@
use super::ScreenCharacter; use super::TextWriter;
use crate::{ use crate::{
colors::{Color16Bit, TextModeColor, DEFAULT_PALETTE}, colors::DEFAULT_PALETTE,
fonts::TEXT_8X16_FONT, fonts::TEXT_8X16_FONT,
registers::CrtcControllerIndex, vga::{VideoMode, VGA},
vga::{Vga, VideoMode, VGA},
}; };
use spinning_top::SpinlockGuard;
const WIDTH: usize = 40; const WIDTH: usize = 40;
const HEIGHT: usize = 25; const HEIGHT: usize = 25;
const SCREEN_SIZE: usize = WIDTH * HEIGHT;
static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
character: b' ',
color: TextModeColor::new(Color16Bit::Yellow, Color16Bit::Black),
};
/// A basic interface for interacting with vga text mode 40x25 /// A basic interface for interacting with vga text mode 40x25
/// ///
@ -23,7 +15,7 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
/// Basic usage: /// Basic usage:
/// ///
/// ```no_run /// ```no_run
/// use vga::writers::Text40x25; /// use vga::writers::{TextWriter, Text40x25};
/// ///
/// let text_mode = Text40x25::new(); /// let text_mode = Text40x25::new();
/// ///
@ -33,41 +25,17 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
#[derive(Default)] #[derive(Default)]
pub struct Text40x25; pub struct Text40x25;
impl Text40x25 { impl TextWriter for Text40x25 {
/// Creates a new `Text40x25`. fn get_width(&self) -> usize {
pub fn new() -> Text40x25 { WIDTH
Text40x25 {}
} }
/// Clears the screen by setting all cells to `b' '` with fn get_height(&self) -> usize {
/// a background color of `Color16Bit::Black` and a foreground HEIGHT
/// color of `Color16Bit::Yellow`.
pub fn clear_screen(&self) {
let (_vga, frame_buffer) = self.get_frame_buffer();
for i in 0..SCREEN_SIZE {
unsafe {
frame_buffer.add(i).write_volatile(BLANK_CHARACTER);
}
}
}
/// Prints the given `character` and `color` at `(x, y)`.
///
/// Panics if `x >= 40` or `y >= 25`.
pub fn write_character(&self, x: usize, y: usize, character: u8, color: TextModeColor) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let (_vga, frame_buffer) = self.get_frame_buffer();
let offset = WIDTH * y + x;
unsafe {
frame_buffer
.add(offset)
.write_volatile(ScreenCharacter { character, color });
}
} }
/// Sets the graphics device to `VideoMode::Mode40x25`. /// Sets the graphics device to `VideoMode::Mode40x25`.
pub fn set_mode(&self) { fn set_mode(&self) {
let mut vga = VGA.lock(); let mut vga = VGA.lock();
vga.set_video_mode(VideoMode::Mode40x25); vga.set_video_mode(VideoMode::Mode40x25);
@ -76,37 +44,11 @@ impl Text40x25 {
vga.load_palette(&DEFAULT_PALETTE); vga.load_palette(&DEFAULT_PALETTE);
vga.load_font(&TEXT_8X16_FONT); vga.load_font(&TEXT_8X16_FONT);
} }
}
/// Sets the current text cursor to the position specified by impl Text40x25 {
/// `x` and `y`. /// Creates a new `Text40x25`.
/// pub fn new() -> Text40x25 {
/// Panics if `x >= 40` or `y >= 25`. Text40x25 {}
pub fn set_cursor_position(&self, x: usize, y: usize) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let offset = WIDTH * y + x;
let (mut vga, _frame_buffer) = self.get_frame_buffer();
let emulation_mode = vga.get_emulation_mode();
let cursor_start = offset & 0xFF;
let cursor_end = (offset >> 8) & 0xFF;
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationLow,
cursor_start as u8,
);
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationHigh,
cursor_end as u8,
);
}
/// Returns the start of the `FrameBuffer` as `*mut ScreenCharacter`
/// as well as a lock to the vga driver. This ensures the vga
/// driver stays locked while the frame buffer is in use.
fn get_frame_buffer(&self) -> (SpinlockGuard<Vga>, *mut ScreenCharacter) {
let mut vga = VGA.lock();
let frame_buffer = vga.get_frame_buffer();
(vga, u32::from(frame_buffer) as *mut ScreenCharacter)
} }
} }

View file

@ -1,20 +1,12 @@
use super::ScreenCharacter; use super::TextWriter;
use crate::{ use crate::{
colors::{Color16Bit, TextModeColor, DEFAULT_PALETTE}, colors::DEFAULT_PALETTE,
fonts::TEXT_8X8_FONT, fonts::TEXT_8X8_FONT,
registers::CrtcControllerIndex, vga::{VideoMode, VGA},
vga::{Vga, VideoMode, VGA},
}; };
use spinning_top::SpinlockGuard;
const WIDTH: usize = 40; const WIDTH: usize = 40;
const HEIGHT: usize = 50; const HEIGHT: usize = 50;
const SCREEN_SIZE: usize = WIDTH * HEIGHT;
static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
character: b' ',
color: TextModeColor::new(Color16Bit::Yellow, Color16Bit::Black),
};
/// A basic interface for interacting with vga text mode 40x50 /// A basic interface for interacting with vga text mode 40x50
/// ///
@ -23,7 +15,7 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
/// Basic usage: /// Basic usage:
/// ///
/// ```no_run /// ```no_run
/// use vga::writers::Text40x50; /// use vga::writers::{TextWriter, Text40x50};
/// ///
/// let text_mode = Text40x50::new(); /// let text_mode = Text40x50::new();
/// ///
@ -33,41 +25,17 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
#[derive(Default)] #[derive(Default)]
pub struct Text40x50; pub struct Text40x50;
impl Text40x50 { impl TextWriter for Text40x50 {
/// Creates a new `Text40x50`. fn get_width(&self) -> usize {
pub fn new() -> Text40x50 { WIDTH
Text40x50 {}
} }
/// Clears the screen by setting all cells to `b' '` with fn get_height(&self) -> usize {
/// a background color of `Color16Bit::Black` and a foreground HEIGHT
/// color of `Color16Bit::Yellow`.
pub fn clear_screen(&self) {
let (_vga, frame_buffer) = self.get_frame_buffer();
for i in 0..SCREEN_SIZE {
unsafe {
frame_buffer.add(i).write_volatile(BLANK_CHARACTER);
}
}
}
/// Prints the given `character` and `color` at `(x, y)`.
///
/// Panics if `x >= 40` or `y >= 50`.
pub fn write_character(&self, x: usize, y: usize, character: u8, color: TextModeColor) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let (_vga, frame_buffer) = self.get_frame_buffer();
let offset = WIDTH * y + x;
unsafe {
frame_buffer
.add(offset)
.write_volatile(ScreenCharacter { character, color });
}
} }
/// Sets the graphics device to `VideoMode::Mode40x50`. /// Sets the graphics device to `VideoMode::Mode40x50`.
pub fn set_mode(&self) { fn set_mode(&self) {
let mut vga = VGA.lock(); let mut vga = VGA.lock();
vga.set_video_mode(VideoMode::Mode40x50); vga.set_video_mode(VideoMode::Mode40x50);
@ -76,37 +44,11 @@ impl Text40x50 {
vga.load_palette(&DEFAULT_PALETTE); vga.load_palette(&DEFAULT_PALETTE);
vga.load_font(&TEXT_8X8_FONT); vga.load_font(&TEXT_8X8_FONT);
} }
}
/// Sets the current text cursor to the position specified by impl Text40x50 {
/// `x` and `y`. /// Creates a new `Text40x50`.
/// pub fn new() -> Text40x50 {
/// Panics if `x >= 40` or `y >= 50`. Text40x50 {}
pub fn set_cursor_position(&self, x: usize, y: usize) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let offset = WIDTH * y + x;
let (mut vga, _frame_buffer) = self.get_frame_buffer();
let emulation_mode = vga.get_emulation_mode();
let cursor_start = offset & 0xFF;
let cursor_end = (offset >> 8) & 0xFF;
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationLow,
cursor_start as u8,
);
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationHigh,
cursor_end as u8,
);
}
/// Returns the start of the `FrameBuffer` as `*mut ScreenCharacter`
/// as well as a lock to the vga driver. This ensures the vga
/// driver stays locked while the frame buffer is in use.
fn get_frame_buffer(&self) -> (SpinlockGuard<Vga>, *mut ScreenCharacter) {
let mut vga = VGA.lock();
let frame_buffer = vga.get_frame_buffer();
(vga, u32::from(frame_buffer) as *mut ScreenCharacter)
} }
} }

View file

@ -1,20 +1,12 @@
use super::ScreenCharacter; use super::TextWriter;
use crate::{ use crate::{
colors::{Color16Bit, TextModeColor, DEFAULT_PALETTE}, colors::DEFAULT_PALETTE,
fonts::TEXT_8X16_FONT, fonts::TEXT_8X16_FONT,
registers::CrtcControllerIndex, vga::{VideoMode, VGA},
vga::{Vga, VideoMode, VGA},
}; };
use spinning_top::SpinlockGuard;
const WIDTH: usize = 80; const WIDTH: usize = 80;
const HEIGHT: usize = 25; const HEIGHT: usize = 25;
const SCREEN_SIZE: usize = WIDTH * HEIGHT;
static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
character: b' ',
color: TextModeColor::new(Color16Bit::Yellow, Color16Bit::Black),
};
/// A basic interface for interacting with vga text mode 80x25 /// A basic interface for interacting with vga text mode 80x25
/// ///
@ -23,7 +15,7 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
/// Basic usage: /// Basic usage:
/// ///
/// ```no_run /// ```no_run
/// use vga::writers::Text80x25; /// use vga::writers::{TextWriter, Text80x25};
/// ///
/// let text_mode = Text80x25::new(); /// let text_mode = Text80x25::new();
/// ///
@ -33,41 +25,16 @@ static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
#[derive(Default)] #[derive(Default)]
pub struct Text80x25; pub struct Text80x25;
impl Text80x25 { impl TextWriter for Text80x25 {
/// Creates a new `Text80x25`. fn get_width(&self) -> usize {
pub fn new() -> Text80x25 { WIDTH
Text80x25 {}
} }
/// Clears the screen by setting all cells to `b' '` with fn get_height(&self) -> usize {
/// a background color of `Color16Bit::Black` and a foreground HEIGHT
/// color of `Color16Bit::Yellow`.
pub fn clear_screen(&self) {
let (_vga, frame_buffer) = self.get_frame_buffer();
for i in 0..SCREEN_SIZE {
unsafe {
frame_buffer.add(i).write_volatile(BLANK_CHARACTER);
}
}
} }
/// Prints the given `character` and `color` at `(x, y)`. fn set_mode(&self) {
///
/// Panics if `x >= 80` or `y >= 25`.
pub fn write_character(&self, x: usize, y: usize, character: u8, color: TextModeColor) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let (_vga, frame_buffer) = self.get_frame_buffer();
let offset = WIDTH * y + x;
unsafe {
frame_buffer
.add(offset)
.write_volatile(ScreenCharacter { character, color });
}
}
/// Sets the graphics device to `VideoMode::Mode80x25`.
pub fn set_mode(&self) {
let mut vga = VGA.lock(); let mut vga = VGA.lock();
vga.set_video_mode(VideoMode::Mode80x25); vga.set_video_mode(VideoMode::Mode80x25);
@ -76,37 +43,11 @@ impl Text80x25 {
vga.load_palette(&DEFAULT_PALETTE); vga.load_palette(&DEFAULT_PALETTE);
vga.load_font(&TEXT_8X16_FONT); vga.load_font(&TEXT_8X16_FONT);
} }
}
/// Sets the current text cursor to the position specified by impl Text80x25 {
/// `x` and `y`. /// Creates a new `Text80x25`.
/// pub fn new() -> Text80x25 {
/// Panics if `x >= 80` or `y >= 25`. Text80x25 {}
pub fn set_cursor_position(&self, x: usize, y: usize) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let offset = WIDTH * y + x;
let (mut vga, _frame_buffer) = self.get_frame_buffer();
let emulation_mode = vga.get_emulation_mode();
let cursor_start = offset & 0xFF;
let cursor_end = (offset >> 8) & 0xFF;
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationLow,
cursor_start as u8,
);
vga.write_crtc_controller(
emulation_mode,
CrtcControllerIndex::TextCursorLocationHigh,
cursor_end as u8,
);
}
/// Returns the start of the `FrameBuffer` as `*mut ScreenCharacter`
/// as well as a lock to the vga driver. This ensures the vga
/// driver stays locked while the frame buffer is in use.
fn get_frame_buffer(&self) -> (SpinlockGuard<Vga>, *mut ScreenCharacter) {
let mut vga = VGA.lock();
let frame_buffer = vga.get_frame_buffer();
(vga, u32::from(frame_buffer) as *mut ScreenCharacter)
} }
} }