1use crate::config::{CommonConfig, GameBoyAdvanceConfig}; 2use crate::mainloop::create::{CreatableEmulator, ReadInputResult}; 3use crate::mainloop::{CreatedEmulator, NativeDebugFn, create, file_name_no_ext}; 4use crate::{NativeEmulator, NativeEmulatorError, NativeEmulatorResult, extensions}; 5use gba_config::{GbaInputs, SolarSensorState}; 6use gba_core::api::GameBoyAdvanceEmulator; 7use jgenesis_common::frontend::SaveWriter; 8use jgenesis_native_config::common::WindowSize; 9use jgenesis_native_config::input::mappings::ButtonMappingVec; 10use std::fs; 11 12pub type NativeGbaEmulator = NativeEmulator<GameBoyAdvanceEmulator>; 13 14impl CreatableEmulator for GameBoyAdvanceEmulator { 15 type NativeConfig = GameBoyAdvanceConfig; 16 type CreateInput = Vec<u8>; 17 18 fn read_create_input( 19 config: &Self::NativeConfig, 20 ) -> NativeEmulatorResult<ReadInputResult<Self::CreateInput>> { 21 create::read_rom_file(&config.common.rom_file_path, extensions::GAME_BOY_ADVANCE) 22 } 23 24 fn create( 25 input: ReadInputResult<Self::CreateInput>, 26 config: &Self::NativeConfig, 27 save_writer: &mut impl SaveWriter, 28 ) -> NativeEmulatorResult<CreatedEmulator<Self>> { 29 let Some(bios_path) = &config.bios_path else { 30 return Err(NativeEmulatorError::GbaNoBios); 31 }; 32 33 let bios_rom = fs::read(bios_path).map_err(NativeEmulatorError::GbaBiosLoad)?; 34 35 let emulator = GameBoyAdvanceEmulator::create( 36 input.input, 37 bios_rom, 38 config.emulator_config, 39 save_writer, 40 )?; 41 42 let rom_title = file_name_no_ext(&input.rom_path)?; 43 let window_title = format!("gba - {rom_title}"); 44 45 let default_window_size = WindowSize::new_gba(config.common.initial_window_size); 46 47 Ok(CreatedEmulator { emulator, window_title, default_window_size }) 48 } 49 50 fn common_config(config: &Self::NativeConfig) -> &CommonConfig { 51 &config.common 52 } 53 54 fn emulator_config(config: &Self::NativeConfig) -> &Self::Config { 55 &config.emulator_config 56 } 57 58 fn reload_native_config( 59 emulator: &mut NativeEmulator<Self>, 60 config: &Self::NativeConfig, 61 ) -> NativeEmulatorResult<()> { 62 emulator.inputs.solar = SolarSensorState { 63 brightness: emulator.inputs.solar.brightness, 64 ..new_solar_state(config) 65 }; 66 67 Ok(()) 68 } 69 70 fn initial_inputs(config: &Self::NativeConfig) -> Self::Inputs { 71 GbaInputs { solar: new_solar_state(config), ..GbaInputs::default() } 72 } 73 74 fn input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 75 config.inputs.to_mapping_vec() 76 } 77 78 fn turbo_input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> { 79 config.inputs.to_turbo_mapping_vec() 80 } 81 82 fn debug_fn() -> Option<NativeDebugFn<Self>> { 83 Some(|| { 84 jgenesis_debugger_frontend::partial_clone_debug_fn( 85 jgenesis_debugger_frontend::gba::render_fn(), 86 ) 87 }) 88 } 89} 90 91fn new_solar_state(config: &GameBoyAdvanceConfig) -> SolarSensorState { 92 SolarSensorState { 93 brightness: config.solar_min_brightness, 94 brightness_step: config.solar_brightness_step, 95 min_brightness: config.solar_min_brightness, 96 max_brightness: config.solar_max_brightness, 97 } 98}