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_HEIGHT: u32 = 350;
const SCREEN_WIDTH: u32 = 640; const SCREEN_WIDTH: u32 = 640;
const EGA_COLORS: [Color; 16] = [ const GLYPH_COLUMNS: u8 = 80;
Color::RGB(0x00, 0x00, 0x00), // Black const GLYPH_ROWS: u8 = 25;
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
];
pub fn textattr_to_int(back: u8, fore: u8, codepoint: u8, blink: bool) -> usize { const GLYPH_HEIGHT: u8 = 14;
let num = (usize::from(blink) << 15) + const GLYPH_WIDTH: u8 = 8;
(usize::from(back) << 12) +
(usize::from(fore) << 8) + // Total glyph textures = 256 glyphs * 16 foreground colors * 8 background colors
usize::from(codepoint); const TOTAL_GLYPH_TEXTURES: usize = 256 * 16 * 8;
num
// 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,
} }
pub fn int_to_textattr(num: usize) -> (u8, u8, u8, bool) { impl EgaColors {
let blink = (num >> 15) != 0; pub fn as_u8(color: EgaColors) -> u8 {
let back = (num >> 12) as u8; let num = match color {
let fore = ((num >> 8) & 15) as u8; EgaColors::Black => 0,
let codepoint = (num & 255) as u8; EgaColors::Blue => 1,
(back, fore, codepoint, blink) 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 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
}
} }
pub fn render(canvas: &mut WindowCanvas, color: Color, texture: &Texture) { #[derive(Clone, Copy)]
canvas.set_draw_color(color); 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 glyph = (num & 255) as u8;
(blink, back, fore, glyph)
}
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(); canvas.clear();
match canvas.copy(texture, Rect::new(0, 0, 8, 14), Rect::new(0, 0, 8, 14)) { for (idx, block) in screen.iter().enumerate() {
Ok(()) => (), let x = (idx % GLYPH_COLUMNS as usize) as u8;
Err(err) => panic!("Unable to copy texture to canvas! SDL Error: {}", err), let y = (idx / GLYPH_COLUMNS as usize) as u8;
}; block_to_canvas(canvas, &textures, x, y, block);
}
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),
};
canvas.present(); canvas.present();
} }
@ -100,9 +231,9 @@ pub fn main() {
let texture_creator = canvas.texture_creator(); let texture_creator = canvas.texture_creator();
let mut glyph_textures: Vec<Texture> = Vec::new(); let mut glyph_textures: Vec<Texture> = Vec::new();
for tex_idx in 0..=32767 { for tex_idx in 0..TOTAL_GLYPH_TEXTURES {
let (back, fore, cp, _) = int_to_textattr(tex_idx); let (_, back, fore, cp) = ScreenBlock::index_to_attrs(tex_idx);
let mut texture = match texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, 8, 14) { let mut texture = match texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, u32::from(GLYPH_WIDTH), u32::from(GLYPH_HEIGHT)) {
Ok(texture) => texture, Ok(texture) => texture,
Err(err) => panic!("SDL could not create texture. SDL Error: {}", err), 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() { for (x, pixel) in bits.iter().enumerate() {
let offset = y * pitch + x * 3; let offset = y * pitch + x * 3;
if pixel == false { if pixel == false {
buffer[offset] = EGA_COLORS[back as usize].r; buffer[offset] = EgaColors::from_u8(back).r;
buffer[offset + 1] = EGA_COLORS[back as usize].g; buffer[offset + 1] = EgaColors::from_u8(back).g;
buffer[offset + 2] = EGA_COLORS[back as usize].b; buffer[offset + 2] = EgaColors::from_u8(back).b;
} else { } else {
buffer[offset] = EGA_COLORS[fore as usize].r; buffer[offset] = EgaColors::from_u8(fore).r;
buffer[offset + 1] = EGA_COLORS[fore as usize].g; buffer[offset + 1] = EgaColors::from_u8(fore).g;
buffer[offset + 2] = EGA_COLORS[fore as usize].b; buffer[offset + 2] = EgaColors::from_u8(fore).b;
} }
} }
} }
@ -129,12 +260,28 @@ pub fn main() {
glyph_textures.push(texture); 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() { let mut event_pump = match sdl_context.event_pump() {
Ok(event_pump) => event_pump, Ok(event_pump) => event_pump,
Err(err) => panic!("Could not obtain SDL2 Event Pump! SDL_Error: {}", err), Err(err) => panic!("Could not obtain SDL2 Event Pump! SDL_Error: {}", err),
}; };
'running: loop { 'running: loop {
for event in event_pump.poll_iter() { for event in event_pump.poll_iter() {
match event { 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)); sleep(Duration::new(0, 1_000_000_000u32 / 60));
} }
} }