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>, buffer: Vec, window: minifb::Window, char_rom: Vec, } pub fn get_char_bin(path: &str) -> Vec { 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>) -> 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)); } } }