george-emu/src/video.rs

142 lines
4.5 KiB
Rust

use crate::{memory, Mem};
use minifb::{Window, WindowOptions};
use std::{
char,
fs::File,
io::Read,
process::exit,
sync::{Arc, RwLock, RwLockReadGuard},
thread::sleep,
time::{Duration, Instant},
};
const FG_COLOR: u32 = 0xFFCC00;
//const BG_COLOR: u32 = 0x110500;
const BG_COLOR: u32 = 0x22BB00;
pub struct Crtc {
memory: Arc<RwLock<Mem>>,
buffer: Vec<u32>,
window: minifb::Window,
char_rom: Vec<u8>,
}
pub fn get_char_bin(path: &str) -> Vec<u8> {
let mut file = File::open(path).unwrap();
let mut buffer = vec![0; 0xFFFF];
file.read_exact(&mut buffer).unwrap();
buffer
}
impl Crtc {
pub fn new(memory: Arc<RwLock<Mem>>) -> Self {
let window = Window::new("screen", 512, 380, WindowOptions::default()).unwrap();
let char_rom = get_char_bin("./src/cozette.bin");
Self {
memory,
buffer: vec![0; 512 * 380],
window,
char_rom,
}
}
fn draw(&mut self) {
match &mut self.memory.clone().try_read() {
Ok(memory) => {
let hw_ctrl = memory.read(0x4000).unwrap();
match hw_ctrl & 0b0000_1000 == 0b0000_1000 {
false => self.draw_chars(),
true => self.draw_hires(),
};
}
Err(_) => {
println!("Couldn't acquire read on shared memory in main thread");
return;
}
};
self.window
.update_with_buffer(&self.buffer, 512, 380)
.unwrap();
}
fn draw_chars(&mut self) {
let memory = match self.memory.try_read() {
Ok(read) => read,
Err(_) => {
println!("Couldn't acquire read on shared memory in main thread");
return;
}
};
for char_col in 0..65 {
let pixel_col = char_col * 8;
for char_row in 0..30 {
let pixel_row = char_row * 13;
for row in 0..13 {
for i in 0..8 {
let address: usize = ((pixel_col * pixel_row + row * 13) + i) * 8;
self.buffer[address] = BG_COLOR;
}
}
}
}
//for char_col in 0..64 {
// for char_row in 0..29 {
// let ascii = memory.read(0x6000 + char_row * char_col).unwrap();
// for row in 0..13 {
// for char in 0..=255 {
// if ascii == char {
// let byte = self.char_rom[char as usize + (row * 0xFF)];
// for i in 0..8 {
// let address: usize = ((char_col as usize * 64 + (8 * i))
// + (char_row as usize + (13 * row) * 29))
// * 8
// + i;
// if (byte >> i) & 0b1 == 1 {
// self.buffer[address] = FG_COLOR;
// } else {
// self.buffer[address] = BG_COLOR;
// }
// }
// }
// }
// }
// }
//}
println!("{:?}", self.buffer);
//exit(0);
}
fn draw_hires(&mut self) {
let memory = match self.memory.try_read() {
Ok(read) => read,
Err(_) => {
println!("Couldn't acquire read on shared memory in main thread");
return;
}
};
for addr in 0x6000..0xBF00 {
// TODO: eventually this will access memory in the weird interleaved way the hardware is
// designed, but this is easiest to implement for now
let byte = memory.read(addr).unwrap();
for i in 0..8 {
match byte & 0x80 >> i == 0 {
true => self.buffer[(addr - 0x6000) as usize * 8 + i] = BG_COLOR,
false => self.buffer[(addr - 0x6000) as usize * 8 + i] = FG_COLOR,
}
}
}
}
pub fn run(&mut self) {
let frame_duration = Duration::from_millis(16);
let mut previous_draw = Instant::now();
loop {
let now = Instant::now();
if now - previous_draw > frame_duration {
self.draw();
previous_draw = now;
}
sleep(Duration::from_millis(1));
}
}
}