137 lines
4.5 KiB
Rust
137 lines
4.5 KiB
Rust
#![feature(likely_unlikely, widening_mul)]
|
|
#![deny(clippy::all)]
|
|
|
|
use std::env::args;
|
|
use std::process::exit;
|
|
use std::sync::atomic::AtomicU32;
|
|
use std::sync::{Arc, Mutex};
|
|
use std::thread::{scope, sleep};
|
|
use std::time::Duration;
|
|
|
|
use pixels::{Error, Pixels, SurfaceTexture};
|
|
use winit::dpi::LogicalSize;
|
|
use winit::event::{Event, WindowEvent};
|
|
use winit::event_loop::EventLoop;
|
|
use winit::platform::scancode::PhysicalKeyExtScancode;
|
|
use winit::window::Window;
|
|
use winit_input_helper::WinitInputHelper;
|
|
|
|
use crate::cpu::Computer;
|
|
|
|
const WIDTH: u32 = 640;
|
|
const HEIGHT: u32 = 480;
|
|
|
|
mod cpu;
|
|
|
|
fn main() -> Result<(), Error> {
|
|
let event_loop = EventLoop::new().unwrap();
|
|
let mut input = WinitInputHelper::new();
|
|
let window = {
|
|
let size = LogicalSize::new((WIDTH * 3) as f64, (HEIGHT * 3) as f64);
|
|
#[allow(deprecated)]
|
|
Arc::new(
|
|
event_loop
|
|
.create_window(
|
|
Window::default_attributes()
|
|
.with_title("bisare screen")
|
|
.with_inner_size(size)
|
|
.with_min_inner_size(size),
|
|
)
|
|
.unwrap(),
|
|
)
|
|
};
|
|
|
|
let pixels = Mutex::new({
|
|
let window_size = window.inner_size();
|
|
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
|
Pixels::new(WIDTH, HEIGHT, surface_texture)?
|
|
});
|
|
|
|
let keyboard = AtomicU32::new(0);
|
|
let program = args()
|
|
.nth(1)
|
|
.expect("you must supply the exec name as the first argument");
|
|
let kbref = &keyboard;
|
|
let pixelref = &pixels;
|
|
scope(|sc| {
|
|
sc.spawn(|| {
|
|
let mut simulation = Computer::new(program, pixelref, kbref);
|
|
loop {
|
|
simulation.step();
|
|
}
|
|
});
|
|
|
|
#[allow(deprecated)]
|
|
let res = event_loop.run(|event, elwt| {
|
|
match event {
|
|
Event::Resumed => {}
|
|
Event::NewEvents(_) => input.step(),
|
|
Event::AboutToWait => input.end_step(),
|
|
Event::DeviceEvent { event, .. } => {
|
|
input.process_device_event(&event);
|
|
}
|
|
Event::WindowEvent { event, .. } => {
|
|
// Draw the current frame
|
|
if event == WindowEvent::RedrawRequested {
|
|
if let Err(_) = pixels.lock().unwrap().render() {
|
|
elwt.exit();
|
|
return;
|
|
}
|
|
sleep(Duration::from_millis(30));
|
|
}
|
|
|
|
if let WindowEvent::KeyboardInput {
|
|
device_id: _,
|
|
ref event,
|
|
is_synthetic: _,
|
|
} = event
|
|
{
|
|
match event.state {
|
|
winit::event::ElementState::Pressed => {
|
|
if let Some(val) = event.physical_key.to_scancode() {
|
|
kbref.store(val + 8, std::sync::atomic::Ordering::Relaxed);
|
|
}
|
|
}
|
|
winit::event::ElementState::Released => {
|
|
kbref.store(0, std::sync::atomic::Ordering::Relaxed)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle input events
|
|
if input.process_window_event(&event) {
|
|
// Close events
|
|
if input.close_requested() {
|
|
elwt.exit();
|
|
return;
|
|
}
|
|
|
|
// Resize the window
|
|
if let Some(size) = input.window_resized() {
|
|
if let Err(_) = pixels
|
|
.lock()
|
|
.unwrap()
|
|
.resize_surface(size.width, size.height)
|
|
{
|
|
elwt.exit();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Update internal state and request a redraw
|
|
window.request_redraw();
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
});
|
|
match res {
|
|
Ok(_) => exit(0),
|
|
Err(e) => {
|
|
println!("{e}");
|
|
exit(1);
|
|
}
|
|
}
|
|
})
|
|
}
|