commit
4a5598e072
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "vga"
|
name = "vga"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
|
authors = ["Ryan Kennedy <rkennedy9064@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Support for vga specific functions, data structures, and registers."
|
description = "Support for vga specific functions, data structures, and registers."
|
||||||
|
|
|
@ -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
|
# 0.2.2
|
||||||
|
|
||||||
## Breaking
|
## Breaking
|
||||||
|
|
|
@ -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 {
|
pub const MODE_320X200X256_CONFIGURATION: VgaConfiguration = VgaConfiguration {
|
||||||
// Configuration values acquired from https://www.singlix.com/trdos/archive/vga/Graphics%20in%20pmode.pdf
|
// Configuration values acquired from https://www.singlix.com/trdos/archive/vga/Graphics%20in%20pmode.pdf
|
||||||
miscellaneous_output: 0x63,
|
miscellaneous_output: 0x63,
|
||||||
|
@ -389,3 +389,77 @@ pub const MODE_320X200X256_CONFIGURATION: VgaConfiguration = VgaConfiguration {
|
||||||
(AttributeControllerIndex::ColorSelect, 0x00),
|
(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, 0x0D),
|
||||||
|
(CrtcControllerIndex::Overflow, 0x3E),
|
||||||
|
(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, 0xEA),
|
||||||
|
(CrtcControllerIndex::VerticalSyncEnd, 0xAC),
|
||||||
|
(CrtcControllerIndex::VerticalDisplayEnableEnd, 0xDF),
|
||||||
|
(CrtcControllerIndex::Offset, 0x28),
|
||||||
|
(CrtcControllerIndex::UnderlineLocation, 0x00),
|
||||||
|
(CrtcControllerIndex::VerticalBlankingStart, 0xE7),
|
||||||
|
(CrtcControllerIndex::VerticalBlankingEnd, 0x06),
|
||||||
|
(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),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl SequencerRegisters {
|
||||||
|
|
||||||
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
|
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
|
||||||
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
|
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(
|
self.write(
|
||||||
SequencerIndex::PlaneMask,
|
SequencerIndex::PlaneMask,
|
||||||
original_value | u8::from(plane_mask),
|
original_value | u8::from(plane_mask),
|
||||||
|
|
14
src/vga.rs
14
src/vga.rs
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
configurations::{
|
configurations::{
|
||||||
VgaConfiguration, MODE_320X200X256_CONFIGURATION, MODE_40X25_CONFIGURATION,
|
VgaConfiguration, MODE_320X200X256_CONFIGURATION, MODE_320X240X256_CONFIGURATION,
|
||||||
MODE_40X50_CONFIGURATION, MODE_640X480X16_CONFIGURATION, MODE_80X25_CONFIGURATION,
|
MODE_40X25_CONFIGURATION, MODE_40X50_CONFIGURATION, MODE_640X480X16_CONFIGURATION,
|
||||||
|
MODE_80X25_CONFIGURATION,
|
||||||
},
|
},
|
||||||
fonts::VgaFont,
|
fonts::VgaFont,
|
||||||
registers::{
|
registers::{
|
||||||
|
@ -59,6 +60,8 @@ pub enum VideoMode {
|
||||||
Mode80x25,
|
Mode80x25,
|
||||||
/// Represents graphics mode 320x200x256.
|
/// Represents graphics mode 320x200x256.
|
||||||
Mode320x200x256,
|
Mode320x200x256,
|
||||||
|
/// Represents graphics mode 320x240x256.
|
||||||
|
Mode320x240x256,
|
||||||
/// Represents graphics mode 640x480x16.
|
/// Represents graphics mode 640x480x16.
|
||||||
Mode640x480x16,
|
Mode640x480x16,
|
||||||
}
|
}
|
||||||
|
@ -101,6 +104,7 @@ impl Vga {
|
||||||
VideoMode::Mode40x50 => self.set_video_mode_40x50(),
|
VideoMode::Mode40x50 => self.set_video_mode_40x50(),
|
||||||
VideoMode::Mode80x25 => self.set_video_mode_80x25(),
|
VideoMode::Mode80x25 => self.set_video_mode_80x25(),
|
||||||
VideoMode::Mode320x200x256 => self.set_video_mode_320x200x256(),
|
VideoMode::Mode320x200x256 => self.set_video_mode_320x200x256(),
|
||||||
|
VideoMode::Mode320x240x256 => self.set_video_mode_320x240x256(),
|
||||||
VideoMode::Mode640x480x16 => self.set_video_mode_640x480x16(),
|
VideoMode::Mode640x480x16 => self.set_video_mode_640x480x16(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,6 +279,12 @@ impl Vga {
|
||||||
self.most_recent_video_mode = Some(VideoMode::Mode320x200x256);
|
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.
|
/// Sets the video card to Mode 640x480x16.
|
||||||
fn set_video_mode_640x480x16(&mut self) {
|
fn set_video_mode_640x480x16(&mut self) {
|
||||||
self.set_registers(&MODE_640X480X16_CONFIGURATION);
|
self.set_registers(&MODE_640X480X16_CONFIGURATION);
|
||||||
|
|
|
@ -2,10 +2,9 @@ use super::{GraphicsWriter, Screen};
|
||||||
use crate::{
|
use crate::{
|
||||||
colors::DEFAULT_PALETTE,
|
colors::DEFAULT_PALETTE,
|
||||||
drawing::{Bresenham, Point},
|
drawing::{Bresenham, Point},
|
||||||
vga::{Vga, VideoMode, VGA},
|
vga::{VideoMode, VGA},
|
||||||
};
|
};
|
||||||
use font8x8::UnicodeFonts;
|
use font8x8::UnicodeFonts;
|
||||||
use spinning_top::SpinlockGuard;
|
|
||||||
|
|
||||||
const WIDTH: usize = 320;
|
const WIDTH: usize = 320;
|
||||||
const HEIGHT: usize = 200;
|
const HEIGHT: usize = 200;
|
||||||
|
@ -20,7 +19,7 @@ const SIZE: usize = WIDTH * HEIGHT;
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use vga::colors::Color16;
|
/// use vga::colors::Color16;
|
||||||
/// use vga::writers::{Graphics320x200x256, GraphicsWriter};
|
/// use vga::writers::{Graphics320x200x256, GraphicsWriter};
|
||||||
|
///
|
||||||
/// let mode = Graphics320x200x256::new();
|
/// let mode = Graphics320x200x256::new();
|
||||||
/// mode.set_mode();
|
/// mode.set_mode();
|
||||||
/// mode.clear_screen(0);
|
/// mode.clear_screen(0);
|
||||||
|
@ -44,10 +43,8 @@ impl Screen for Graphics320x200x256 {
|
||||||
|
|
||||||
impl GraphicsWriter<u8> for Graphics320x200x256 {
|
impl GraphicsWriter<u8> for Graphics320x200x256 {
|
||||||
fn clear_screen(&self, color: u8) {
|
fn clear_screen(&self, color: u8) {
|
||||||
for x in 0..WIDTH {
|
unsafe {
|
||||||
for y in 0..HEIGHT {
|
self.get_frame_buffer().write_bytes(color, Self::SIZE);
|
||||||
self.set_pixel(x, y, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: u8) {
|
fn draw_line(&self, start: Point<isize>, end: Point<isize>, color: u8) {
|
||||||
|
@ -56,10 +53,9 @@ impl GraphicsWriter<u8> for Graphics320x200x256 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_pixel(&self, x: usize, y: usize, color: u8) {
|
fn set_pixel(&self, x: usize, y: usize, color: u8) {
|
||||||
let (_vga, frame_buffer) = self.get_frame_buffer();
|
|
||||||
let offset = (y * WIDTH) + x;
|
let offset = (y * WIDTH) + x;
|
||||||
unsafe {
|
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) {
|
fn draw_character(&self, x: usize, y: usize, character: char, color: u8) {
|
||||||
|
@ -93,13 +89,4 @@ impl Graphics320x200x256 {
|
||||||
pub const fn new() -> Graphics320x200x256 {
|
pub const fn new() -> Graphics320x200x256 {
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
102
src/writers/graphics_320x240x256.rs
Normal file
102
src/writers/graphics_320x240x256.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
use super::{GraphicsWriter, Screen};
|
||||||
|
use crate::{
|
||||||
|
colors::DEFAULT_PALETTE,
|
||||||
|
drawing::{Bresenham, Point},
|
||||||
|
registers::PlaneMask,
|
||||||
|
vga::{VideoMode, VGA},
|
||||||
|
};
|
||||||
|
use font8x8::UnicodeFonts;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
impl Screen for Graphics320x240x256 {
|
||||||
|
const WIDTH: usize = WIDTH;
|
||||||
|
const HEIGHT: usize = HEIGHT;
|
||||||
|
const SIZE: usize = SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GraphicsWriter<u8> for Graphics320x240x256 {
|
||||||
|
fn clear_screen(&self, color: u8) {
|
||||||
|
let frame_buffer = self.get_frame_buffer();
|
||||||
|
VGA.lock()
|
||||||
|
.sequencer_registers
|
||||||
|
.set_plane_mask(PlaneMask::ALL_PLANES);
|
||||||
|
unsafe {
|
||||||
|
frame_buffer.write_bytes(color, Self::SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn draw_line(&self, start: Point<isize>, end: Point<isize>, 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 frame_buffer = self.get_frame_buffer();
|
||||||
|
unsafe {
|
||||||
|
let offset = (WIDTH * y + x) / 4;
|
||||||
|
let plane_mask = 0x1 << (x & 3);
|
||||||
|
VGA.lock()
|
||||||
|
.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 {
|
||||||
|
/// Creates a new `Graphics320x240x256`.
|
||||||
|
pub const fn new() -> Graphics320x240x256 {
|
||||||
|
Graphics320x240x256
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,15 +3,13 @@ use crate::{
|
||||||
colors::{Color16, DEFAULT_PALETTE},
|
colors::{Color16, DEFAULT_PALETTE},
|
||||||
drawing::{Bresenham, Point},
|
drawing::{Bresenham, Point},
|
||||||
registers::{PlaneMask, WriteMode},
|
registers::{PlaneMask, WriteMode},
|
||||||
vga::{Vga, VideoMode, VGA},
|
vga::{VideoMode, VGA},
|
||||||
};
|
};
|
||||||
use font8x8::UnicodeFonts;
|
use font8x8::UnicodeFonts;
|
||||||
use spinning_top::SpinlockGuard;
|
|
||||||
|
|
||||||
const WIDTH: usize = 640;
|
const WIDTH: usize = 640;
|
||||||
const HEIGHT: usize = 480;
|
const HEIGHT: usize = 480;
|
||||||
const SIZE: usize = WIDTH * HEIGHT;
|
const SIZE: usize = (WIDTH * HEIGHT) / 8;
|
||||||
const ALL_PLANES_SCREEN_SIZE: usize = (WIDTH * HEIGHT) / 8;
|
|
||||||
const WIDTH_IN_BYTES: usize = WIDTH / 8;
|
const WIDTH_IN_BYTES: usize = WIDTH / 8;
|
||||||
|
|
||||||
/// A basic interface for interacting with vga graphics mode 640x480x16
|
/// A basic interface for interacting with vga graphics mode 640x480x16
|
||||||
|
@ -48,11 +46,9 @@ impl Screen for Graphics640x480x16 {
|
||||||
impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
impl GraphicsWriter<Color16> for Graphics640x480x16 {
|
||||||
fn clear_screen(&self, color: Color16) {
|
fn clear_screen(&self, color: Color16) {
|
||||||
self.set_write_mode_2();
|
self.set_write_mode_2();
|
||||||
let (_vga, frame_buffer) = self.get_frame_buffer();
|
unsafe {
|
||||||
for offset in 0..ALL_PLANES_SCREEN_SIZE {
|
self.get_frame_buffer()
|
||||||
unsafe {
|
.write_bytes(u8::from(color), Self::SIZE);
|
||||||
frame_buffer.add(offset).write_volatile(u8::from(color));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +103,7 @@ impl Graphics640x480x16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_write_mode_0(self, color: Color16) {
|
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_set_reset(color);
|
||||||
vga.graphics_controller_registers
|
vga.graphics_controller_registers
|
||||||
.write_enable_set_reset(0xF);
|
.write_enable_set_reset(0xF);
|
||||||
|
@ -116,7 +112,7 @@ impl Graphics640x480x16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_write_mode_2(self) {
|
fn set_write_mode_2(self) {
|
||||||
let (mut vga, _frame_buffer) = self.get_frame_buffer();
|
let mut vga = VGA.lock();
|
||||||
vga.graphics_controller_registers
|
vga.graphics_controller_registers
|
||||||
.set_write_mode(WriteMode::Mode2);
|
.set_write_mode(WriteMode::Mode2);
|
||||||
vga.graphics_controller_registers.set_bit_mask(0xFF);
|
vga.graphics_controller_registers.set_bit_mask(0xFF);
|
||||||
|
@ -124,21 +120,14 @@ impl Graphics640x480x16 {
|
||||||
.set_plane_mask(PlaneMask::ALL_PLANES);
|
.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]
|
#[inline]
|
||||||
fn _set_pixel(self, x: usize, y: usize, color: Color16) {
|
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 offset = x / 8 + y * WIDTH_IN_BYTES;
|
||||||
let pixel_mask = 0x80 >> (x & 0x07);
|
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 {
|
unsafe {
|
||||||
frame_buffer.add(offset).read_volatile();
|
frame_buffer.add(offset).read_volatile();
|
||||||
frame_buffer.add(offset).write_volatile(u8::from(color));
|
frame_buffer.add(offset).write_volatile(u8::from(color));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Writers for common vga modes.
|
//! Writers for common vga modes.
|
||||||
mod graphics_320x200x256;
|
mod graphics_320x200x256;
|
||||||
|
mod graphics_320x240x256;
|
||||||
mod graphics_640x480x16;
|
mod graphics_640x480x16;
|
||||||
mod text_40x25;
|
mod text_40x25;
|
||||||
mod text_40x50;
|
mod text_40x50;
|
||||||
|
@ -14,6 +15,7 @@ use super::{
|
||||||
use spinning_top::SpinlockGuard;
|
use spinning_top::SpinlockGuard;
|
||||||
|
|
||||||
pub use graphics_320x200x256::Graphics320x200x256;
|
pub use graphics_320x200x256::Graphics320x200x256;
|
||||||
|
pub use graphics_320x240x256::Graphics320x240x256;
|
||||||
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;
|
||||||
|
@ -197,4 +199,8 @@ pub trait GraphicsWriter<Color> {
|
||||||
fn set_pixel(&self, x: usize, y: usize, color: Color);
|
fn set_pixel(&self, x: usize, y: usize, color: Color);
|
||||||
/// Sets the graphics device to a `VideoMode`.
|
/// Sets the graphics device to a `VideoMode`.
|
||||||
fn set_mode(&self);
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue