1use crate::config::{CommonConfig, SnesConfig}; 2 3use crate::mainloop::{CreatedEmulator, NativeDebugFn, create}; 4use crate::{NativeEmulator, NativeEmulatorResult, extensions}; 5 6use crate::mainloop::create::{CreatableEmulator, ReadInputResult}; 7use jgenesis_common::frontend::SaveWriter; 8use jgenesis_native_config::common::WindowSize; 9use jgenesis_native_config::input::mappings::{ButtonMappingVec, SnesControllerType}; 10use snes_config::SnesJoypadState; 11use snes_core::api::SnesEmulator; 12use snes_core::input::{SnesController, SnesInputs, SnesMouseState, SuperScopeState}; 13 14trait SnesControllerTypeExt { 15 fn to_controller(self) -> SnesController; 16} 17 18impl SnesControllerTypeExt for SnesControllerType { 19 fn to_controller(self) -> SnesController { 20 match self { 21 Self::Gamepad => SnesController::Gamepad(SnesJoypadState::default()), 22 Self::Mouse => SnesController::Mouse(SnesMouseState::default()), 23 Self::SuperScope => SnesController::SuperScope(SuperScopeState::default()), 24 Self::None => SnesController::None, 25 } 26 } 27} 28 29trait SnesControllerExt { 30 fn to_type(self) -> SnesControllerType; 31} 32 33impl SnesControllerExt for SnesController { 34 fn to_type(self) -> SnesControllerType { 35 match self { 36 Self::Gamepad(_) => SnesControllerType::Gamepad, 37 Self::Mouse(_) => SnesControllerType::Mouse, 38 Self::SuperScope(_) => SnesControllerType::SuperScope, 39 Self::None => SnesControllerType::None, 40 } 41 } 42} 43 44pub type NativeSnesEmulator = NativeEmulator<SnesEmulator>; 45 46impl CreatableEmulator for SnesEmulator { 47 type NativeConfig = SnesConfig; 48 type CreateInput = Vec<u8>; 49 50 fn read_create_input( 51 config: &Self::NativeConfig, 52 ) -> NativeEmulatorResult<ReadInputResult<Self::CreateInput>> { 53 create::read_rom_file(&config.common.rom_file_path, extensions::SNES) 54 } 55 56 fn create( 57 input: ReadInputResult<Self::CreateInput>, 58 config: &Self::NativeConfig, 59 save_writer: &mut impl SaveWriter, 60 ) -> NativeEmulatorResult<CreatedEmulator<Self>> { 61 let coprocessor_roms = config.to_coprocessor_roms(); 62 let mut emulator = SnesEmulator::create( 63 input.input, 64 config.emulator_config, 65 coprocessor_roms, 66 save_writer, 67 )?; 68 69 let cartridge_title = emulator.cartridge_title(); 70 let window_title = format!("snes - {cartridge_title}"); 71 72 let default_window_size = WindowSize::new_snes( 73 config.common.initial_window_size, 74 config.emulator_config.aspect_ratio, 75 ); 76 77 Ok(CreatedEmulator { emulator, window_title, default_window_size }) 78 } 79 80 fn common_config(config: &Self::NativeConfig) -> &CommonConfig { 81 &config.common 82 } 83 84 fn emulator_config(config: &Self::NativeConfig) -> &Self::Config { 85 &config.emulator_config 86 } 87 88 fn reload_native_config( 89 emulator: &mut NativeEmulator<Self>, 90 config: &Self::NativeConfig, 91 ) -> NativeEmulatorResult<()> { 92 for (inputs, controller_type) in [ 93 (&mut emulator.inputs.p1, config.inputs.p1_type), 94 (&mut emulator.inputs.p2, config.inputs.p2_type), 95 ] { 96 if inputs.to_type() != controller_type { 97 *inputs = controller_type.to_controller(); 98 } 99 } 100 101 Ok(()) 102 } 103 104 fn initial_inputs(config: &Self::NativeConfig) -> Self::Inputs { 105 SnesInputs { 106 p1: config.inputs.p1_type.to_controller(), 107 p2: config.inputs.p2_type.to_controller(), 108 } 109 } 110 111 fn input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 112 config.inputs.to_mapping_vec() 113 } 114 115 fn turbo_input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 116 config.inputs.to_turbo_mapping_vec() 117 } 118 119 fn debug_fn() -> Option<NativeDebugFn<Self>> { 120 Some(|| { 121 jgenesis_debugger_frontend::partial_clone_debug_fn( 122 jgenesis_debugger_frontend::snes::render_fn(), 123 ) 124 }) 125 } 126}