use crate::gpu::graphic_card::GraphicCard;
impl GFXMode {
pub const MODE_TEXT_80_25: u16 = 0x0003;
}
#[derive(Clone, Debug, PartialEq)]
pub enum GFXMode {
TEXT,
CGA2,
CGA4,
EGA,
VGA,
TANDY16,
LIN4,
LIN8,
LIN15,
LIN16,
LIN24,
LIN32,
}
impl Default for GFXMode {
fn default() -> Self { GFXMode::TEXT }
}
#[derive(Clone, Default)]
pub struct VideoModeBlock {
pub mode: u16,
pub kind: GFXMode,
pub swidth: u32, pub sheight: u32, pub twidth: usize,
pub theight: usize,
pub cwidth: usize, pub cheight: usize, pub ptotal: u8, pub pstart: u32,
pub plength: usize,
pub htotal: u32, pub vtotal: usize, pub hdispend: usize, pub vdispend: usize, pub special: SpecialMode,
}
impl VideoModeBlock {
pub fn get_mode_block(card: &GraphicCard) -> Vec<VideoModeBlock> {
match *card {
GraphicCard::VGA => {
vga_mode_block().to_vec()
}
_ => panic!("unhandled {:?}", card)
}
}
pub fn is_text(&self) -> bool {
self.kind == GFXMode::TEXT
}
pub fn crtc_address(&self) -> u16 {
if self.mono_mode() {
0x3B4
} else {
0x3D4
}
}
pub fn mono_mode(&self) -> bool {
self.mode == 0x07 || self.mode == 0x0F
}
}
#[derive(Clone, PartialEq)]
pub struct SpecialMode {
pub ega_half_clock: bool,
pub doublescan: bool,
pub vga_pixel_double: bool,
pub s3_pixel_double: bool,
pub repeat1: bool,
pub cga_syncdouble: bool,
}
impl Default for SpecialMode {
fn default() -> Self {
SpecialMode {
ega_half_clock: false,
doublescan: false,
vga_pixel_double: false,
s3_pixel_double: false,
repeat1: false,
cga_syncdouble: false,
}
}
}
pub fn ega_mode_block() -> [VideoModeBlock; 12] {[
VideoModeBlock{mode: 0x000, kind: GFXMode::TEXT, swidth: 320, sheight: 350, twidth: 40, theight: 25, cwidth: 8, cheight: 14, ptotal: 8, pstart: 0xB_8000, plength: 0x0800, htotal: 50, vtotal: 366, hdispend: 40, vdispend: 350, special: SpecialMode{ega_half_clock: true, ..Default::default()}},
VideoModeBlock{mode: 0x001, kind: GFXMode::TEXT, swidth: 320, sheight: 350, twidth: 40, theight: 25, cwidth: 8, cheight: 14, ptotal: 8, pstart: 0xB_8000, plength: 0x0800, htotal: 50, vtotal: 366, hdispend: 40, vdispend: 350, special: SpecialMode{ega_half_clock: true, ..Default::default()}},
VideoModeBlock{mode: 0x002, kind: GFXMode::TEXT, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 8, pstart: 0xB_8000, plength: 0x1000, htotal: 96, vtotal: 366, hdispend: 80, vdispend: 350, special: SpecialMode::default()},
VideoModeBlock{mode: GFXMode::MODE_TEXT_80_25, kind: GFXMode::TEXT, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 8, pstart: 0xB_8000, plength: 0x1000, htotal: 96, vtotal: 366, hdispend: 80, vdispend: 350, special: Default::default()},
VideoModeBlock{mode: 0x004, kind: GFXMode::CGA4, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 60, vtotal: 262, hdispend: 40, vdispend: 200, special: SpecialMode{ega_half_clock: true, repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x005, kind: GFXMode::CGA4, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 60, vtotal: 262, hdispend: 40, vdispend: 200, special: SpecialMode{ega_half_clock: true, repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x006, kind: GFXMode::CGA2, swidth: 640, sheight: 200, twidth: 80, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 120, vtotal: 262, hdispend: 80, vdispend: 200, special: SpecialMode{repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x007, kind: GFXMode::TEXT, swidth: 720, sheight: 350, twidth: 80, theight: 25, cwidth: 9, cheight: 14, ptotal: 8, pstart: 0xB_0000, plength: 0x1000, htotal: 120, vtotal: 440, hdispend: 80, vdispend: 350, special: Default::default()},
VideoModeBlock{mode: 0x00D, kind: GFXMode::EGA, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 8, pstart: 0xA_0000, plength: 0x2000, htotal: 60, vtotal: 262, hdispend: 40, vdispend: 200, special: SpecialMode{ega_half_clock: true, ..Default::default()}},
VideoModeBlock{mode: 0x00E, kind: GFXMode::EGA, swidth: 640, sheight: 200, twidth: 80, theight: 25, cwidth: 8, cheight: 8, ptotal: 4, pstart: 0xA_0000, plength: 0x4000, htotal: 120, vtotal: 262, hdispend: 80, vdispend: 200, special: Default::default()},
VideoModeBlock{mode: 0x00F, kind: GFXMode::EGA, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 2, pstart: 0xA_0000, plength: 0x8000, htotal: 96, vtotal: 366, hdispend: 80, vdispend: 350, special: Default::default()},
VideoModeBlock{mode: 0x010, kind: GFXMode::EGA, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 2, pstart: 0xA_0000, plength: 0x8000, htotal: 96, vtotal: 366, hdispend: 80, vdispend: 350, special: Default::default()},
]}
pub fn vga_mode_block() -> [VideoModeBlock; 15] {[
VideoModeBlock{mode: 0x000, kind: GFXMode::TEXT, swidth: 360, sheight: 400, twidth: 40, theight: 25, cwidth: 9, cheight: 16, ptotal: 8, pstart: 0xB_8000, plength: 0x0800, htotal: 50, vtotal: 449, hdispend: 40, vdispend: 400, special: SpecialMode{ega_half_clock: true, ..Default::default()}},
VideoModeBlock{mode: 0x001, kind: GFXMode::TEXT, swidth: 360, sheight: 400, twidth: 40, theight: 25, cwidth: 9, cheight: 16, ptotal: 8, pstart: 0xB_8000, plength: 0x0800, htotal: 50, vtotal: 449, hdispend: 40, vdispend: 400, special: SpecialMode{ega_half_clock: true, ..Default::default()}},
VideoModeBlock{mode: 0x002, kind: GFXMode::TEXT, swidth: 720, sheight: 400, twidth: 80, theight: 25, cwidth: 9, cheight: 16, ptotal: 8, pstart: 0xB_8000, plength: 0x1000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: Default::default()},
VideoModeBlock{mode: GFXMode::MODE_TEXT_80_25, kind: GFXMode::TEXT, swidth: 720, sheight: 400, twidth: 80, theight: 25, cwidth: 9, cheight: 16, ptotal: 8, pstart: 0xB_8000, plength: 0x1000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: Default::default()},
VideoModeBlock{mode: 0x004, kind: GFXMode::CGA4, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 50, vtotal: 449, hdispend: 40, vdispend: 400, special: SpecialMode{ega_half_clock: true, doublescan: true, repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x005, kind: GFXMode::CGA4, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 50, vtotal: 449, hdispend: 40, vdispend: 400, special: SpecialMode{ega_half_clock: true, doublescan: true, repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x006, kind: GFXMode::CGA2, swidth: 640, sheight: 200, twidth: 80, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xB_8000, plength: 0x4000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: SpecialMode{doublescan: true, repeat1: true, ..Default::default()}},
VideoModeBlock{mode: 0x007, kind: GFXMode::TEXT, swidth: 720, sheight: 400, twidth: 80, theight: 25, cwidth: 9, cheight: 16, ptotal: 8, pstart: 0xB_0000, plength: 0x1000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: Default::default()},
VideoModeBlock{mode: 0x00D, kind: GFXMode::EGA, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 8, pstart: 0xA_0000, plength: 0x2000, htotal: 50, vtotal: 449, hdispend: 40, vdispend: 400, special: SpecialMode{ega_half_clock: true, doublescan: true, ..Default::default()}},
VideoModeBlock{mode: 0x00E, kind: GFXMode::EGA, swidth: 640, sheight: 200, twidth: 80, theight: 25, cwidth: 8, cheight: 8, ptotal: 4, pstart: 0xA_0000, plength: 0x4000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: SpecialMode{doublescan: true, ..Default::default()}},
VideoModeBlock{mode: 0x00F, kind: GFXMode::EGA, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 2, pstart: 0xA_0000, plength: 0x8000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 350, special: Default::default()},
VideoModeBlock{mode: 0x010, kind: GFXMode::EGA, swidth: 640, sheight: 350, twidth: 80, theight: 25, cwidth: 8, cheight: 14, ptotal: 2, pstart: 0xA_0000, plength: 0x8000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 350, special: Default::default()},
VideoModeBlock{mode: 0x011, kind: GFXMode::EGA, swidth: 640, sheight: 480, twidth: 80, theight: 30, cwidth: 8, cheight: 16, ptotal: 1, pstart: 0xA_0000, plength: 0xA000, htotal: 100, vtotal: 525, hdispend: 80, vdispend: 480, special: Default::default()},
VideoModeBlock{mode: 0x012, kind: GFXMode::EGA, swidth: 640, sheight: 480, twidth: 80, theight: 30, cwidth: 8, cheight: 16, ptotal: 1, pstart: 0xA_0000, plength: 0xA000, htotal: 100, vtotal: 525, hdispend: 80, vdispend: 480, special: Default::default()},
VideoModeBlock{mode: 0x013, kind: GFXMode::VGA, swidth: 320, sheight: 200, twidth: 40, theight: 25, cwidth: 8, cheight: 8, ptotal: 1, pstart: 0xA_0000, plength: 0x2000, htotal: 100, vtotal: 449, hdispend: 80, vdispend: 400, special: SpecialMode{repeat1: true, ..Default::default()}},
]}