1use crate::config::{CommonConfig, NesConfig}; 2 3use crate::mainloop::{CreatedEmulator, NativeDebugFn, create, file_name_no_ext}; 4use crate::{NativeEmulator, NativeEmulatorResult, extensions}; 5 6use nes_core::api::NesEmulator; 7use nes_core::input::{NesInputDevice, NesInputs, ZapperState}; 8 9use crate::mainloop::create::{CreatableEmulator, ReadInputResult}; 10use jgenesis_common::frontend::SaveWriter; 11use jgenesis_native_config::common::WindowSize; 12use jgenesis_native_config::input::mappings::{ButtonMappingVec, NesControllerType}; 13use nes_config::NesJoypadState; 14 15trait NesControllerTypeExt { 16 fn to_input_device(self) -> NesInputDevice; 17} 18 19impl NesControllerTypeExt for NesControllerType { 20 fn to_input_device(self) -> NesInputDevice { 21 match self { 22 Self::Gamepad => NesInputDevice::Controller(NesJoypadState::default()), 23 Self::Zapper => NesInputDevice::Zapper(ZapperState::default()), 24 } 25 } 26} 27 28pub type NativeNesEmulator = NativeEmulator<NesEmulator>; 29 30impl CreatableEmulator for NesEmulator { 31 type NativeConfig = NesConfig; 32 type CreateInput = Vec<u8>; 33 34 fn read_create_input( 35 config: &Self::NativeConfig, 36 ) -> NativeEmulatorResult<ReadInputResult<Self::CreateInput>> { 37 create::read_rom_file(&config.common.rom_file_path, extensions::NES) 38 } 39 40 fn create( 41 input: ReadInputResult<Self::CreateInput>, 42 config: &Self::NativeConfig, 43 save_writer: &mut impl SaveWriter, 44 ) -> NativeEmulatorResult<CreatedEmulator<Self>> { 45 let emulator = NesEmulator::create(input.input, config.emulator_config, save_writer)?; 46 47 let rom_title = file_name_no_ext(&input.rom_path)?; 48 let window_title = format!("nes - {rom_title}"); 49 50 let default_window_size = WindowSize::new_nes( 51 config.common.initial_window_size, 52 config.emulator_config.aspect_ratio, 53 emulator.timing_mode(), 54 config.emulator_config.ntsc_crop_vertical_overscan, 55 ); 56 57 Ok(CreatedEmulator { emulator, window_title, default_window_size }) 58 } 59 60 fn common_config(config: &Self::NativeConfig) -> &CommonConfig { 61 &config.common 62 } 63 64 fn emulator_config(config: &Self::NativeConfig) -> &Self::Config { 65 &config.emulator_config 66 } 67 68 fn reload_native_config( 69 emulator: &mut NativeEmulator<Self>, 70 config: &Self::NativeConfig, 71 ) -> NativeEmulatorResult<()> { 72 emulator.inputs.p2 = config.inputs.p2_type.to_input_device(); 73 74 Ok(()) 75 } 76 77 fn initial_inputs(config: &Self::NativeConfig) -> Self::Inputs { 78 NesInputs { p1: NesJoypadState::default(), p2: config.inputs.p2_type.to_input_device() } 79 } 80 81 fn input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 82 config.inputs.to_mapping_vec() 83 } 84 85 fn turbo_input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 86 config.inputs.to_turbo_mapping_vec() 87 } 88 89 fn debug_fn() -> Option<NativeDebugFn<Self>> { 90 Some(|| { 91 jgenesis_debugger_frontend::partial_clone_debug_fn( 92 jgenesis_debugger_frontend::nes::render_fn(), 93 ) 94 }) 95 } 96}