diff --git a/src/devices/bochs.rs b/src/devices/bochs.rs index 2f909cc..909556b 100644 --- a/src/devices/bochs.rs +++ b/src/devices/bochs.rs @@ -1,5 +1,9 @@ use super::pci::{find_pci_device, PciDevice}; -use crate::drawing::{Bresenham, Point, Rectangle}; +use crate::{ + drawing::{Bresenham, Point, Rectangle}, + writers::GraphicsWriter, +}; +use font8x8::UnicodeFonts; use x86_64::{instructions::port::Port, PhysAddr, VirtAddr}; const BOCHS_ID: u32 = 0x1111_1234; @@ -100,24 +104,6 @@ impl BochsDevice { } } - /// Clears the screen using the given `color`. - pub fn clear_screen(&self, color: u32) { - let screen_size = self.current_resolution.width * self.current_resolution.height; - let frame_buffer = self.virtual_address.as_mut_ptr::(); - for offset in 0..screen_size { - unsafe { - frame_buffer.add(offset).write_volatile(color); - } - } - } - - /// Draws a line from the given `start` to `end` using the given `color`. - pub fn draw_line(&self, start: Point, end: Point, color: u32) { - for (x, y) in Bresenham::new(start, end) { - self.set_pixel(x as usize, y as usize, color); - } - } - /// Draws a rectangle using the given `rectangle` and `color`. pub fn draw_rectangle(&self, rectangle: &Rectangle, color: u32) { let p1 = (rectangle.left as isize, rectangle.top as isize); @@ -134,22 +120,11 @@ impl BochsDevice { pub fn fill_rectangle(&self, rectangle: &Rectangle, color: u32) { for y in rectangle.top..rectangle.bottom { for x in rectangle.left..rectangle.right { - self.set_pixel(x, y, color); + self.set_pixel(x as usize, y as usize, color); } } } - /// Sets the pixel at `(x, y)` to the given `color`. - pub fn set_pixel(&self, x: usize, y: usize, color: u32) { - let offset = (y * self.current_resolution.width) + x; - unsafe { - self.virtual_address - .as_mut_ptr::() - .add(offset) - .write_volatile(color); - } - } - fn disable_display(&mut self) { unsafe { self.index_port.write(VBE_DISPI_INDEX_ENABLE); @@ -217,3 +192,48 @@ impl BochsDevice { } } } + +impl GraphicsWriter for BochsDevice { + fn clear_screen(&self, color: u32) { + let screen_size = self.current_resolution.width * self.current_resolution.height; + let frame_buffer = self.virtual_address.as_mut_ptr::(); + for offset in 0..screen_size { + unsafe { + frame_buffer.add(offset).write_volatile(color); + } + } + } + fn draw_character(&self, x: usize, y: usize, character: char, color: u32) { + let character = match font8x8::BASIC_FONTS.get(character) { + Some(character) => character, + // Default to a filled block if the character isn't found + None => font8x8::unicode::BLOCK_UNICODE[8].byte_array(), + }; + + for (row, byte) in character.iter().enumerate() { + for bit in 0..8 { + match *byte & 1 << bit { + 0 => (), + _ => self.set_pixel(x + bit, y + row, color), + } + } + } + } + fn draw_line(&self, start: Point, end: Point, color: u32) { + for (x, y) in Bresenham::new(start, end) { + self.set_pixel(x as usize, y as usize, color); + } + } + fn set_pixel(&self, x: usize, y: usize, color: u32) { + let offset = (y * self.current_resolution.width) + x; + unsafe { + self.virtual_address + .as_mut_ptr::() + .add(offset) + .write_volatile(color); + } + } + fn get_frame_buffer(&self) -> *mut T { + self.virtual_address.as_mut_ptr() + } +} diff --git a/src/writers/graphics_320x200x256.rs b/src/writers/graphics_320x200x256.rs index 998514d..4f8e766 100644 --- a/src/writers/graphics_320x200x256.rs +++ b/src/writers/graphics_320x200x256.rs @@ -76,14 +76,6 @@ impl GraphicsWriter for Graphics320x200x256 { } } } - fn set_mode(&self) { - let mut vga = VGA.lock(); - vga.set_video_mode(VideoMode::Mode320x200x256); - - // Some bios mess up the palette when switching modes, - // so explicitly set it. - vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); - } fn get_frame_buffer(&self) -> *mut T { u32::from(VGA.lock().get_frame_buffer()) as *mut T } @@ -94,4 +86,14 @@ impl Graphics320x200x256 { pub const fn new() -> Graphics320x200x256 { Graphics320x200x256 } + + /// Sets the graphics device to a `VideoMode`. + pub fn set_mode(&self) { + let mut vga = VGA.lock(); + vga.set_video_mode(VideoMode::Mode320x200x256); + + // Some bios mess up the palette when switching modes, + // so explicitly set it. + vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); + } } diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index 44352fe..4fa733d 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -84,14 +84,6 @@ impl GraphicsWriter for Graphics320x240x256 { } } } - fn set_mode(&self) { - let mut vga = VGA.lock(); - vga.set_video_mode(VideoMode::Mode320x240x256); - - // Some bios mess up the palette when switching modes, - // so explicitly set it. - vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); - } fn get_frame_buffer(&self) -> *mut T { u32::from(VGA.lock().get_frame_buffer()) as *mut T } @@ -102,4 +94,14 @@ impl Graphics320x240x256 { pub const fn new() -> Graphics320x240x256 { Graphics320x240x256 } + + /// Sets the graphics device to a `VideoMode`. + pub fn set_mode(&self) { + let mut vga = VGA.lock(); + vga.set_video_mode(VideoMode::Mode320x240x256); + + // Some bios mess up the palette when switching modes, + // so explicitly set it. + vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); + } } diff --git a/src/writers/graphics_640x480x16.rs b/src/writers/graphics_640x480x16.rs index 24eb23d..0e896f0 100644 --- a/src/writers/graphics_640x480x16.rs +++ b/src/writers/graphics_640x480x16.rs @@ -86,14 +86,6 @@ impl GraphicsWriter for Graphics640x480x16 { self._set_pixel(x, y, color); } - fn set_mode(&self) { - let mut vga = VGA.lock(); - vga.set_video_mode(VideoMode::Mode640x480x16); - - // Some bios mess up the palette when switching modes, - // so explicitly set it. - vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); - } fn get_frame_buffer(&self) -> *mut T { u32::from(VGA.lock().get_frame_buffer()) as *mut T } @@ -105,6 +97,16 @@ impl Graphics640x480x16 { Graphics640x480x16 } + /// Sets the graphics device to a `VideoMode`. + pub fn set_mode(&self) { + let mut vga = VGA.lock(); + vga.set_video_mode(VideoMode::Mode640x480x16); + + // Some bios mess up the palette when switching modes, + // so explicitly set it. + vga.color_palette_registers.load_palette(&DEFAULT_PALETTE); + } + fn set_write_mode_0(self, color: Color16) { let mut vga = VGA.lock(); vga.graphics_controller_registers.write_set_reset(color); diff --git a/src/writers/mod.rs b/src/writers/mod.rs index a613946..36ab2cb 100644 --- a/src/writers/mod.rs +++ b/src/writers/mod.rs @@ -197,8 +197,6 @@ pub trait GraphicsWriter { fn draw_character(&self, x: usize, y: usize, character: char, color: Color); /// Sets the given pixel at `(x, y)` to the given `color`. fn set_pixel(&self, x: usize, y: usize, color: Color); - /// Sets the graphics device to a `VideoMode`. - fn set_mode(&self); /// Returns the frame buffer for this vga mode. fn get_frame_buffer(&self) -> *mut T; }