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_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;
|
||||||
|
|
||||||
|
// 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
|
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 blink = (num >> 15) != 0;
|
||||||
let back = (num >> 12) as u8;
|
let back = (num >> 12) as u8;
|
||||||
let fore = ((num >> 8) & 15) as u8;
|
let fore = ((num >> 8) & 15) as u8;
|
||||||
let codepoint = (num & 255) as u8;
|
let glyph = (num & 255) as u8;
|
||||||
(back, fore, codepoint, blink)
|
(blink, back, fore, glyph)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(canvas: &mut WindowCanvas, color: Color, texture: &Texture) {
|
pub fn as_texture_index(&self) -> usize {
|
||||||
canvas.set_draw_color(color);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue