Files
porcel8/src/main.rs

162 lines
5.0 KiB
Rust
Raw Normal View History

2024-03-03 11:48:07 +05:30
use std::fs::File;
use std::io::Read;
2024-03-03 12:53:33 +05:30
use std::sync::{Arc, Mutex, MutexGuard};
2024-03-03 11:48:07 +05:30
use std::thread;
use std::time::Duration;
2024-02-29 11:55:14 +05:30
use log::LevelFilter;
2024-03-03 11:48:07 +05:30
use sdl2::audio::{AudioQueue, AudioSpecDesired};
use sdl2::event::Event;
use sdl2::EventPump;
use sdl2::keyboard::Keycode;
2024-03-03 12:53:33 +05:30
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::render::{BlendMode, TextureAccess, WindowCanvas};
2024-02-29 11:55:14 +05:30
use simple_logger::SimpleLogger;
use device::timer::Timer;
use crate::device::Device;
2024-03-03 11:48:07 +05:30
use crate::kb_map::get_key_index;
2024-02-29 11:55:14 +05:30
mod args;
mod device;
2024-03-03 11:48:07 +05:30
mod kb_map;
2024-02-29 11:55:14 +05:30
fn main() {
SimpleLogger::new().with_level(LevelFilter::Info).env().init().unwrap();
log::info!("Started emulator");
let mut timer = Timer::new();
timer.start();
2024-03-03 11:48:07 +05:30
let frame_buffer = get_frame_buffer();
let frame_buffer_for_display = Arc::clone(&frame_buffer);
2024-03-03 11:48:07 +05:30
let (sender,receiver) = std::sync::mpsc::channel();
let compute_handle = thread::spawn(move ||{
let mut device = Device::new(timer, frame_buffer);
device.set_default_font();
{
let rom = load_rom();
device.load_rom(&rom);
}
loop {
let val = receiver.try_recv();
if let Ok(()) = val{
break;
}else if let Err(std::sync::mpsc::TryRecvError::Disconnected) = val{
panic!("Disconnected");
}
device.cycle();
}
});
2024-03-03 12:53:33 +05:30
let (mut canvas, mut event_pump) = initiate_sdl(8f32);
let mut fb_sdl = vec![0;3*Device::FRAME_BUFFER_SIZE];
2024-03-03 11:48:07 +05:30
canvas.set_draw_color(Color::BLACK);
canvas.clear();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit { .. } |
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
sender.send(()).expect("Could not send");
break 'running;
}
Event::KeyDown { keycode: Some(x), repeat: false, .. } => {
if let Some(key_val) = get_key_index(x) {
log::info!("Key+ {}",key_val)
}
}
Event::KeyUp { keycode: Some(x), repeat: false, .. } => {
if let Some(key_val) = get_key_index(x) {
log::info!("Key- {}",key_val)
}
}
_ => {}
}
}
// The rest of the game loop goes here...
{
let lock = frame_buffer_for_display.lock().expect("Failed to get Display");
2024-03-03 12:53:33 +05:30
draw_screen(lock,&mut canvas,&mut fb_sdl);
// log::info!("Framebuffer status: {:?}",lock);
2024-03-03 11:48:07 +05:30
}
canvas.present();
// 60fps - small offset to consider for cpu cycle time
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60 - 2000_000));
}
compute_handle.join().unwrap();
}
2024-03-03 12:53:33 +05:30
fn draw_screen(frame_buffer: MutexGuard<Box<[u8; 2048]>>, window_canvas: &mut WindowCanvas, x1: &mut Vec<u8>) {
for (i,pixel) in frame_buffer.iter().enumerate(){
x1[3*i] = *pixel;
x1[3*i+1] = *pixel;
x1[3*i+2] = *pixel;
}
drop(frame_buffer);
let tex_creator = window_canvas.texture_creator();
let mut tex = tex_creator.create_texture(PixelFormatEnum::RGB24, TextureAccess::Streaming, Device::FRAME_BUFFER_WIDTH as u32, Device::FRAME_BUFFER_HEIGHT as u32).expect("Failed to create tex");
tex.with_lock(None,|u,i|{
u.copy_from_slice(x1);
}).expect("Unwrap tex");
window_canvas.copy(&tex,None,None);
}
2024-03-03 11:48:07 +05:30
fn get_frame_buffer() -> Arc<Mutex<Box<[u8; 2048]>>> {
Arc::new(Mutex::new(vec![0u8; Device::FRAME_BUFFER_SIZE].into_boxed_slice().try_into().unwrap()))
}
const ROM_SIZE:usize = 4096 - 0x200;
fn load_rom()->[u8;ROM_SIZE]{
let mut rom_slice = [0u8;ROM_SIZE];
let mut file = File::open("roms/ibm_logo.ch8").expect("could not open");
file.read(&mut rom_slice).expect("Unwrap");
rom_slice
}
fn initiate_sdl(draw_scale:f32) -> (WindowCanvas, EventPump) {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
// let audio_subsystem = sdl_context.audio().unwrap();
// let wanted_spec = AudioSpecDesired {
// channels: Some(1),
// samples: Some(256),
// freq: Some(15360),
// };
// let audio_queue = audio_subsystem.open_queue::<u8, _>(None, &wanted_spec).unwrap();
// audio_queue.resume();
let window_width = (Device::FRAME_BUFFER_WIDTH as f32 * draw_scale) as u32;
let window_height = (Device::FRAME_BUFFER_HEIGHT as f32 * draw_scale) as u32;
let window = video_subsystem.window("byte-pusher-emu", window_width,window_height)
.position_centered()
.build()
.unwrap();
let mut canvas = window.into_canvas().build().unwrap();
canvas.set_scale(draw_scale, draw_scale).expect("Setting scale");
canvas.set_blend_mode(BlendMode::None);
canvas.clear();
canvas.present();
let event_pump = sdl_context.event_pump().unwrap();
(canvas, event_pump
// , audio_queue
)
2024-02-29 11:55:14 +05:30
}