Created
March 4, 2020 23:49
-
-
Save RKennedy9064/374ed861f743079e43b1c5da87af63f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mod vga; | |
mod vga_configurations; | |
mod vga_fonts; | |
mod vga_registers; | |
pub use vga::VideoMode; | |
pub use vga::VGA; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use super::{ | |
vga_configurations::MODE_3_CONFIGURATION, | |
vga_fonts::{TEXT_8X16_FONT, VgaFont}, | |
vga_registers::{ | |
AttributeControllerRegisters, CrtcControllerIndex, CrtcControllerRegisters, EmulationMode, | |
GeneralRegisters, GraphicsControllerIndex, GraphicsControllerRegisters, SequencerIndex, | |
SequencerRegisters, | |
}, | |
}; | |
use conquer_once::spin::Lazy; | |
use spinning_top::Spinlock; | |
pub static VGA: Lazy<Spinlock<Vga>> = Lazy::new(|| Spinlock::new(Vga::new())); | |
#[derive(Debug)] | |
#[repr(u32)] | |
enum FrameBuffer { | |
GraphicsMode = 0xa0000, | |
CgaMode = 0xb8000, | |
MdaMode = 0xb0000, | |
} | |
impl From<u8> for FrameBuffer { | |
fn from(value: u8) -> FrameBuffer { | |
match value { | |
0x1 => FrameBuffer::GraphicsMode, | |
0x2 => FrameBuffer::MdaMode, | |
0x3 => FrameBuffer::CgaMode, | |
_ => panic!("{:X} is not a valid FrameBuffer value", value), | |
} | |
} | |
} | |
impl From<FrameBuffer> for u32 { | |
fn from(value: FrameBuffer) -> u32 { | |
value as u32 | |
} | |
} | |
#[allow(dead_code)] | |
#[derive(Debug)] | |
#[repr(u8)] | |
enum Plane { | |
Plane0 = 0x0, | |
Plane1 = 0x1, | |
Plane2 = 0x2, | |
Plane3 = 0x3, | |
} | |
impl From<Plane> for u8 { | |
fn from(value: Plane) -> u8 { | |
value as u8 | |
} | |
} | |
#[derive(Debug)] | |
pub enum VideoMode { | |
Mode3, | |
Mode12, | |
Mode13, | |
ModeX, | |
} | |
#[derive(Debug)] | |
pub struct Vga { | |
general_registers: GeneralRegisters, | |
sequencer_registers: SequencerRegisters, | |
graphics_controller_registers: GraphicsControllerRegisters, | |
attribute_controller_registers: AttributeControllerRegisters, | |
crtc_controller_registers: CrtcControllerRegisters, | |
} | |
impl Vga { | |
fn new() -> Vga { | |
Vga { | |
general_registers: GeneralRegisters::new(), | |
sequencer_registers: SequencerRegisters::new(), | |
graphics_controller_registers: GraphicsControllerRegisters::new(), | |
attribute_controller_registers: AttributeControllerRegisters::new(), | |
crtc_controller_registers: CrtcControllerRegisters::new(), | |
} | |
} | |
pub fn set_video_mode(&mut self, video_mode: VideoMode) { | |
match video_mode { | |
VideoMode::Mode3 => self.set_video_mode_3(), | |
_ => panic!("VideoMode::{:?} hasn't been implemented yet", video_mode), | |
} | |
} | |
fn get_frame_buffer(&mut self) -> *mut u8 { | |
let miscellaneous_graphics = self | |
.graphics_controller_registers | |
.read(GraphicsControllerIndex::Miscellaneous); | |
let memory_map_mode = (miscellaneous_graphics >> 0x2) & 0x3; | |
let frame_buffer = FrameBuffer::from(memory_map_mode); | |
u32::from(frame_buffer) as *mut u8 | |
} | |
/// `I/O Address Select` Bit 0 `(value & 0x1)` of MSR selects 3Bxh or 3Dxh as the I/O address for the CRT Controller | |
/// registers, the Feature Control Register (FCR), and Input Status Register 1 (ST01). Presently | |
/// ignored (whole range is claimed), but will "ignore" 3Bx for color configuration or 3Dx for | |
/// monochrome. | |
/// Note that it is typical in AGP chipsets to shadow this bit and properly steer I/O cycles to the | |
/// proper bus for operation where a MDA exists on another bus such as ISA. | |
/// | |
/// 0 = Select 3Bxh I/O address `(EmulationMode::Mda)` | |
/// | |
/// 1 = Select 3Dxh I/O address `(EmulationMode:Cga)` | |
fn get_emulation_mode(&mut self) -> EmulationMode { | |
EmulationMode::from(self.general_registers.read_msr() & 0x1) | |
} | |
fn load_font(&mut self, vga_font: &VgaFont) { | |
// Save registers | |
let ( | |
plane_mask, | |
sequencer_memory_mode, | |
read_plane_select, | |
graphics_mode, | |
miscellaneous_graphics, | |
) = self.save_font_registers(); | |
// Switch to flat addressing | |
self.sequencer_registers | |
.write(SequencerIndex::MemoryMode, sequencer_memory_mode | 0x04); | |
// Disable Even/Odd addressing | |
self.graphics_controller_registers | |
.write(GraphicsControllerIndex::GraphicsMode, graphics_mode & !0x10); | |
self.graphics_controller_registers.write( | |
GraphicsControllerIndex::Miscellaneous, | |
miscellaneous_graphics & !0x02, | |
); | |
// Write font to plane | |
self.set_plane(Plane::Plane2); | |
let frame_buffer = self.get_frame_buffer(); | |
for character in 0..vga_font.characters { | |
for row in 0..vga_font.character_height { | |
let offset = (character * 32) + row; | |
let font_offset = (character * vga_font.character_height) + row; | |
unsafe { | |
frame_buffer | |
.offset(offset as isize) | |
.write_volatile(vga_font.font_data[font_offset as usize]); | |
} | |
} | |
} | |
self.restore_font_registers( | |
plane_mask, | |
sequencer_memory_mode, | |
read_plane_select, | |
graphics_mode, | |
miscellaneous_graphics, | |
); | |
} | |
fn restore_font_registers( | |
&mut self, | |
plane_mask: u8, | |
sequencer_memory_mode: u8, | |
read_plane_select: u8, | |
graphics_mode: u8, | |
miscellaneous_graphics: u8, | |
) { | |
self.sequencer_registers | |
.write(SequencerIndex::PlaneMask, plane_mask); | |
self.sequencer_registers | |
.write(SequencerIndex::MemoryMode, sequencer_memory_mode); | |
self.graphics_controller_registers | |
.write(GraphicsControllerIndex::ReadPlaneSelect, read_plane_select); | |
self.graphics_controller_registers | |
.write(GraphicsControllerIndex::GraphicsMode, graphics_mode); | |
self.graphics_controller_registers.write( | |
GraphicsControllerIndex::Miscellaneous, | |
miscellaneous_graphics, | |
); | |
} | |
fn save_font_registers(&mut self) -> (u8, u8, u8, u8, u8) { | |
( | |
self.sequencer_registers.read(SequencerIndex::PlaneMask), | |
self.sequencer_registers.read(SequencerIndex::MemoryMode), | |
self.graphics_controller_registers | |
.read(GraphicsControllerIndex::ReadPlaneSelect), | |
self.graphics_controller_registers | |
.read(GraphicsControllerIndex::GraphicsMode), | |
self.graphics_controller_registers | |
.read(GraphicsControllerIndex::Miscellaneous), | |
) | |
} | |
fn set_plane(&mut self, plane: Plane) { | |
let mut plane = u8::from(plane); | |
plane &= 0x3; | |
self.graphics_controller_registers | |
.write(GraphicsControllerIndex::ReadPlaneSelect, plane); | |
self.sequencer_registers | |
.write(SequencerIndex::PlaneMask, 0x1 << plane); | |
} | |
/// Sets the video card to Mode 3. | |
fn set_video_mode_3(&mut self) { | |
let configuration = &MODE_3_CONFIGURATION; | |
let emulation_mode = self.get_emulation_mode(); | |
// Set miscellaneous output | |
self.general_registers | |
.write_msr(configuration.miscellaneous_output); | |
// Set the sequencer registers. | |
for (index, value) in configuration.sequencer_registers { | |
self.sequencer_registers.write(*index, *value); | |
} | |
// Unlock the crtc registers. | |
self.unlock_crtc_registers(emulation_mode); | |
// Set the crtc registers. | |
for (index, value) in configuration.crtc_controller_registers { | |
self.crtc_controller_registers | |
.write(emulation_mode, *index, *value); | |
} | |
// Set the grx registers. | |
for (index, value) in configuration.graphics_controller_registers { | |
self.graphics_controller_registers.write(*index, *value); | |
} | |
// Blank the screen so the palette registers are unlocked. | |
self.attribute_controller_registers | |
.blank_screen(emulation_mode); | |
// Set the arx registers. | |
for (index, value) in configuration.attribute_controller_registers { | |
self.attribute_controller_registers | |
.write(emulation_mode, *index, *value); | |
} | |
// Unblank the screen so the palette registers are locked. | |
self.attribute_controller_registers | |
.unblank_screen(emulation_mode); | |
self.load_font(&TEXT_8X16_FONT); | |
} | |
/// Unlocks the CRTC registers by setting bit 7 to 0 `(value & 0x7F)`. | |
/// | |
/// `Protect Registers [0:7]`: Note that the ability to write to Bit 4 of the Overflow Register (CR07) | |
/// is not affected by this bit (i.e., bit 4 of the Overflow Register is always writeable). | |
/// | |
/// 0 = Enable writes to registers `CR[00:07]` | |
/// | |
/// 1 = Disable writes to registers `CR[00:07]` | |
fn unlock_crtc_registers(&mut self, emulation_mode: EmulationMode) { | |
// Setting bit 7 to 1 used to be required for `VGA`, but says it's | |
// ignored in modern hardware. Setting it to 1 just to be safe for older | |
// hardware. More information can be found here | |
// https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-hsw-display.pdf | |
// under `CR03 - Horizontal Blanking End Register`. | |
let horizontal_blanking_end = self | |
.crtc_controller_registers | |
.read(emulation_mode, CrtcControllerIndex::HorizontalBlankingEnd); | |
self.crtc_controller_registers.write( | |
emulation_mode, | |
CrtcControllerIndex::HorizontalBlankingEnd, | |
horizontal_blanking_end | 0x80, | |
); | |
let vertical_sync_end = self | |
.crtc_controller_registers | |
.read(emulation_mode, CrtcControllerIndex::VerticalSyncEnd); | |
self.crtc_controller_registers.write( | |
emulation_mode, | |
CrtcControllerIndex::VerticalSyncEnd, | |
vertical_sync_end & 0x7F, | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use super::vga_registers::{ | |
AttributeControllerIndex, CrtcControllerIndex, GraphicsControllerIndex, SequencerIndex, | |
}; | |
/// Store register values for various `VGA` modes. | |
#[derive(Debug)] | |
pub struct VgaConfiguration { | |
pub miscellaneous_output: u8, | |
pub sequencer_registers: &'static [(SequencerIndex, u8)], | |
pub crtc_controller_registers: &'static [(CrtcControllerIndex, u8)], | |
pub graphics_controller_registers: &'static [(GraphicsControllerIndex, u8)], | |
pub attribute_controller_registers: &'static [(AttributeControllerIndex, u8)], | |
} | |
/// Register values for `VGA` mode 3 (80x25 Text). | |
/// | |
/// Configuration values acquired from https://github.com/FlingOS/FlingOS/blob/develop/Kernel/Libraries/Kernel.VGA/Configurations/Text/T_80x25.cs | |
pub const MODE_3_CONFIGURATION: VgaConfiguration = VgaConfiguration { | |
miscellaneous_output: 0x67, | |
sequencer_registers: &[ | |
(SequencerIndex::SequencerReset, 0x03), | |
(SequencerIndex::ClockingMode, 0x00), | |
(SequencerIndex::PlaneMask, 0x03), | |
(SequencerIndex::CharacterFont, 0x00), | |
(SequencerIndex::MemoryMode, 0x02), | |
], | |
crtc_controller_registers: &[ | |
(CrtcControllerIndex::HorizontalTotal, 0x5F), | |
(CrtcControllerIndex::HorizontalDisplayEnableEnd, 0x4F), | |
(CrtcControllerIndex::HorizontalBlankingStart, 0x50), | |
(CrtcControllerIndex::HorizontalBlankingEnd, 0x82), | |
(CrtcControllerIndex::HorizontalSyncStart, 0x55), | |
(CrtcControllerIndex::HorizontalSyncEnd, 0x81), | |
(CrtcControllerIndex::VeritcalTotal, 0xBF), | |
(CrtcControllerIndex::Overflow, 0x1F), | |
(CrtcControllerIndex::PresetRowScan, 0x00), | |
(CrtcControllerIndex::MaximumScanLine, 0x4F), | |
(CrtcControllerIndex::TextCursorStart, 0x0D), | |
(CrtcControllerIndex::TextCursorEnd, 0x0E), | |
(CrtcControllerIndex::StartAddressHigh, 0x00), | |
(CrtcControllerIndex::StartAddressLow, 0x00), | |
(CrtcControllerIndex::TextCursorLocationHigh, 0x00), | |
(CrtcControllerIndex::TextCursorLocationLow, 0x50), | |
(CrtcControllerIndex::VerticalSyncStart, 0x9C), | |
(CrtcControllerIndex::VerticalSyncEnd, 0x8E), | |
(CrtcControllerIndex::VerticalDisplayEnableEnd, 0x8F), | |
(CrtcControllerIndex::Offset, 0x28), | |
(CrtcControllerIndex::UnderlineLocationRegister, 0x1F), | |
(CrtcControllerIndex::VerticalBlankingStart, 0x96), | |
(CrtcControllerIndex::VerticalBlankingEnd, 0xB9), | |
(CrtcControllerIndex::ModeControl, 0xA3), | |
(CrtcControllerIndex::LineCompare, 0xFF), | |
], | |
graphics_controller_registers: &[ | |
(GraphicsControllerIndex::SetReset, 0x00), | |
(GraphicsControllerIndex::EnableSetReset, 0x00), | |
(GraphicsControllerIndex::ColorCompare, 0x00), | |
(GraphicsControllerIndex::DataRotate, 0x00), | |
(GraphicsControllerIndex::ReadPlaneSelect, 0x00), | |
(GraphicsControllerIndex::GraphicsMode, 0x10), | |
(GraphicsControllerIndex::Miscellaneous, 0x0E), | |
(GraphicsControllerIndex::ColorDontCare, 0x00), | |
(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, 0x0C), | |
(AttributeControllerIndex::OverscanColor, 0x00), | |
(AttributeControllerIndex::MemoryPlaneEnable, 0x0F), | |
(AttributeControllerIndex::HorizontalPixelPanning, 0x08), | |
(AttributeControllerIndex::ColorSelect, 0x00), | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct VgaFont { | |
pub characters: u16, | |
pub character_height: u16, | |
pub font_data: &'static [u8], | |
} | |
/// Font data obtained from https://www.singlix.com/trdos/archive/vga/Graphics%20in%20pmode.pdf | |
pub const TEXT_8X16_FONT: VgaFont = VgaFont { | |
characters: 256, | |
character_height: 16, | |
font_data: &[ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, | |
0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, | |
0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, | |
0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, | |
0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, | |
0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x0E, | |
0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, | |
0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, | |
0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, | |
0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, | |
0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, | |
0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, | |
0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, | |
0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, | |
0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, | |
0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, | |
0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, | |
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, | |
0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, | |
0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, | |
0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, | |
0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, | |
0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x06, | |
0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, | |
0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, | |
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, | |
0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, | |
0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, | |
0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, | |
0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, | |
0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, | |
0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, | |
0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, | |
0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, | |
0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, | |
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, | |
0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, | |
0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, | |
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, | |
0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, | |
0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, | |
0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, | |
0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, | |
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, | |
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, | |
0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, | |
0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0C, 0x0C, | |
0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, | |
0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, 0x00, | |
0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, | |
0x3C, 0x00, 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, | |
0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, | |
0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, | |
0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, | |
0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, | |
0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, | |
0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, | |
0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, | |
0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, | |
0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, | |
0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, | |
0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, | |
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x00, | |
0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, | |
0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, | |
0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, | |
0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, | |
0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, | |
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, | |
0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, | |
0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6C, | |
0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, | |
0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, | |
0x0C, 0x78, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, | |
0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, | |
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, | |
0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, | |
0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, | |
0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, | |
0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, | |
0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, | |
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, | |
0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, | |
0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | |
0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, | |
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, | |
0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, | |
0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, | |
0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, | |
0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, | |
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x55, 0xAA, 0x55, | |
0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0xDD, 0x77, | |
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, | |
0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, | |
0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, | |
0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, | |
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, | |
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, | |
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, | |
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, | |
0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, | |
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, | |
0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, | |
0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, | |
0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, | |
0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x18, | |
0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | |
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, | |
0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, | |
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, | |
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0C, 0x0C, | |
0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x6C, | |
0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, | |
0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use x86_64::instructions::port::{Port, PortReadOnly, PortWriteOnly}; | |
const ST00_READ_ADDRESS: u16 = 0x3C2; | |
const ST01_READ_CGA_ADDRESS: u16 = 0x3DA; | |
const ST01_READ_MDA_ADDRESS: u16 = 0x3BA; | |
const FCR_READ_ADDRESS: u16 = 0x3CA; | |
const FCR_CGA_WRITE_ADDRESS: u16 = 0x3DA; | |
const FCR_MDA_WRITE_ADDRESS: u16 = 0x3BA; | |
const MSR_READ_ADDRESS: u16 = 0x3CC; | |
const MSR_WRITE_ADDRESS: u16 = 0x3C2; | |
const SRX_INDEX_ADDRESS: u16 = 0x3C4; | |
const SRX_DATA_ADDRESS: u16 = 0x3C5; | |
const GRX_INDEX_ADDRESS: u16 = 0x3CE; | |
const GRX_DATA_ADDRESS: u16 = 0x3CF; | |
const ARX_INDEX_ADDRESS: u16 = 0x3C0; | |
const ARX_DATA_ADDRESS: u16 = 0x3C1; | |
const CRX_INDEX_CGA_ADDRESS: u16 = 0x3D4; | |
const CRX_INDEX_MDA_ADDRESS: u16 = 0x3B4; | |
const CRX_DATA_CGA_ADDRESS: u16 = 0x3D5; | |
const CRX_DATA_MDA_ADDRESS: u16 = 0x3B5; | |
#[derive(Debug, Copy, Clone)] | |
#[repr(u8)] | |
pub enum EmulationMode { | |
Mda = 0x0, | |
Cga = 0x1, | |
} | |
impl From<u8> for EmulationMode { | |
fn from(value: u8) -> EmulationMode { | |
match value { | |
0x0 => EmulationMode::Mda, | |
0x1 => EmulationMode::Cga, | |
_ => panic!("{} is an invalid emulation mode", value), | |
} | |
} | |
} | |
#[derive(Debug, Clone, Copy)] | |
#[repr(u8)] | |
pub enum SequencerIndex { | |
SequencerReset = 0x0, | |
ClockingMode = 0x1, | |
PlaneMask = 0x2, | |
CharacterFont = 0x3, | |
MemoryMode = 0x4, | |
CounterReset = 0x7, | |
} | |
impl From<SequencerIndex> for u8 { | |
fn from(value: SequencerIndex) -> u8 { | |
value as u8 | |
} | |
} | |
#[derive(Debug, Copy, Clone)] | |
#[repr(u8)] | |
pub enum GraphicsControllerIndex { | |
SetReset = 0x0, | |
EnableSetReset = 0x1, | |
ColorCompare = 0x2, | |
DataRotate = 0x3, | |
ReadPlaneSelect = 0x4, | |
GraphicsMode = 0x5, | |
Miscellaneous = 0x6, | |
ColorDontCare = 0x7, | |
BitMask = 0x8, | |
AddressMapping = 0x10, | |
PageSelector = 0x11, | |
SoftwareFlags = 0x18, | |
} | |
impl From<GraphicsControllerIndex> for u8 { | |
fn from(value: GraphicsControllerIndex) -> u8 { | |
value as u8 | |
} | |
} | |
#[derive(Debug, Copy, Clone)] | |
#[repr(u8)] | |
pub enum AttributeControllerIndex { | |
PaletteRegister0 = 0x00, | |
PaletteRegister1 = 0x01, | |
PaletteRegister2 = 0x02, | |
PaletteRegister3 = 0x03, | |
PaletteRegister4 = 0x04, | |
PaletteRegister5 = 0x05, | |
PaletteRegister6 = 0x06, | |
PaletteRegister7 = 0x07, | |
PaletteRegister8 = 0x08, | |
PaletteRegister9 = 0x09, | |
PaletteRegisterA = 0x0A, | |
PaletteRegisterB = 0x0B, | |
PaletteRegisterC = 0x0C, | |
PaletteRegisterD = 0x0D, | |
PaletteRegisterE = 0x0E, | |
PaletteRegisterF = 0x0F, | |
ModeControl = 0x10, | |
OverscanColor = 0x11, | |
MemoryPlaneEnable = 0x12, | |
HorizontalPixelPanning = 0x13, | |
ColorSelect = 0x14, | |
} | |
impl From<AttributeControllerIndex> for u8 { | |
fn from(value: AttributeControllerIndex) -> u8 { | |
value as u8 | |
} | |
} | |
#[derive(Debug, Copy, Clone)] | |
#[repr(u8)] | |
pub enum CrtcControllerIndex { | |
HorizontalTotal = 0x00, | |
HorizontalDisplayEnableEnd = 0x01, | |
HorizontalBlankingStart = 0x02, | |
HorizontalBlankingEnd = 0x03, | |
HorizontalSyncStart = 0x04, | |
HorizontalSyncEnd = 0x05, | |
VeritcalTotal = 0x06, | |
Overflow = 0x07, | |
PresetRowScan = 0x08, | |
MaximumScanLine = 0x09, | |
TextCursorStart = 0x0A, | |
TextCursorEnd = 0x0B, | |
StartAddressHigh = 0x0C, | |
StartAddressLow = 0x0D, | |
TextCursorLocationHigh = 0x0E, | |
TextCursorLocationLow = 0x0F, | |
VerticalSyncStart = 0x10, | |
VerticalSyncEnd = 0x11, | |
VerticalDisplayEnableEnd = 0x12, | |
Offset = 0x13, | |
UnderlineLocationRegister = 0x14, | |
VerticalBlankingStart = 0x15, | |
VerticalBlankingEnd = 0x16, | |
ModeControl = 0x17, | |
LineCompare = 0x18, | |
MemoryReadLatchData = 0x22, | |
ToggleStateOfAttributeController = 0x24, | |
} | |
impl From<CrtcControllerIndex> for u8 { | |
fn from(value: CrtcControllerIndex) -> u8 { | |
value as u8 | |
} | |
} | |
#[derive(Debug)] | |
pub struct GeneralRegisters { | |
st00_read: PortReadOnly<u8>, | |
st01_read_cga: PortReadOnly<u8>, | |
st01_read_mda: PortReadOnly<u8>, | |
fcr_read: PortReadOnly<u8>, | |
fcr_write_cga: PortWriteOnly<u8>, | |
fcr_write_mda: PortWriteOnly<u8>, | |
msr_read: PortReadOnly<u8>, | |
msr_write: PortWriteOnly<u8>, | |
} | |
impl GeneralRegisters { | |
pub fn new() -> GeneralRegisters { | |
GeneralRegisters { | |
st00_read: PortReadOnly::new(ST00_READ_ADDRESS), | |
st01_read_cga: PortReadOnly::new(ST01_READ_CGA_ADDRESS), | |
st01_read_mda: PortReadOnly::new(ST01_READ_MDA_ADDRESS), | |
fcr_read: PortReadOnly::new(FCR_READ_ADDRESS), | |
fcr_write_cga: PortWriteOnly::new(FCR_CGA_WRITE_ADDRESS), | |
fcr_write_mda: PortWriteOnly::new(FCR_MDA_WRITE_ADDRESS), | |
msr_read: PortReadOnly::new(MSR_READ_ADDRESS), | |
msr_write: PortWriteOnly::new(MSR_WRITE_ADDRESS), | |
} | |
} | |
pub fn read_msr(&mut self) -> u8 { | |
unsafe { self.msr_read.read() } | |
} | |
pub fn write_msr(&mut self, value: u8) { | |
unsafe { | |
self.msr_write.write(value); | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct SequencerRegisters { | |
srx_index: Port<u8>, | |
srx_data: Port<u8>, | |
} | |
impl SequencerRegisters { | |
pub fn new() -> SequencerRegisters { | |
SequencerRegisters { | |
srx_index: Port::new(SRX_INDEX_ADDRESS), | |
srx_data: Port::new(SRX_DATA_ADDRESS), | |
} | |
} | |
pub fn read(&mut self, index: SequencerIndex) -> u8 { | |
self.set_index(index); | |
unsafe { self.srx_data.read() } | |
} | |
pub fn write(&mut self, index: SequencerIndex, value: u8) { | |
self.set_index(index); | |
unsafe { | |
self.srx_data.write(value); | |
} | |
} | |
fn set_index(&mut self, index: SequencerIndex) { | |
unsafe { | |
self.srx_index.write(u8::from(index)); | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct GraphicsControllerRegisters { | |
grx_index: Port<u8>, | |
grx_data: Port<u8>, | |
} | |
impl GraphicsControllerRegisters { | |
pub fn new() -> GraphicsControllerRegisters { | |
GraphicsControllerRegisters { | |
grx_index: Port::new(GRX_INDEX_ADDRESS), | |
grx_data: Port::new(GRX_DATA_ADDRESS), | |
} | |
} | |
pub fn read(&mut self, index: GraphicsControllerIndex) -> u8 { | |
self.set_index(index); | |
unsafe { self.grx_data.read() } | |
} | |
pub fn write(&mut self, index: GraphicsControllerIndex, value: u8) { | |
self.set_index(index); | |
unsafe { | |
self.grx_data.write(value); | |
} | |
} | |
fn set_index(&mut self, index: GraphicsControllerIndex) { | |
unsafe { | |
self.grx_index.write(u8::from(index)); | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct AttributeControllerRegisters { | |
arx_index: Port<u8>, | |
arx_data: Port<u8>, | |
st01_read_cga: Port<u8>, | |
st01_read_mda: Port<u8>, | |
} | |
impl AttributeControllerRegisters { | |
pub fn new() -> AttributeControllerRegisters { | |
AttributeControllerRegisters { | |
arx_index: Port::new(ARX_INDEX_ADDRESS), | |
arx_data: Port::new(ARX_DATA_ADDRESS), | |
st01_read_cga: Port::new(ST01_READ_CGA_ADDRESS), | |
st01_read_mda: Port::new(ST01_READ_MDA_ADDRESS), | |
} | |
} | |
pub fn write( | |
&mut self, | |
emulation_mode: EmulationMode, | |
index: AttributeControllerIndex, | |
value: u8, | |
) { | |
self.toggle_index(emulation_mode); | |
self.set_index(index); | |
unsafe { | |
self.arx_index.write(value); | |
} | |
} | |
fn set_index(&mut self, index: AttributeControllerIndex) { | |
unsafe { | |
self.arx_index.write(u8::from(index)); | |
} | |
} | |
fn toggle_index(&mut self, emulation_mode: EmulationMode) { | |
let st01_read = match emulation_mode { | |
EmulationMode::Cga => &mut self.st01_read_cga, | |
EmulationMode::Mda => &mut self.st01_read_mda, | |
}; | |
unsafe { | |
st01_read.read(); | |
} | |
} | |
/// Video Enable. Note that In the VGA standard, this is called the "Palette Address Source" bit. | |
/// Clearing this bit will cause the VGA display data to become all 00 index values. For the default | |
/// palette, this will cause a black screen. The video timing signals continue. Another control bit will | |
/// turn video off and stop the data fetches. | |
/// | |
/// 0 = Disable. Attribute controller color registers (AR[00:0F]) can be accessed by the CPU. | |
/// | |
/// 1 = Enable. Attribute controller color registers (AR[00:0F]) are inaccessible by the CPU. | |
pub fn blank_screen(&mut self, emulation_mode: EmulationMode) { | |
self.toggle_index(emulation_mode); | |
let arx_index_value = unsafe { self.arx_index.read() }; | |
unsafe { | |
self.arx_index.write(arx_index_value & 0xDF); | |
} | |
} | |
/// Video Enable. Note that In the VGA standard, this is called the "Palette Address Source" bit. | |
/// Clearing this bit will cause the VGA display data to become all 00 index values. For the default | |
/// palette, this will cause a black screen. The video timing signals continue. Another control bit will | |
/// turn video off and stop the data fetches. | |
/// | |
/// 0 = Disable. Attribute controller color registers (AR[00:0F]) can be accessed by the CPU. | |
/// | |
/// 1 = Enable. Attribute controller color registers (AR[00:0F]) are inaccessible by the CPU. | |
pub fn unblank_screen(&mut self, emulation_mode: EmulationMode) { | |
self.toggle_index(emulation_mode); | |
let arx_index_value = unsafe { self.arx_index.read() }; | |
unsafe { | |
self.arx_index.write(arx_index_value | 0x20); | |
} | |
} | |
} | |
#[derive(Debug)] | |
pub struct CrtcControllerRegisters { | |
crx_index_cga: Port<u8>, | |
crx_index_mda: Port<u8>, | |
crx_data_cga: Port<u8>, | |
crx_data_mda: Port<u8>, | |
} | |
impl CrtcControllerRegisters { | |
pub fn new() -> CrtcControllerRegisters { | |
CrtcControllerRegisters { | |
crx_index_cga: Port::new(CRX_INDEX_CGA_ADDRESS), | |
crx_index_mda: Port::new(CRX_INDEX_MDA_ADDRESS), | |
crx_data_cga: Port::new(CRX_DATA_CGA_ADDRESS), | |
crx_data_mda: Port::new(CRX_DATA_MDA_ADDRESS), | |
} | |
} | |
pub fn read(&mut self, emulation_mode: EmulationMode, index: CrtcControllerIndex) -> u8 { | |
self.set_index(emulation_mode, index); | |
unsafe { self.get_data_port(emulation_mode).read() } | |
} | |
pub fn write(&mut self, emulation_mode: EmulationMode, index: CrtcControllerIndex, value: u8) { | |
self.set_index(emulation_mode, index); | |
unsafe { | |
self.get_data_port(emulation_mode).write(value); | |
} | |
} | |
fn set_index(&mut self, emulation_mode: EmulationMode, index: CrtcControllerIndex) { | |
unsafe { | |
self.get_index_port(emulation_mode).write(u8::from(index)); | |
} | |
} | |
fn get_data_port(&mut self, emulation_mode: EmulationMode) -> &mut Port<u8> { | |
match emulation_mode { | |
EmulationMode::Cga => &mut self.crx_data_cga, | |
EmulationMode::Mda => &mut self.crx_data_mda, | |
} | |
} | |
fn get_index_port(&mut self, emulation_mode: EmulationMode) -> &mut Port<u8> { | |
match emulation_mode { | |
EmulationMode::Cga => &mut self.crx_index_cga, | |
EmulationMode::Mda => &mut self.crx_index_mda, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment