emu_driver/
lib.rs

1use log::error;
2use pixels::{Error, Pixels, SurfaceTexture};
3use winit::dpi::LogicalSize;
4use winit::event::{Event, VirtualKeyCode};
5use winit::event_loop::{ControlFlow, EventLoop};
6use winit::window::WindowBuilder;
7use winit_input_helper::WinitInputHelper;
8// use std::time::Duration;
9
10/// Stores state for a black and white window
11pub struct StateBW {
12    pub active: Vec<bool>,//[bool; width as usize*HEIGHT as usize],
13    width: u32,
14    height: u32,
15}
16impl StateBW {
17    fn new(width: u32, height: u32) -> StateBW {
18        StateBW{ active: vec![true; width as usize*height as usize], width: width, height: height}
19    }
20    /// Draws all pixels stored in `active` to the screen
21    fn draw(&self, frame: &mut [u8]) {
22        for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
23            let rgba = if self.active[i] {
24                [0xFF, 0xFF, 0xFF, 0xFF]
25            } else {
26                [0x00, 0x00, 0x00, 0x00]
27            };
28            pixel.copy_from_slice(&rgba);
29        }
30    }
31    /// Returns the value at the given position
32    pub fn get(&self, x: u32, y: u32) -> bool {
33        self.active[ (y*self.width + x) as usize ]
34    }
35    /// Sets the value at the given position to the new value
36    pub fn set(&mut self, x: u32, y: u32, new: bool) {
37        self.active[ (y*self.width + x) as usize ] = new;
38    }
39    /// Flips the bit at the given position
40    pub fn switch(&mut self, x: u32, y: u32) {
41        self.active[ (y*self.width + x) as usize ] = !self.get(x, y);
42    }
43}
44
45pub struct WinBW {
46    width: u32,
47    height: u32,
48}
49
50impl WinBW {
51    pub fn new(width: u32, height: u32) -> WinBW {
52        WinBW{width: width, height: height}
53    }
54    /// Runs the main loop
55    /// # Arguments
56    /// * `looper` - A reference to the function called at each loop
57    /// * `state_manager - The struct instance that holds state data
58    /// * `fps` - The FPS cap for the window
59    pub fn run<T>(&mut self, looper: &'static (dyn for<'r, 's> Fn(&'r mut StateBW, &'s mut T) + 'static), mut state_manager: T , fps: u64) -> Result<(), Error>  {
60        env_logger::init();
61        let event_loop = EventLoop::new();
62        let mut input = WinitInputHelper::new();
63        let window = {
64            let size = LogicalSize::new(self.width as f64, self.height as f64);
65            WindowBuilder::new()
66                .with_title("Emulator")
67                .with_inner_size(size)
68                .with_min_inner_size(size)
69                .build(&event_loop)
70                .unwrap()
71        };
72
73        let mut pixels = {
74            let window_size = window.inner_size();
75            let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
76            Pixels::new(self.width, self.height, surface_texture)?
77        };
78
79        let mut world = StateBW::new(self.width, self.height);
80
81        // let sleeper = Duration::from_secs(1/fps);
82
83        event_loop.run(move |event, _, control_flow| {
84
85            // thread::sleep(sleeper);
86
87            // Draw current frame
88            if let Event::RedrawRequested(_) = event {
89                world.draw(pixels.get_frame());
90                if pixels
91                    .render()
92                    .map_err(|e| error!("pixels.render() failed: {}", e))
93                    .is_err()
94                {
95                    *control_flow = ControlFlow::Exit;
96                    return;
97                }
98            }
99
100            // Handle input events
101            if input.update(&event) {
102
103                if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
104                    *control_flow = ControlFlow::Exit;
105                    return;
106                }
107
108                if let Some(size) = input.window_resized() {
109                    pixels.resize_surface(size.width, size.height);
110                }
111
112                looper(&mut world, &mut state_manager);
113                window.request_redraw();
114
115            }
116
117        });
118    }
119}