Created screen array
This commit is contained in:
parent
45dcd8b0f6
commit
428079cf6b
1 changed files with 206 additions and 59 deletions
255
src/main.rs
255
src/main.rs
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue