rewrite it in rust #1
			
				
			
		
		
		
	| 
						 | 
					@ -1957,6 +1957,7 @@ name = "shrooms-vb-native"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "anyhow",
 | 
					 "anyhow",
 | 
				
			||||||
 | 
					 "bitflags 2.6.0",
 | 
				
			||||||
 "bytemuck",
 | 
					 "bytemuck",
 | 
				
			||||||
 "cc",
 | 
					 "cc",
 | 
				
			||||||
 "clap",
 | 
					 "clap",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
anyhow = "1"
 | 
					anyhow = "1"
 | 
				
			||||||
 | 
					bitflags = "2"
 | 
				
			||||||
bytemuck = { version = "1", features = ["derive"] }
 | 
					bytemuck = { version = "1", features = ["derive"] }
 | 
				
			||||||
clap = { version = "4", features = ["derive"] }
 | 
					clap = { version = "4", features = ["derive"] }
 | 
				
			||||||
cpal = "0.15"
 | 
					cpal = "0.15"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/app.rs
								
								
								
								
							
							
						
						
									
										20
									
								
								src/app.rs
								
								
								
								
							| 
						 | 
					@ -9,13 +9,13 @@ use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _
 | 
				
			||||||
use winit::{
 | 
					use winit::{
 | 
				
			||||||
    application::ApplicationHandler,
 | 
					    application::ApplicationHandler,
 | 
				
			||||||
    dpi::{LogicalSize, PhysicalSize},
 | 
					    dpi::{LogicalSize, PhysicalSize},
 | 
				
			||||||
    event::{ElementState, Event, WindowEvent},
 | 
					    event::{Event, WindowEvent},
 | 
				
			||||||
    event_loop::ActiveEventLoop,
 | 
					    event_loop::ActiveEventLoop,
 | 
				
			||||||
    keyboard::Key,
 | 
					 | 
				
			||||||
    window::Window,
 | 
					    window::Window,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
 | 
					    controller::ControllerState,
 | 
				
			||||||
    emulator::{EmulatorClient, EmulatorCommand},
 | 
					    emulator::{EmulatorClient, EmulatorCommand},
 | 
				
			||||||
    renderer::GameRenderer,
 | 
					    renderer::GameRenderer,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -270,13 +270,17 @@ impl AppWindow {
 | 
				
			||||||
pub struct App {
 | 
					pub struct App {
 | 
				
			||||||
    window: Option<AppWindow>,
 | 
					    window: Option<AppWindow>,
 | 
				
			||||||
    client: EmulatorClient,
 | 
					    client: EmulatorClient,
 | 
				
			||||||
 | 
					    controller: ControllerState,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl App {
 | 
					impl App {
 | 
				
			||||||
    pub fn new(client: EmulatorClient) -> Self {
 | 
					    pub fn new(client: EmulatorClient) -> Self {
 | 
				
			||||||
 | 
					        let controller = ControllerState::new();
 | 
				
			||||||
 | 
					        client.send_command(EmulatorCommand::SetKeys(controller.pressed()));
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            window: None,
 | 
					            window: None,
 | 
				
			||||||
            client,
 | 
					            client,
 | 
				
			||||||
 | 
					            controller,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -305,15 +309,9 @@ impl ApplicationHandler for App {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            WindowEvent::CloseRequested => event_loop.exit(),
 | 
					            WindowEvent::CloseRequested => event_loop.exit(),
 | 
				
			||||||
            WindowEvent::KeyboardInput { event, .. } => {
 | 
					            WindowEvent::KeyboardInput { event, .. } => {
 | 
				
			||||||
                if let Key::Character("s") = event.logical_key.as_ref() {
 | 
					                if self.controller.key_event(event) {
 | 
				
			||||||
                    match event.state {
 | 
					                    self.client
 | 
				
			||||||
                        ElementState::Pressed => {
 | 
					                        .send_command(EmulatorCommand::SetKeys(self.controller.pressed()));
 | 
				
			||||||
                            self.client.send_command(EmulatorCommand::PressStart)
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        ElementState::Released => {
 | 
					 | 
				
			||||||
                            self.client.send_command(EmulatorCommand::ReleaseStart)
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            WindowEvent::RedrawRequested => {
 | 
					            WindowEvent::RedrawRequested => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					use winit::{
 | 
				
			||||||
 | 
					    event::{ElementState, KeyEvent},
 | 
				
			||||||
 | 
					    keyboard::{Key, NamedKey},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::shrooms_vb_core::VBKey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct ControllerState {
 | 
				
			||||||
 | 
					    pressed: VBKey,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ControllerState {
 | 
				
			||||||
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            pressed: VBKey::SGN,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn pressed(&self) -> VBKey {
 | 
				
			||||||
 | 
					        self.pressed
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn key_event(&mut self, event: &KeyEvent) -> bool {
 | 
				
			||||||
 | 
					        let Some(input) = self.key_to_input(&event.logical_key) else {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        match event.state {
 | 
				
			||||||
 | 
					            ElementState::Pressed => {
 | 
				
			||||||
 | 
					                if self.pressed.contains(input) {
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                self.pressed.insert(input);
 | 
				
			||||||
 | 
					                true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ElementState::Released => {
 | 
				
			||||||
 | 
					                if !self.pressed.contains(input) {
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                self.pressed.remove(input);
 | 
				
			||||||
 | 
					                true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn key_to_input(&self, key: &Key) -> Option<VBKey> {
 | 
				
			||||||
 | 
					        match key.as_ref() {
 | 
				
			||||||
 | 
					            Key::Character("a") => Some(VBKey::SEL),
 | 
				
			||||||
 | 
					            Key::Character("s") => Some(VBKey::STA),
 | 
				
			||||||
 | 
					            Key::Character("d") => Some(VBKey::B),
 | 
				
			||||||
 | 
					            Key::Character("f") => Some(VBKey::A),
 | 
				
			||||||
 | 
					            Key::Character("e") => Some(VBKey::LT),
 | 
				
			||||||
 | 
					            Key::Character("r") => Some(VBKey::RT),
 | 
				
			||||||
 | 
					            Key::Character("i") => Some(VBKey::RU),
 | 
				
			||||||
 | 
					            Key::Character("j") => Some(VBKey::RL),
 | 
				
			||||||
 | 
					            Key::Character("k") => Some(VBKey::RD),
 | 
				
			||||||
 | 
					            Key::Character("l") => Some(VBKey::RR),
 | 
				
			||||||
 | 
					            Key::Named(NamedKey::ArrowUp) => Some(VBKey::LU),
 | 
				
			||||||
 | 
					            Key::Named(NamedKey::ArrowLeft) => Some(VBKey::LL),
 | 
				
			||||||
 | 
					            Key::Named(NamedKey::ArrowDown) => Some(VBKey::LD),
 | 
				
			||||||
 | 
					            Key::Named(NamedKey::ArrowRight) => Some(VBKey::LR),
 | 
				
			||||||
 | 
					            _ => None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,11 @@ use std::{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use anyhow::Result;
 | 
					use anyhow::Result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{audio::Audio, renderer::GameRenderer, shrooms_vb_core::CoreVB};
 | 
					use crate::{
 | 
				
			||||||
 | 
					    audio::Audio,
 | 
				
			||||||
 | 
					    renderer::GameRenderer,
 | 
				
			||||||
 | 
					    shrooms_vb_core::{CoreVB, VBKey},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct EmulatorBuilder {
 | 
					pub struct EmulatorBuilder {
 | 
				
			||||||
    rom: Option<PathBuf>,
 | 
					    rom: Option<PathBuf>,
 | 
				
			||||||
| 
						 | 
					@ -132,11 +136,8 @@ impl Emulator {
 | 
				
			||||||
                self.sim.reset();
 | 
					                self.sim.reset();
 | 
				
			||||||
                self.running.store(true, Ordering::Release);
 | 
					                self.running.store(true, Ordering::Release);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            EmulatorCommand::PressStart => {
 | 
					            EmulatorCommand::SetKeys(keys) => {
 | 
				
			||||||
                self.sim.set_keys(0x1003);
 | 
					                self.sim.set_keys(keys);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            EmulatorCommand::ReleaseStart => {
 | 
					 | 
				
			||||||
                self.sim.set_keys(0x0003);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -149,8 +150,7 @@ pub enum EmulatorCommand {
 | 
				
			||||||
    Pause,
 | 
					    Pause,
 | 
				
			||||||
    Resume,
 | 
					    Resume,
 | 
				
			||||||
    Reset,
 | 
					    Reset,
 | 
				
			||||||
    PressStart,
 | 
					    SetKeys(VBKey),
 | 
				
			||||||
    ReleaseStart,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct EmulatorClient {
 | 
					pub struct EmulatorClient {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ use winit::event_loop::{ControlFlow, EventLoop};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod app;
 | 
					mod app;
 | 
				
			||||||
mod audio;
 | 
					mod audio;
 | 
				
			||||||
 | 
					mod controller;
 | 
				
			||||||
mod emulator;
 | 
					mod emulator;
 | 
				
			||||||
mod renderer;
 | 
					mod renderer;
 | 
				
			||||||
mod shrooms_vb_core;
 | 
					mod shrooms_vb_core;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
use std::{ffi::c_void, ptr, slice};
 | 
					use std::{ffi::c_void, ptr, slice};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use anyhow::{anyhow, Result};
 | 
					use anyhow::{anyhow, Result};
 | 
				
			||||||
 | 
					use bitflags::bitflags;
 | 
				
			||||||
use num_derive::{FromPrimitive, ToPrimitive};
 | 
					use num_derive::{FromPrimitive, ToPrimitive};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[repr(C)]
 | 
					#[repr(C)]
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,28 @@ enum VBDataType {
 | 
				
			||||||
    F32 = 5,
 | 
					    F32 = 5,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bitflags! {
 | 
				
			||||||
 | 
					    #[derive(Clone, Copy, Debug)]
 | 
				
			||||||
 | 
					    pub struct VBKey: u16 {
 | 
				
			||||||
 | 
					        const PWR = 0x0001;
 | 
				
			||||||
 | 
					        const SGN = 0x0002;
 | 
				
			||||||
 | 
					        const A   = 0x0004;
 | 
				
			||||||
 | 
					        const B   = 0x0008;
 | 
				
			||||||
 | 
					        const RT  = 0x0010;
 | 
				
			||||||
 | 
					        const LT  = 0x0020;
 | 
				
			||||||
 | 
					        const RU  = 0x0040;
 | 
				
			||||||
 | 
					        const RR  = 0x0080;
 | 
				
			||||||
 | 
					        const LR  = 0x0100;
 | 
				
			||||||
 | 
					        const LL  = 0x0200;
 | 
				
			||||||
 | 
					        const LD  = 0x0400;
 | 
				
			||||||
 | 
					        const LU  = 0x0800;
 | 
				
			||||||
 | 
					        const STA = 0x1000;
 | 
				
			||||||
 | 
					        const SEL = 0x2000;
 | 
				
			||||||
 | 
					        const RL  = 0x4000;
 | 
				
			||||||
 | 
					        const RD  = 0x8000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type OnFrame = extern "C" fn(sim: *mut VB) -> c_int;
 | 
					type OnFrame = extern "C" fn(sim: *mut VB) -> c_int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[link(name = "vb")]
 | 
					#[link(name = "vb")]
 | 
				
			||||||
| 
						 | 
					@ -198,8 +221,8 @@ impl CoreVB {
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn set_keys(&mut self, keys: u16) {
 | 
					    pub fn set_keys(&mut self, keys: VBKey) {
 | 
				
			||||||
        unsafe { vb_set_keys(self.sim, keys) };
 | 
					        unsafe { vb_set_keys(self.sim, keys.bits()) };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue