From 626ad52589b6fa8662e8e67b50df9400b90d1d21 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sat, 4 Apr 2020 22:53:36 -0500 Subject: [PATCH 1/7] Initial setup for mode 320x240x256 --- src/configurations.rs | 76 +++++++++++++++++++++++++- src/registers/sequencer.rs | 2 +- src/vga.rs | 14 ++++- src/writers/graphics_320x240x256.rs | 85 +++++++++++++++++++++++++++++ src/writers/mod.rs | 2 + 5 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/writers/graphics_320x240x256.rs diff --git a/src/configurations.rs b/src/configurations.rs index bd35e1d..1c1b898 100644 --- a/src/configurations.rs +++ b/src/configurations.rs @@ -316,7 +316,7 @@ pub const MODE_640X480X16_CONFIGURATION: VgaConfiguration = VgaConfiguration { ], }; -/// Register values for Vga mode 640x480x16 Graphics. +/// Register values for Vga mode 320x200x256 Graphics. pub const MODE_320X200X256_CONFIGURATION: VgaConfiguration = VgaConfiguration { // Configuration values acquired from https://www.singlix.com/trdos/archive/vga/Graphics%20in%20pmode.pdf miscellaneous_output: 0x63, @@ -389,3 +389,77 @@ pub const MODE_320X200X256_CONFIGURATION: VgaConfiguration = VgaConfiguration { (AttributeControllerIndex::ColorSelect, 0x00), ], }; + +/// Register values for Vga mode 320x200x256x Graphics. +pub const MODE_320X240X256_CONFIGURATION: VgaConfiguration = VgaConfiguration { + // Configuration values acquired from https://www.singlix.com/trdos/archive/vga/Graphics%20in%20pmode.pdf + miscellaneous_output: 0x63, + sequencer_registers: &[ + (SequencerIndex::SequencerReset, 0x03), + (SequencerIndex::ClockingMode, 0x01), + (SequencerIndex::PlaneMask, 0x0F), + (SequencerIndex::CharacterFont, 0x00), + (SequencerIndex::MemoryMode, 0x06), + ], + crtc_controller_registers: &[ + (CrtcControllerIndex::HorizontalTotal, 0x5F), + (CrtcControllerIndex::HorizontalDisplayEnableEnd, 0x4F), + (CrtcControllerIndex::HorizontalBlankingStart, 0x50), + (CrtcControllerIndex::HorizontalBlankingEnd, 0x82), + (CrtcControllerIndex::HorizontalSyncStart, 0x54), + (CrtcControllerIndex::HorizontalSyncEnd, 0x80), + (CrtcControllerIndex::VeritcalTotal, 0xBF), + (CrtcControllerIndex::Overflow, 0x1F), + (CrtcControllerIndex::PresetRowScan, 0x00), + (CrtcControllerIndex::MaximumScanLine, 0x41), + (CrtcControllerIndex::TextCursorStart, 0x00), + (CrtcControllerIndex::TextCursorEnd, 0x00), + (CrtcControllerIndex::StartAddressHigh, 0x00), + (CrtcControllerIndex::StartAddressLow, 0x00), + (CrtcControllerIndex::TextCursorLocationHigh, 0x00), + (CrtcControllerIndex::TextCursorLocationLow, 0x00), + (CrtcControllerIndex::VerticalSyncStart, 0x9C), + (CrtcControllerIndex::VerticalSyncEnd, 0x0E), + (CrtcControllerIndex::VerticalDisplayEnableEnd, 0x8F), + (CrtcControllerIndex::Offset, 0x28), + (CrtcControllerIndex::UnderlineLocation, 0x00), + (CrtcControllerIndex::VerticalBlankingStart, 0x96), + (CrtcControllerIndex::VerticalBlankingEnd, 0xB9), + (CrtcControllerIndex::ModeControl, 0xe3), + (CrtcControllerIndex::LineCompare, 0xFF), + ], + graphics_controller_registers: &[ + (GraphicsControllerIndex::SetReset, 0x00), + (GraphicsControllerIndex::EnableSetReset, 0x00), + (GraphicsControllerIndex::ColorCompare, 0x00), + (GraphicsControllerIndex::DataRotate, 0x00), + (GraphicsControllerIndex::ReadPlaneSelect, 0x00), + (GraphicsControllerIndex::GraphicsMode, 0x40), + (GraphicsControllerIndex::Miscellaneous, 0x05), + (GraphicsControllerIndex::ColorDontCare, 0x0F), + (GraphicsControllerIndex::BitMask, 0xFF), + ], + attribute_controller_registers: &[ + (AttributeControllerIndex::PaletteRegister0, 0x00), + (AttributeControllerIndex::PaletteRegister1, 0x01), + (AttributeControllerIndex::PaletteRegister2, 0x02), + (AttributeControllerIndex::PaletteRegister3, 0x03), + (AttributeControllerIndex::PaletteRegister4, 0x04), + (AttributeControllerIndex::PaletteRegister5, 0x05), + (AttributeControllerIndex::PaletteRegister6, 0x06), + (AttributeControllerIndex::PaletteRegister7, 0x07), + (AttributeControllerIndex::PaletteRegister8, 0x08), + (AttributeControllerIndex::PaletteRegister9, 0x09), + (AttributeControllerIndex::PaletteRegisterA, 0x0A), + (AttributeControllerIndex::PaletteRegisterB, 0x0B), + (AttributeControllerIndex::PaletteRegisterC, 0x0C), + (AttributeControllerIndex::PaletteRegisterD, 0x0D), + (AttributeControllerIndex::PaletteRegisterE, 0x0E), + (AttributeControllerIndex::PaletteRegisterF, 0x0F), + (AttributeControllerIndex::ModeControl, 0x41), + (AttributeControllerIndex::OverscanColor, 0x00), + (AttributeControllerIndex::MemoryPlaneEnable, 0x0F), + (AttributeControllerIndex::HorizontalPixelPanning, 0x00), + (AttributeControllerIndex::ColorSelect, 0x00), + ], +}; diff --git a/src/registers/sequencer.rs b/src/registers/sequencer.rs index a161929..d7dfe61 100644 --- a/src/registers/sequencer.rs +++ b/src/registers/sequencer.rs @@ -96,7 +96,7 @@ impl SequencerRegisters { /// Sets the plane mask of the sequencer controller, as specified by `plane_mask`. pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) { - let original_value = self.read(SequencerIndex::PlaneMask); + let original_value = self.read(SequencerIndex::PlaneMask) & 0xF0; self.write( SequencerIndex::PlaneMask, original_value | u8::from(plane_mask), diff --git a/src/vga.rs b/src/vga.rs index 79d70e0..581222d 100644 --- a/src/vga.rs +++ b/src/vga.rs @@ -2,8 +2,9 @@ use super::{ configurations::{ - VgaConfiguration, MODE_320X200X256_CONFIGURATION, MODE_40X25_CONFIGURATION, - MODE_40X50_CONFIGURATION, MODE_640X480X16_CONFIGURATION, MODE_80X25_CONFIGURATION, + VgaConfiguration, MODE_320X200X256_CONFIGURATION, MODE_320X240X256_CONFIGURATION, + MODE_40X25_CONFIGURATION, MODE_40X50_CONFIGURATION, MODE_640X480X16_CONFIGURATION, + MODE_80X25_CONFIGURATION, }, fonts::VgaFont, registers::{ @@ -59,6 +60,8 @@ pub enum VideoMode { Mode80x25, /// Represents graphics mode 320x200x256. Mode320x200x256, + /// Represents graphics mode 320x240x256. + Mode320x240x256, /// Represents graphics mode 640x480x16. Mode640x480x16, } @@ -101,6 +104,7 @@ impl Vga { VideoMode::Mode40x50 => self.set_video_mode_40x50(), VideoMode::Mode80x25 => self.set_video_mode_80x25(), VideoMode::Mode320x200x256 => self.set_video_mode_320x200x256(), + VideoMode::Mode320x240x256 => self.set_video_mode_320x240x256(), VideoMode::Mode640x480x16 => self.set_video_mode_640x480x16(), } } @@ -275,6 +279,12 @@ impl Vga { self.most_recent_video_mode = Some(VideoMode::Mode320x200x256); } + /// Sets the video card to Mode 320x200x256x. + fn set_video_mode_320x240x256(&mut self) { + self.set_registers(&MODE_320X240X256_CONFIGURATION); + self.most_recent_video_mode = Some(VideoMode::Mode320x240x256); + } + /// Sets the video card to Mode 640x480x16. fn set_video_mode_640x480x16(&mut self) { self.set_registers(&MODE_640X480X16_CONFIGURATION); diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs new file mode 100644 index 0000000..fbaaad2 --- /dev/null +++ b/src/writers/graphics_320x240x256.rs @@ -0,0 +1,85 @@ +use super::{GraphicsWriter, Screen}; +use crate::{ + colors::DEFAULT_PALETTE, + drawing::{Bresenham, Point}, + registers::PlaneMask, + vga::{Vga, VideoMode, VGA}, +}; +use font8x8::UnicodeFonts; +use spinning_top::SpinlockGuard; + +const WIDTH: usize = 320; +const HEIGHT: usize = 200; +const SIZE: usize = (WIDTH * HEIGHT) / 4; + +#[derive(Debug, Clone, Copy, Default)] +pub struct Graphics320x240x256; + +impl Screen for Graphics320x240x256 { + const WIDTH: usize = WIDTH; + const HEIGHT: usize = HEIGHT; + const SIZE: usize = SIZE; +} + +impl GraphicsWriter for Graphics320x240x256 { + fn clear_screen(&self, color: u8) { + let (_vga, frame_buffer) = self.get_frame_buffer(); + unsafe { + frame_buffer.write_bytes(color, Self::SIZE); + } + } + fn draw_line(&self, start: Point, end: Point, color: u8) { + 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: u8) { + let (mut vga, frame_buffer) = self.get_frame_buffer(); + unsafe { + let offset = (WIDTH * y + x) / 4; + let plane_mask = 0x1 << (x & 3); + vga.sequencer_registers + .set_plane_mask(PlaneMask::from_bits(plane_mask).unwrap()); + frame_buffer.add(offset).write_volatile(color); + } + } + fn draw_character(&self, x: usize, y: usize, character: char, color: u8) { + 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 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); + } +} + +impl Graphics320x240x256 { + pub const fn new() -> Graphics320x240x256 { + Graphics320x240x256 + } + + /// Returns the start of the `FrameBuffer` as `*mut u8` 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<'static, Vga>, *mut u8) { + let mut vga = VGA.lock(); + let frame_buffer = vga.get_frame_buffer(); + (vga, u32::from(frame_buffer) as *mut u8) + } +} diff --git a/src/writers/mod.rs b/src/writers/mod.rs index d47a2a8..3d83742 100644 --- a/src/writers/mod.rs +++ b/src/writers/mod.rs @@ -1,5 +1,6 @@ //! Writers for common vga modes. mod graphics_320x200x256; +mod graphics_320x240x256; mod graphics_640x480x16; mod text_40x25; mod text_40x50; @@ -14,6 +15,7 @@ use super::{ use spinning_top::SpinlockGuard; pub use graphics_320x200x256::Graphics320x200x256; +pub use graphics_320x240x256::Graphics320x240x256; pub use graphics_640x480x16::Graphics640x480x16; pub use text_40x25::Text40x25; pub use text_40x50::Text40x50; From ac80307d294cd8efe16d293602ae1ed77fdeb282 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sat, 4 Apr 2020 23:08:34 -0500 Subject: [PATCH 2/7] Probably don't need those locks --- src/writers/graphics_320x200x256.rs | 18 +++------------- src/writers/graphics_320x240x256.rs | 17 ++++----------- src/writers/graphics_640x480x16.rs | 33 ++++++++++------------------- src/writers/mod.rs | 4 ++++ 4 files changed, 22 insertions(+), 50 deletions(-) diff --git a/src/writers/graphics_320x200x256.rs b/src/writers/graphics_320x200x256.rs index e2c8cc0..48cd4ee 100644 --- a/src/writers/graphics_320x200x256.rs +++ b/src/writers/graphics_320x200x256.rs @@ -44,10 +44,8 @@ impl Screen for Graphics320x200x256 { impl GraphicsWriter for Graphics320x200x256 { fn clear_screen(&self, color: u8) { - for x in 0..WIDTH { - for y in 0..HEIGHT { - self.set_pixel(x, y, color); - } + unsafe { + self.get_frame_buffer().write_bytes(color, Self::SIZE); } } fn draw_line(&self, start: Point, end: Point, color: u8) { @@ -56,10 +54,9 @@ impl GraphicsWriter for Graphics320x200x256 { } } fn set_pixel(&self, x: usize, y: usize, color: u8) { - let (_vga, frame_buffer) = self.get_frame_buffer(); let offset = (y * WIDTH) + x; unsafe { - frame_buffer.add(offset).write_volatile(color); + self.get_frame_buffer().add(offset).write_volatile(color); } } fn draw_character(&self, x: usize, y: usize, character: char, color: u8) { @@ -93,13 +90,4 @@ impl Graphics320x200x256 { pub const fn new() -> Graphics320x200x256 { Graphics320x200x256 } - - /// Returns the start of the `FrameBuffer` as `*mut u8` 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<'static, Vga>, *mut u8) { - let mut vga = VGA.lock(); - let frame_buffer = vga.get_frame_buffer(); - (vga, u32::from(frame_buffer) as *mut u8) - } } diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index fbaaad2..a3ec1d1 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -23,9 +23,8 @@ impl Screen for Graphics320x240x256 { impl GraphicsWriter for Graphics320x240x256 { fn clear_screen(&self, color: u8) { - let (_vga, frame_buffer) = self.get_frame_buffer(); unsafe { - frame_buffer.write_bytes(color, Self::SIZE); + self.get_frame_buffer().write_bytes(color, Self::SIZE); } } fn draw_line(&self, start: Point, end: Point, color: u8) { @@ -34,11 +33,12 @@ impl GraphicsWriter for Graphics320x240x256 { } } fn set_pixel(&self, x: usize, y: usize, color: u8) { - let (mut vga, frame_buffer) = self.get_frame_buffer(); + let frame_buffer = self.get_frame_buffer(); unsafe { let offset = (WIDTH * y + x) / 4; let plane_mask = 0x1 << (x & 3); - vga.sequencer_registers + VGA.lock() + .sequencer_registers .set_plane_mask(PlaneMask::from_bits(plane_mask).unwrap()); frame_buffer.add(offset).write_volatile(color); } @@ -73,13 +73,4 @@ impl Graphics320x240x256 { pub const fn new() -> Graphics320x240x256 { Graphics320x240x256 } - - /// Returns the start of the `FrameBuffer` as `*mut u8` 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<'static, Vga>, *mut u8) { - let mut vga = VGA.lock(); - let frame_buffer = vga.get_frame_buffer(); - (vga, u32::from(frame_buffer) as *mut u8) - } } diff --git a/src/writers/graphics_640x480x16.rs b/src/writers/graphics_640x480x16.rs index 43a42b0..80a015f 100644 --- a/src/writers/graphics_640x480x16.rs +++ b/src/writers/graphics_640x480x16.rs @@ -3,15 +3,13 @@ use crate::{ colors::{Color16, DEFAULT_PALETTE}, drawing::{Bresenham, Point}, registers::{PlaneMask, WriteMode}, - vga::{Vga, VideoMode, VGA}, + vga::{VideoMode, VGA}, }; use font8x8::UnicodeFonts; -use spinning_top::SpinlockGuard; const WIDTH: usize = 640; const HEIGHT: usize = 480; -const SIZE: usize = WIDTH * HEIGHT; -const ALL_PLANES_SCREEN_SIZE: usize = (WIDTH * HEIGHT) / 8; +const SIZE: usize = (WIDTH * HEIGHT) / 8; const WIDTH_IN_BYTES: usize = WIDTH / 8; /// A basic interface for interacting with vga graphics mode 640x480x16 @@ -48,11 +46,9 @@ impl Screen for Graphics640x480x16 { impl GraphicsWriter for Graphics640x480x16 { fn clear_screen(&self, color: Color16) { self.set_write_mode_2(); - let (_vga, frame_buffer) = self.get_frame_buffer(); - for offset in 0..ALL_PLANES_SCREEN_SIZE { - unsafe { - frame_buffer.add(offset).write_volatile(u8::from(color)); - } + unsafe { + self.get_frame_buffer() + .write_bytes(u8::from(color), Self::SIZE); } } @@ -107,7 +103,7 @@ impl Graphics640x480x16 { } fn set_write_mode_0(self, color: Color16) { - let (mut vga, _frame_buffer) = self.get_frame_buffer(); + let mut vga = VGA.lock(); vga.graphics_controller_registers.write_set_reset(color); vga.graphics_controller_registers .write_enable_set_reset(0xF); @@ -116,7 +112,7 @@ impl Graphics640x480x16 { } fn set_write_mode_2(self) { - let (mut vga, _frame_buffer) = self.get_frame_buffer(); + let mut vga = VGA.lock(); vga.graphics_controller_registers .set_write_mode(WriteMode::Mode2); vga.graphics_controller_registers.set_bit_mask(0xFF); @@ -124,21 +120,14 @@ impl Graphics640x480x16 { .set_plane_mask(PlaneMask::ALL_PLANES); } - /// Returns the start of the `FrameBuffer` as `*mut u8` 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<'static, Vga>, *mut u8) { - let mut vga = VGA.lock(); - let frame_buffer = vga.get_frame_buffer(); - (vga, u32::from(frame_buffer) as *mut u8) - } - #[inline] fn _set_pixel(self, x: usize, y: usize, color: Color16) { - let (mut vga, frame_buffer) = self.get_frame_buffer(); + let frame_buffer = self.get_frame_buffer(); let offset = x / 8 + y * WIDTH_IN_BYTES; let pixel_mask = 0x80 >> (x & 0x07); - vga.graphics_controller_registers.set_bit_mask(pixel_mask); + VGA.lock() + .graphics_controller_registers + .set_bit_mask(pixel_mask); unsafe { frame_buffer.add(offset).read_volatile(); frame_buffer.add(offset).write_volatile(u8::from(color)); diff --git a/src/writers/mod.rs b/src/writers/mod.rs index 3d83742..1ace5cf 100644 --- a/src/writers/mod.rs +++ b/src/writers/mod.rs @@ -199,4 +199,8 @@ pub trait GraphicsWriter { 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 u8 { + u32::from(VGA.lock().get_frame_buffer()) as *mut u8 + } } From 95f550a55e906b37def63deb1108254542b62c08 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sat, 4 Apr 2020 23:14:09 -0500 Subject: [PATCH 3/7] Unused imports --- src/writers/graphics_320x200x256.rs | 3 +-- src/writers/graphics_320x240x256.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/writers/graphics_320x200x256.rs b/src/writers/graphics_320x200x256.rs index 48cd4ee..43dc28d 100644 --- a/src/writers/graphics_320x200x256.rs +++ b/src/writers/graphics_320x200x256.rs @@ -2,10 +2,9 @@ use super::{GraphicsWriter, Screen}; use crate::{ colors::DEFAULT_PALETTE, drawing::{Bresenham, Point}, - vga::{Vga, VideoMode, VGA}, + vga::{VideoMode, VGA}, }; use font8x8::UnicodeFonts; -use spinning_top::SpinlockGuard; const WIDTH: usize = 320; const HEIGHT: usize = 200; diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index a3ec1d1..197c4a1 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -3,10 +3,9 @@ use crate::{ colors::DEFAULT_PALETTE, drawing::{Bresenham, Point}, registers::PlaneMask, - vga::{Vga, VideoMode, VGA}, + vga::{VideoMode, VGA}, }; use font8x8::UnicodeFonts; -use spinning_top::SpinlockGuard; const WIDTH: usize = 320; const HEIGHT: usize = 200; From 015c1c6597300d49181237b63683c8ac0799a811 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sun, 5 Apr 2020 17:17:16 -0500 Subject: [PATCH 4/7] Actually make the height 240 --- src/configurations.rs | 16 ++++++++-------- src/writers/graphics_320x240x256.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/configurations.rs b/src/configurations.rs index 1c1b898..1478a9e 100644 --- a/src/configurations.rs +++ b/src/configurations.rs @@ -408,8 +408,8 @@ pub const MODE_320X240X256_CONFIGURATION: VgaConfiguration = VgaConfiguration { (CrtcControllerIndex::HorizontalBlankingEnd, 0x82), (CrtcControllerIndex::HorizontalSyncStart, 0x54), (CrtcControllerIndex::HorizontalSyncEnd, 0x80), - (CrtcControllerIndex::VeritcalTotal, 0xBF), - (CrtcControllerIndex::Overflow, 0x1F), + (CrtcControllerIndex::VeritcalTotal, 0x0D), + (CrtcControllerIndex::Overflow, 0x3E), (CrtcControllerIndex::PresetRowScan, 0x00), (CrtcControllerIndex::MaximumScanLine, 0x41), (CrtcControllerIndex::TextCursorStart, 0x00), @@ -418,14 +418,14 @@ pub const MODE_320X240X256_CONFIGURATION: VgaConfiguration = VgaConfiguration { (CrtcControllerIndex::StartAddressLow, 0x00), (CrtcControllerIndex::TextCursorLocationHigh, 0x00), (CrtcControllerIndex::TextCursorLocationLow, 0x00), - (CrtcControllerIndex::VerticalSyncStart, 0x9C), - (CrtcControllerIndex::VerticalSyncEnd, 0x0E), - (CrtcControllerIndex::VerticalDisplayEnableEnd, 0x8F), + (CrtcControllerIndex::VerticalSyncStart, 0xEA), + (CrtcControllerIndex::VerticalSyncEnd, 0xAC), + (CrtcControllerIndex::VerticalDisplayEnableEnd, 0xDF), (CrtcControllerIndex::Offset, 0x28), (CrtcControllerIndex::UnderlineLocation, 0x00), - (CrtcControllerIndex::VerticalBlankingStart, 0x96), - (CrtcControllerIndex::VerticalBlankingEnd, 0xB9), - (CrtcControllerIndex::ModeControl, 0xe3), + (CrtcControllerIndex::VerticalBlankingStart, 0xE7), + (CrtcControllerIndex::VerticalBlankingEnd, 0x06), + (CrtcControllerIndex::ModeControl, 0xE3), (CrtcControllerIndex::LineCompare, 0xFF), ], graphics_controller_registers: &[ diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index 197c4a1..ae89116 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -8,7 +8,7 @@ use crate::{ use font8x8::UnicodeFonts; const WIDTH: usize = 320; -const HEIGHT: usize = 200; +const HEIGHT: usize = 240; const SIZE: usize = (WIDTH * HEIGHT) / 4; #[derive(Debug, Clone, Copy, Default)] From 41a746fd2c8257d4b995d783f6a30795caafb442 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sun, 5 Apr 2020 17:49:31 -0500 Subject: [PATCH 5/7] Always specify plane for clear screen --- src/writers/graphics_320x240x256.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index ae89116..04b1fe7 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -22,6 +22,11 @@ impl Screen for Graphics320x240x256 { impl GraphicsWriter for Graphics320x240x256 { fn clear_screen(&self, color: u8) { + { + let mut vga = VGA.lock(); + vga.sequencer_registers + .set_plane_mask(PlaneMask::ALL_PLANES); + } unsafe { self.get_frame_buffer().write_bytes(color, Self::SIZE); } From 6861ca509fe55275db6d1b96b911490e3f369f68 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sun, 5 Apr 2020 18:45:52 -0500 Subject: [PATCH 6/7] Comments and cleanup --- src/writers/graphics_320x200x256.rs | 2 +- src/writers/graphics_320x240x256.rs | 34 ++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/writers/graphics_320x200x256.rs b/src/writers/graphics_320x200x256.rs index 43dc28d..1a2815e 100644 --- a/src/writers/graphics_320x200x256.rs +++ b/src/writers/graphics_320x200x256.rs @@ -19,7 +19,7 @@ const SIZE: usize = WIDTH * HEIGHT; /// ```no_run /// use vga::colors::Color16; /// use vga::writers::{Graphics320x200x256, GraphicsWriter}; - +/// /// let mode = Graphics320x200x256::new(); /// mode.set_mode(); /// mode.clear_screen(0); diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index 04b1fe7..2d8b580 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -11,6 +11,28 @@ const WIDTH: usize = 320; const HEIGHT: usize = 240; const SIZE: usize = (WIDTH * HEIGHT) / 4; +/// A basic interface for interacting with vga graphics mode 320x200x256. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ```no_run +/// use vga::colors::Color16; +/// use vga::writers::{Graphics320x240x256, GraphicsWriter}; +/// +/// let mode = Graphics320x240x256::new(); +/// mode.set_mode(); +/// mode.clear_screen(0); +/// mode.draw_line((60, 20), (260, 20), 255); +/// mode.draw_line((60, 20), (60, 180), 255); +/// mode.draw_line((60, 180), (260, 180), 255); +/// mode.draw_line((260, 180), (260, 20), 255); +/// mode.draw_line((60, 40), (260, 40), 255); +/// for (offset, character) in "Hello World!".chars().enumerate() { +/// mode.draw_character(118 + offset * 8, 27, character, 255); +/// } +/// ``` #[derive(Debug, Clone, Copy, Default)] pub struct Graphics320x240x256; @@ -22,13 +44,12 @@ impl Screen for Graphics320x240x256 { impl GraphicsWriter for Graphics320x240x256 { fn clear_screen(&self, color: u8) { - { - let mut vga = VGA.lock(); - vga.sequencer_registers - .set_plane_mask(PlaneMask::ALL_PLANES); - } + let frame_buffer = self.get_frame_buffer(); + VGA.lock() + .sequencer_registers + .set_plane_mask(PlaneMask::ALL_PLANES); unsafe { - self.get_frame_buffer().write_bytes(color, Self::SIZE); + frame_buffer.write_bytes(color, Self::SIZE); } } fn draw_line(&self, start: Point, end: Point, color: u8) { @@ -74,6 +95,7 @@ impl GraphicsWriter for Graphics320x240x256 { } impl Graphics320x240x256 { + /// Creates a new `Graphics320x240x256`. pub const fn new() -> Graphics320x240x256 { Graphics320x240x256 } From 39ad683665e628e4a15a998f0008ae937af8224c Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Sun, 5 Apr 2020 18:58:30 -0500 Subject: [PATCH 7/7] Changelog and version bump --- Cargo.toml | 2 +- Changelog.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2f03e24..bf7fbd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vga" -version = "0.2.2" +version = "0.2.3" authors = ["Ryan Kennedy "] edition = "2018" description = "Support for vga specific functions, data structures, and registers." diff --git a/Changelog.md b/Changelog.md index 677d5bb..babb358 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +# 0.2.3 + +- Added support for 320x240x256 mode via `Graphics320x240x256`. +- Added the ability to easily get a pointer to the modes frame buffer via `GraphicsWriter::get_frame_buffer`. + # 0.2.2 ## Breaking