Created screen array

This commit is contained in:
Josh W 2023-11-16 01:23:22 -05:00
parent 45dcd8b0f6
commit 428079cf6b

View file

@ -16,60 +16,191 @@ use cp437::GLYPHS;
const SCREEN_HEIGHT: u32 = 350;
const SCREEN_WIDTH: u32 = 640;
const EGA_COLORS: [Color; 16] = [
Color::RGB(0x00, 0x00, 0x00), // Black
Color::RGB(0x00, 0x00, 0xaa), // Blue
Color::RGB(0x00, 0xaa, 0x00), // Green
Color::RGB(0x00, 0xaa, 0xaa), // Cyan
Color::RGB(0xaa, 0x00, 0x00), // Red
Color::RGB(0xaa, 0x00, 0xaa), // Magenta
Color::RGB(0xaa, 0x55, 0x00), // Brown
Color::RGB(0xaa, 0xaa, 0xaa), // White / Light Gray
Color::RGB(0x55, 0x55, 0x55), // Dark Gray / Bright Black
Color::RGB(0x55, 0x55, 0xff), // Bright Blue
Color::RGB(0x55, 0xff, 0x55), // Bright Green
Color::RGB(0x55, 0xff, 0xff), // Bright Cyan
Color::RGB(0xff, 0x55, 0x55), // Bright Red
Color::RGB(0xff, 0x55, 0xff), // Bright Magenta
Color::RGB(0xff, 0xff, 0x55), // Bright Yellow
Color::RGB(0xff, 0xff, 0xff), // Bright White
];
const GLYPH_COLUMNS: u8 = 80;
const GLYPH_ROWS: u8 = 25;
pub fn textattr_to_int(back: u8, fore: u8, codepoint: u8, blink: bool) -> usize {
let num = (usize::from(blink) << 15) +
(usize::from(back) << 12) +
(usize::from(fore) << 8) +
usize::from(codepoint);
const GLYPH_HEIGHT: u8 = 14;
const GLYPH_WIDTH: u8 = 8;
// Total glyph textures = 256 glyphs * 16 foreground colors * 8 background colors
const TOTAL_GLYPH_TEXTURES: usize = 256 * 16 * 8;
// Total screen blocks = GLYPH_COLUMNS * GLYPH_ROWS
const TOTAL_SCREEN_BLOCKS: usize = 2000;
pub enum EgaColors {
Black,
Blue,
Green,
Cyan,
Red,
Magenta,
Brown,
LightGray,
DarkGray,
BrightBlue,
BrightGreen,
BrightCyan,
BrightRed,
BrightMagenta,
BrightYellow,
White,
}
impl EgaColors {
pub fn as_u8(color: EgaColors) -> u8 {
let num = match color {
EgaColors::Black => 0,
EgaColors::Blue => 1,
EgaColors::Green => 2,
EgaColors::Cyan => 3,
EgaColors::Red => 4,
EgaColors::Magenta => 5,
EgaColors::Brown => 6,
EgaColors::LightGray => 7,
EgaColors::DarkGray => 8,
EgaColors::BrightBlue => 9,
EgaColors::BrightGreen => 10,
EgaColors::BrightCyan => 11,
EgaColors::BrightRed => 12,
EgaColors::BrightMagenta => 13,
EgaColors::BrightYellow => 14,
EgaColors::White => 15,
};
num
}
pub fn int_to_textattr(num: usize) -> (u8, u8, u8, bool) {
pub fn from_enum(color: EgaColors) -> Color {
let col = match color {
EgaColors::Black => Color::RGB(0x00, 0x00, 0x00),
EgaColors::Blue => Color::RGB(0x00, 0x00, 0xaa),
EgaColors::Green => Color::RGB(0x00, 0xaa, 0x00),
EgaColors::Cyan => Color::RGB(0x00, 0xaa, 0xaa),
EgaColors::Red => Color::RGB(0xaa, 0x00, 0x00),
EgaColors::Magenta => Color::RGB(0xaa, 0x00, 0xaa),
EgaColors::Brown => Color::RGB(0xaa, 0x55, 0x00),
EgaColors::LightGray => Color::RGB(0xaa, 0xaa, 0xaa),
EgaColors::DarkGray => Color::RGB(0x55, 0x55, 0x55),
EgaColors::BrightBlue => Color::RGB(0x55, 0x55, 0xff),
EgaColors::BrightGreen => Color::RGB(0x55, 0xff, 0x55),
EgaColors::BrightCyan => Color::RGB(0x55, 0xff, 0xff),
EgaColors::BrightRed => Color::RGB(0xff, 0x55, 0x55),
EgaColors::BrightMagenta => Color::RGB(0xff, 0x55, 0xff),
EgaColors::BrightYellow => Color::RGB(0xff, 0xff, 0x55),
EgaColors::White => Color::RGB(0xff, 0xff, 0xff),
};
col
}
pub fn from_u8(num: u8) -> Color {
let col = match num {
0 => Color::RGB(0x00, 0x00, 0x00),
1 => Color::RGB(0x00, 0x00, 0xaa),
2 => Color::RGB(0x00, 0xaa, 0x00),
3 => Color::RGB(0x00, 0xaa, 0xaa),
4 => Color::RGB(0xaa, 0x00, 0x00),
5 => Color::RGB(0xaa, 0x00, 0xaa),
6 => Color::RGB(0xaa, 0x55, 0x00),
7 => Color::RGB(0xaa, 0xaa, 0xaa),
8 => Color::RGB(0x55, 0x55, 0x55),
9 => Color::RGB(0x55, 0x55, 0xff),
10 => Color::RGB(0x55, 0xff, 0x55),
11 => Color::RGB(0x55, 0xff, 0xff),
12 => Color::RGB(0xff, 0x55, 0x55),
13 => Color::RGB(0xff, 0x55, 0xff),
14 => Color::RGB(0xff, 0xff, 0x55),
15 => Color::RGB(0xff, 0xff, 0xff),
_ => panic!("Unknown value for EgaColors: {}", num),
};
col
}
}
#[derive(Clone, Copy)]
pub struct ScreenBlock {
blink: bool,
background: u8,
foreground: u8,
glyph: u8,
}
impl ScreenBlock {
pub fn new(blink: bool, background: u8, foreground: u8, glyph: u8) -> Self {
ScreenBlock { blink, background, foreground, glyph }
}
pub fn attrs_to_index(blink: bool, background: u8, foreground: u8, glyph: u8) -> usize {
let num = (usize::from(blink) << 15) +
(usize::from(background) << 12) +
(usize::from(foreground) << 8) +
usize::from(glyph);
num
}
pub fn index_to_attrs(num: usize) -> (bool, u8, u8, u8) {
let blink = (num >> 15) != 0;
let back = (num >> 12) as u8;
let fore = ((num >> 8) & 15) as u8;
let codepoint = (num & 255) as u8;
(back, fore, codepoint, blink)
let glyph = (num & 255) as u8;
(blink, back, fore, glyph)
}
pub fn render(canvas: &mut WindowCanvas, color: Color, texture: &Texture) {
canvas.set_draw_color(color);
pub fn as_texture_index(&self) -> usize {
let num = ScreenBlock::attrs_to_index(
self.blink,
self.background,
self.foreground,
self.glyph
);
num
}
pub fn from_texture_index(num: usize) -> Self {
let (blink, background, foreground, glyph) = ScreenBlock::index_to_attrs(num);
ScreenBlock { blink, background, foreground, glyph }
}
}
pub fn block_to_canvas(
canvas: &mut WindowCanvas,
textures: &Vec<Texture>,
x: u8,
y: u8,
block: &ScreenBlock) {
let tex_idx = block.as_texture_index();
let dest_x = match x {
n if (0..=GLYPH_COLUMNS - 1).contains(&n) => GLYPH_WIDTH as i32 * x as i32,
//0..=79 => GLYPH_WIDTH as i32 * x as i32,
_ => panic!("x is out of range! Must be 0..79 inclusive."),
};
let dest_y = match y {
n if (0..=GLYPH_ROWS - 1).contains(&n) => GLYPH_HEIGHT as i32 * y as i32,
//0..=24 => GLYPH_HEIGHT as i32 * y as i32,
_ => panic!("y is out of range! Must be 0..24 inclusive."),
};
match canvas.copy(
&textures[tex_idx],
Rect::new(0, 0, u32::from(GLYPH_WIDTH), u32::from(GLYPH_HEIGHT)),
Rect::new(dest_x, dest_y, u32::from(GLYPH_WIDTH), u32::from(GLYPH_HEIGHT)),
) {
Ok(()) => (),
Err(err) => panic!("Unable to copy texture to canvas! SDL Error: {}", err),
};
}
pub fn render(canvas: &mut WindowCanvas, textures: &Vec<Texture>, screen: &[ScreenBlock]) {
canvas.set_draw_color(EgaColors::from_enum(EgaColors::Black));
canvas.clear();
match canvas.copy(texture, Rect::new(0, 0, 8, 14), Rect::new(0, 0, 8, 14)) {
Ok(()) => (),
Err(err) => panic!("Unable to copy texture to canvas! SDL Error: {}", err),
};
match canvas.copy(texture, Rect::new(0, 0, 8, 14), Rect::new(8, 0, 8, 14)) {
Ok(()) => (),
Err(err) => panic!("Unable to copy texture to canvas! SDL Error: {}", err),
};
match canvas.copy(texture, Rect::new(0, 0, 8, 14), Rect::new(16, 0, 8, 14)) {
Ok(()) => (),
Err(err) => panic!("Unable to copy texture to canvas! SDL Error: {}", err),
};
for (idx, block) in screen.iter().enumerate() {
let x = (idx % GLYPH_COLUMNS as usize) as u8;
let y = (idx / GLYPH_COLUMNS as usize) as u8;
block_to_canvas(canvas, &textures, x, y, block);
}
canvas.present();
}
@ -100,9 +231,9 @@ pub fn main() {
let texture_creator = canvas.texture_creator();
let mut glyph_textures: Vec<Texture> = Vec::new();
for tex_idx in 0..=32767 {
let (back, fore, cp, _) = int_to_textattr(tex_idx);
let mut texture = match texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, 8, 14) {
for tex_idx in 0..TOTAL_GLYPH_TEXTURES {
let (_, back, fore, cp) = ScreenBlock::index_to_attrs(tex_idx);
let mut texture = match texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, u32::from(GLYPH_WIDTH), u32::from(GLYPH_HEIGHT)) {
Ok(texture) => texture,
Err(err) => panic!("SDL could not create texture. SDL Error: {}", err),
};
@ -112,13 +243,13 @@ pub fn main() {
for (x, pixel) in bits.iter().enumerate() {
let offset = y * pitch + x * 3;
if pixel == false {
buffer[offset] = EGA_COLORS[back as usize].r;
buffer[offset + 1] = EGA_COLORS[back as usize].g;
buffer[offset + 2] = EGA_COLORS[back as usize].b;
buffer[offset] = EgaColors::from_u8(back).r;
buffer[offset + 1] = EgaColors::from_u8(back).g;
buffer[offset + 2] = EgaColors::from_u8(back).b;
} else {
buffer[offset] = EGA_COLORS[fore as usize].r;
buffer[offset + 1] = EGA_COLORS[fore as usize].g;
buffer[offset + 2] = EGA_COLORS[fore as usize].b;
buffer[offset] = EgaColors::from_u8(fore).r;
buffer[offset + 1] = EgaColors::from_u8(fore).g;
buffer[offset + 2] = EgaColors::from_u8(fore).b;
}
}
}
@ -129,12 +260,28 @@ pub fn main() {
glyph_textures.push(texture);
}
render(&mut canvas, Color::RGB(0, 0, 0), &glyph_textures[3762]);
let mut dos_screen: [ScreenBlock; TOTAL_SCREEN_BLOCKS] = [ScreenBlock::new(false, EgaColors::as_u8(EgaColors::Black), EgaColors::as_u8(EgaColors::Black), 0); TOTAL_SCREEN_BLOCKS];
for col in 0..60 {
dos_screen[col as usize] = ScreenBlock::new(false, EgaColors::as_u8(EgaColors::Black), EgaColors::as_u8(EgaColors::BrightYellow), 178);
}
for row in 1..GLYPH_ROWS-1 {
let idx = row as usize * GLYPH_COLUMNS as usize;
dos_screen[idx] = ScreenBlock::new(false, EgaColors::as_u8(EgaColors::Black), EgaColors::as_u8(EgaColors::BrightYellow), 178);
dos_screen[idx + 59] = ScreenBlock::new(false, EgaColors::as_u8(EgaColors::Black), EgaColors::as_u8(EgaColors::BrightYellow), 178);
}
for col in 0..60 {
let idx = (GLYPH_ROWS - 1) as usize * GLYPH_COLUMNS as usize + col as usize;
dos_screen[idx] = ScreenBlock::new(false, EgaColors::as_u8(EgaColors::Black), EgaColors::as_u8(EgaColors::BrightYellow), 178);
}
render(&mut canvas, &glyph_textures, &dos_screen);
let mut event_pump = match sdl_context.event_pump() {
Ok(event_pump) => event_pump,
Err(err) => panic!("Could not obtain SDL2 Event Pump! SDL_Error: {}", err),
};
'running: loop {
for event in event_pump.poll_iter() {
match event {
@ -146,7 +293,7 @@ pub fn main() {
}
}
render(&mut canvas, Color::RGB(0, 0, 0), &glyph_textures[3762]);
render(&mut canvas, &glyph_textures, &dos_screen);
sleep(Duration::new(0, 1_000_000_000u32 / 60));
}
}