gb.rsannotatedgb.rssource90 lines · 3.0 KB · raw
1use crate::config::{CommonConfig, GameBoyConfig};
2use crate::mainloop::create::{CreatableEmulator, ReadInputResult};
3use crate::mainloop::{CreatedEmulator, NativeDebugFn, create, file_name_no_ext};
4use crate::{NativeEmulator, NativeEmulatorError, NativeEmulatorResult, extensions};
5use gb_core::api::{BootRoms, GameBoyEmulator};
6use jgenesis_common::frontend::SaveWriter;
7use jgenesis_native_config::common::WindowSize;
8use jgenesis_native_config::input::mappings::ButtonMappingVec;
9use std::fs;
10use std::path::PathBuf;
11
12pub type NativeGameBoyEmulator = NativeEmulator<GameBoyEmulator>;
13
14impl CreatableEmulator for GameBoyEmulator {
15    type NativeConfig = GameBoyConfig;
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::GB_GBC)
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 dmg_boot_rom = load_boot_rom(
30            config.dmg_boot_rom,
31            config.dmg_boot_rom_path.as_ref(),
32            NativeEmulatorError::GbNoDmgBootRom,
33        )?;
34        let cgb_boot_rom = load_boot_rom(
35            config.cgb_boot_rom,
36            config.cgb_boot_rom_path.as_ref(),
37            NativeEmulatorError::GbNoCgbBootRom,
38        )?;
39        let boot_roms = BootRoms { dmg: dmg_boot_rom, cgb: cgb_boot_rom };
40
41        let emulator =
42            GameBoyEmulator::create(input.input, boot_roms, config.emulator_config, save_writer)?;
43
44        let rom_title = file_name_no_ext(&input.rom_path)?;
45        let window_title = format!("gb - {rom_title}");
46
47        let default_window_size = WindowSize::new_gb(config.common.initial_window_size);
48
49        Ok(CreatedEmulator { emulator, window_title, default_window_size })
50    }
51
52    fn common_config(config: &Self::NativeConfig) -> &CommonConfig {
53        &config.common
54    }
55
56    fn emulator_config(config: &Self::NativeConfig) -> &Self::Config {
57        &config.emulator_config
58    }
59
60    fn input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> {
61        config.inputs.to_mapping_vec()
62    }
63
64    fn turbo_input_mappings(config: &Self::NativeConfig) -> ButtonMappingVec<'_, Self::Button> {
65        config.inputs.to_turbo_mapping_vec()
66    }
67
68    fn debug_fn() -> Option<NativeDebugFn<Self>> {
69        Some(|| {
70            jgenesis_debugger_frontend::partial_clone_debug_fn(
71                jgenesis_debugger_frontend::gb::render_fn(),
72            )
73        })
74    }
75}
76
77fn load_boot_rom(
78    load: bool,
79    path: Option<&PathBuf>,
80    no_boot_rom_err: NativeEmulatorError,
81) -> NativeEmulatorResult<Option<Vec<u8>>> {
82    if !load {
83        return Ok(None);
84    }
85
86    let Some(path) = path else { return Err(no_boot_rom_err) };
87
88    let boot_rom = fs::read(path).map_err(NativeEmulatorError::GbBootRomLoad)?;
89    Ok(Some(boot_rom))
90}