config!!!

This commit is contained in:
Alex Janka 2023-10-05 10:14:54 +11:00
parent 71bb9f8e6d
commit d3d2de183c
6 changed files with 338 additions and 135 deletions

44
Cargo.lock generated
View file

@ -364,6 +364,9 @@ name = "bitflags"
version = "2.4.0" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "blake3" name = "blake3"
@ -975,6 +978,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "directories"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
dependencies = [
"dirs-sys",
]
[[package]] [[package]]
name = "dirs-next" name = "dirs-next"
version = "1.0.2" version = "1.0.2"
@ -985,6 +997,18 @@ dependencies = [
"dirs-sys-next", "dirs-sys-next",
] ]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "dirs-sys-next" name = "dirs-sys-next"
version = "0.1.2" version = "0.1.2"
@ -1255,6 +1279,7 @@ dependencies = [
"ash-window", "ash-window",
"async-ringbuf", "async-ringbuf",
"bytemuck", "bytemuck",
"directories",
"futures", "futures",
"itertools", "itertools",
"librashader", "librashader",
@ -1263,6 +1288,7 @@ dependencies = [
"pixels", "pixels",
"rand", "rand",
"raw-window-handle", "raw-window-handle",
"ron",
"serde", "serde",
"serde_with", "serde_with",
] ]
@ -2514,6 +2540,12 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "orbclient" name = "orbclient"
version = "0.3.46" version = "0.3.46"
@ -2887,6 +2919,18 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64",
"bitflags 2.4.0",
"serde",
"serde_derive",
]
[[package]] [[package]]
name = "roxmltree" name = "roxmltree"
version = "0.14.1" version = "0.14.1"

View file

@ -5,13 +5,15 @@ use camera::Webcam;
use clap::{ArgGroup, Parser}; use clap::{ArgGroup, Parser};
use debug::Debugger; use debug::Debugger;
use gb_emu_lib::{ use gb_emu_lib::{
config::ConfigManager,
connect::{ connect::{
EmulatorCoreTrait, EmulatorMessage, EmulatorOptions, NoCamera, RomFile, SerialTarget, CgbRomType, EmulatorCoreTrait, EmulatorMessage, EmulatorOptions, NoCamera, RomFile,
StdoutType, SerialTarget, SramType, StdoutType,
}, },
EmulatorCore, EmulatorCore,
}; };
use gilrs::Gilrs; use gilrs::Gilrs;
use serde::{Deserialize, Serialize};
use std::{ use std::{
path::PathBuf, path::PathBuf,
sync::mpsc::channel, sync::mpsc::channel,
@ -47,14 +49,6 @@ struct Args {
#[arg(long)] #[arg(long)]
no_save: bool, no_save: bool,
/// BootROM path
#[arg(short, long)]
bootrom: Option<String>,
/// Shader path
#[arg(long)]
shader: Option<String>,
/// Output link port to stdout as ASCII /// Output link port to stdout as ASCII
#[arg(long)] #[arg(long)]
ascii: bool, ascii: bool,
@ -71,10 +65,6 @@ struct Args {
#[arg(long)] #[arg(long)]
layer_window: bool, layer_window: bool,
/// Scale display by...
#[arg(short, long)]
scale_factor: Option<usize>,
/// Mute audio /// Mute audio
#[arg(long)] #[arg(long)]
mute: bool, mute: bool,
@ -82,19 +72,23 @@ struct Args {
/// Run debug console /// Run debug console
#[arg(long)] #[arg(long)]
debug: bool, debug: bool,
/// Prefer DMG mode
#[arg(short, long)]
dmg: bool,
/// Show BootROM
#[arg(long)]
show_bootrom: bool,
// /// Use webcam as Pocket Camera emulation // /// Use webcam as Pocket Camera emulation
// #[arg(short, long)] // #[arg(short, long)]
// camera: bool, // camera: bool,
} }
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct StandaloneConfig {
scale_factor: usize,
}
impl Default for StandaloneConfig {
fn default() -> Self {
Self { scale_factor: 3 }
}
}
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
@ -114,8 +108,6 @@ struct EmulatorHandler {
impl EmulatorHandler { impl EmulatorHandler {
fn run(args: Args) -> ! { fn run(args: Args) -> ! {
let factor = args.scale_factor.unwrap_or(3);
let (sender, receiver) = channel::<EmulatorMessage>(); let (sender, receiver) = channel::<EmulatorMessage>();
{ {
@ -126,31 +118,50 @@ impl EmulatorHandler {
.unwrap(); .unwrap();
} }
let config_manager = ConfigManager::get().expect("Could not open config folder");
let config = config_manager.load_or_create_base_config();
let standalone_config: StandaloneConfig =
config_manager.load_or_create_config("standalone");
let (output, _stream) = audio::create_output(args.mute); let (output, _stream) = audio::create_output(args.mute);
let rom = RomFile::Path(args.rom); let rom_file = RomFile::Path(PathBuf::from(args.rom));
let (rom, camera) = rom_file
.load(
args.save.map(SramType::File).unwrap_or(SramType::Auto),
NoCamera::default(),
)
.expect("Error parsing rom");
let shader_path = if rom.rom_type == CgbRomType::CgbOnly || config.prefer_cgb {
config.vulkan_config.cgb_shader_path.as_ref()
} else {
config.vulkan_config.dmg_shader_path.as_ref()
}
.map(|v| config_manager.dir().join(v));
let mut window_manager = WindowManager::new(sender); let mut window_manager = WindowManager::new(sender);
let window = window_manager.add( let window = window_manager.add(
factor, standalone_config.scale_factor,
Some(Gilrs::new().unwrap()), Some(Gilrs::new().unwrap()),
args.shader.map(PathBuf::from), shader_path,
); );
let tile_window: Option<WindowRenderer> = if args.tile_window { let tile_window: Option<WindowRenderer> = if args.tile_window {
Some(window_manager.add(factor, None, None)) Some(window_manager.add(standalone_config.scale_factor, None, None))
} else { } else {
None None
}; };
let layer_window: Option<WindowRenderer> = if args.layer_window { let layer_window: Option<WindowRenderer> = if args.layer_window {
Some(window_manager.add(factor.min(2), None, None)) Some(window_manager.add(standalone_config.scale_factor.min(2), None, None))
} else { } else {
None None
}; };
let options = EmulatorOptions::new(window, rom, output) let options =
.with_save_path(args.save) EmulatorOptions::new_with_config(config, config_manager.dir(), window, rom, output)
.with_serial_target(if args.ascii { .with_serial_target(if args.ascii {
SerialTarget::Stdout(StdoutType::Ascii) SerialTarget::Stdout(StdoutType::Ascii)
} else if args.hex { } else if args.hex {
@ -158,20 +169,9 @@ impl EmulatorHandler {
} else { } else {
SerialTarget::None SerialTarget::None
}) })
.with_bootrom(
args.bootrom
.or(if args.dmg {
std::env::var("DMG_BOOTROM").ok()
} else {
std::env::var("CGB_BOOTROM").ok()
})
.map(RomFile::Path),
args.show_bootrom,
)
.with_no_save(args.no_save) .with_no_save(args.no_save)
.with_tile_window(tile_window) .with_tile_window(tile_window)
.with_layer_window(layer_window) .with_layer_window(layer_window);
.with_cgb_mode(!args.dmg);
// let core: Box<dyn EmulatorCoreTrait> = if args.camera { // let core: Box<dyn EmulatorCoreTrait> = if args.camera {
// Box::new(EmulatorCore::init(receiver, options, Webcam::new())) // Box::new(EmulatorCore::init(receiver, options, Webcam::new()))
@ -181,7 +181,7 @@ impl EmulatorHandler {
#[cfg(not(feature = "camera"))] #[cfg(not(feature = "camera"))]
let core: Box<dyn EmulatorCoreTrait> = let core: Box<dyn EmulatorCoreTrait> =
Box::new(EmulatorCore::init(receiver, options, NoCamera::default())); Box::new(EmulatorCore::init(receiver, options, camera));
#[cfg(feature = "camera")] #[cfg(feature = "camera")]
let core = Box::new(EmulatorCore::init(receiver, options, Webcam::new())); let core = Box::new(EmulatorCore::init(receiver, options, Webcam::new()));

113
lib/src/config/mod.rs Normal file
View file

@ -0,0 +1,113 @@
use std::{
fs,
io::{BufReader, BufWriter},
path::PathBuf,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
pub struct ConfigManager {
path: PathBuf,
}
impl ConfigManager {
pub fn get() -> Option<Self> {
directories::ProjectDirs::from("com", "alexjanka", "TWINC")
.map(|v| v.config_dir().to_path_buf())
.map(|path| {
if let Ok(false) = path.try_exists() {
fs::create_dir_all(path.clone()).expect("Failed to create config dir");
};
Self { path }
})
}
pub fn dir(&self) -> PathBuf {
self.path.clone()
}
pub fn load_or_create_base_config(&self) -> Config {
self.load_or_create_config("base")
}
pub fn load_or_create_config<C>(&self, name: &str) -> C
where
C: Serialize + DeserializeOwned + Default + Clone,
{
match self.load_custom_config(name) {
Some(v) => v,
None => {
let config = C::default();
if let Ok(true) = self.path.join(name).try_exists() {
eprintln!("Failed to load \"{name}\" config, but it exists on disk");
} else {
let result = self.save_custom_config(name, config.clone());
if let Err(e) = result {
eprintln!("Failed to save \"{name}\" config: {e:#?}");
}
}
config
}
}
}
pub fn load_custom_config<C>(&self, name: &str) -> Option<C>
where
C: DeserializeOwned + Default,
{
let path = self.path.join(name);
ron::de::from_reader(BufReader::new(fs::File::open(path).ok()?)).ok()
}
pub fn save_custom_config<C>(&self, name: &str, config: C) -> Result<(), ron::Error>
where
C: Serialize,
{
let path = self.path.join(name);
ron::ser::to_writer_pretty(
BufWriter::new(fs::File::create(path)?),
&config,
Default::default(),
)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct Config {
pub dmg_bootrom: Option<String>,
pub cgb_bootrom: Option<String>,
pub show_bootrom: bool,
pub prefer_cgb: bool,
pub vulkan_config: VulkanRendererConfig,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct VulkanRendererConfig {
pub dmg_shader_path: Option<String>,
pub cgb_shader_path: Option<String>,
}
#[allow(clippy::derivable_impls)]
impl Default for Config {
fn default() -> Self {
Self {
dmg_bootrom: None,
cgb_bootrom: None,
show_bootrom: false,
prefer_cgb: true,
vulkan_config: Default::default(),
}
}
}
#[allow(clippy::derivable_impls)]
impl Default for VulkanRendererConfig {
fn default() -> Self {
Self {
dmg_shader_path: None,
cgb_shader_path: None,
}
}
}

View file

@ -1,9 +1,14 @@
use std::fs;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
pub use crate::processor::memory::mmio::gpu::Colour; pub use crate::processor::memory::mmio::gpu::Colour;
pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState}; pub use crate::processor::memory::mmio::joypad::{JoypadButtons, JoypadState};
pub use crate::processor::memory::mmio::serial::{SerialTarget, StdoutType}; pub use crate::processor::memory::mmio::serial::{SerialTarget, StdoutType};
use crate::processor::memory::rom::sram_save::SaveDataLocation;
pub use crate::processor::memory::rom::CgbRomType;
use crate::processor::memory::Rom;
pub use crate::{HEIGHT, WIDTH}; pub use crate::{HEIGHT, WIDTH};
use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb}; use async_ringbuf::{AsyncHeapConsumer, AsyncHeapProducer, AsyncHeapRb};
@ -18,10 +23,54 @@ pub enum DownsampleType {
} }
pub enum RomFile { pub enum RomFile {
Path(String), Path(PathBuf),
Raw(Vec<u8>), Raw(Vec<u8>),
} }
impl RomFile {
#[allow(clippy::type_complexity)]
pub fn load<C>(
self,
save: SramType,
camera: C,
) -> Result<(Rom<C>, Arc<Mutex<CameraWrapper<C>>>), std::io::Error>
where
C: PocketCamera + Send + 'static,
{
let camera: CameraWrapperRef<C> = Arc::new(Mutex::new(CameraWrapper::new(camera)));
match self {
RomFile::Path(path) => {
let save_location = match save {
SramType::File(path) => Some(SaveDataLocation::File(PathBuf::from(path))),
SramType::RawBuffer(buf) => Some(SaveDataLocation::Raw(buf)),
SramType::Auto => Some(SaveDataLocation::File(path.with_extension("sav"))),
SramType::None => None,
};
fs::read(path).map(|data| Rom::load(data, save_location, camera.clone()))
}
RomFile::Raw(data) => {
let save_location = match save {
SramType::File(path) => Some(SaveDataLocation::File(PathBuf::from(path))),
SramType::RawBuffer(buf) => Some(SaveDataLocation::Raw(buf)),
SramType::Auto => None,
SramType::None => None,
};
Ok(Rom::load(data, save_location, camera.clone()))
}
}
.map(|v| (v, camera))
}
pub fn load_data(self) -> Result<Vec<u8>, std::io::Error> {
match self {
RomFile::Path(path) => std::fs::read(path),
RomFile::Raw(data) => Ok(data),
}
}
}
pub trait Renderer<Format: From<Colour>> { pub trait Renderer<Format: From<Colour>> {
fn prepare(&mut self, width: usize, height: usize); fn prepare(&mut self, width: usize, height: usize);
@ -112,7 +161,7 @@ impl PocketCamera for NoCamera {
pub(crate) type CameraWrapperRef<C> = Arc<Mutex<CameraWrapper<C>>>; pub(crate) type CameraWrapperRef<C> = Arc<Mutex<CameraWrapper<C>>>;
pub(crate) struct CameraWrapper<C> pub struct CameraWrapper<C>
where where
C: PocketCamera, C: PocketCamera,
{ {
@ -163,35 +212,40 @@ where
pub enum SramType { pub enum SramType {
File(String), File(String),
RawBuffer(Arc<RwLock<Vec<u8>>>), RawBuffer(Arc<RwLock<Vec<u8>>>),
Auto,
None,
} }
#[non_exhaustive] #[non_exhaustive]
pub struct EmulatorOptions<ColourFormat, R> pub struct EmulatorOptions<ColourFormat, R, C>
where where
ColourFormat: From<Colour> + Copy, ColourFormat: From<Colour> + Copy,
R: Renderer<ColourFormat>, R: Renderer<ColourFormat>,
C: PocketCamera + Send + 'static,
{ {
pub(crate) window: R, pub(crate) window: R,
pub(crate) tile_window: Option<R>, pub(crate) tile_window: Option<R>,
pub(crate) layer_window: Option<R>, pub(crate) layer_window: Option<R>,
pub(crate) rom: RomFile, pub(crate) rom: Rom<C>,
pub(crate) output: AudioOutput, pub(crate) output: AudioOutput,
pub(crate) save: Option<SramType>, pub(crate) save: Option<SramType>,
pub(crate) no_save: bool, pub(crate) no_save: bool,
pub(crate) bootrom: Option<RomFile>, pub(crate) dmg_bootrom: Option<RomFile>,
pub(crate) cgb_bootrom: Option<RomFile>,
pub(crate) show_bootrom: bool, pub(crate) show_bootrom: bool,
pub(crate) serial_target: SerialTarget, pub(crate) serial_target: SerialTarget,
pub(crate) cgb_mode: bool, pub(crate) cgb_mode: bool,
spooky: PhantomData<ColourFormat>, _spooky: PhantomData<ColourFormat>,
} }
impl<ColourFormat, R> EmulatorOptions<ColourFormat, R> impl<ColourFormat, R, C> EmulatorOptions<ColourFormat, R, C>
where where
ColourFormat: From<Colour> + Copy, ColourFormat: From<Colour> + Copy,
R: Renderer<ColourFormat>, R: Renderer<ColourFormat>,
C: PocketCamera + Send + 'static,
{ {
pub fn new(window: R, rom: RomFile, output: AudioOutput) -> Self { pub fn new(window: R, rom: Rom<C>, output: AudioOutput) -> Self {
Self { Self {
window, window,
tile_window: None, tile_window: None,
@ -200,17 +254,44 @@ where
output, output,
save: None, save: None,
no_save: false, no_save: false,
bootrom: None, dmg_bootrom: None,
cgb_bootrom: None,
show_bootrom: false, show_bootrom: false,
serial_target: SerialTarget::None, serial_target: SerialTarget::None,
cgb_mode: true, cgb_mode: true,
spooky: PhantomData, _spooky: PhantomData,
} }
} }
pub fn with_save_path(mut self, path: Option<String>) -> Self { #[cfg(feature = "config")]
self.save = path.map(SramType::File); pub fn new_with_config(
self config: crate::config::Config,
config_dir: PathBuf,
window: R,
rom: Rom<C>,
output: AudioOutput,
) -> Self {
Self {
window,
tile_window: None,
layer_window: None,
rom,
output,
save: None,
no_save: false,
dmg_bootrom: config
.dmg_bootrom
.map(|v| config_dir.join(v))
.map(RomFile::Path),
cgb_bootrom: config
.cgb_bootrom
.map(|v| config_dir.join(v))
.map(RomFile::Path),
show_bootrom: config.show_bootrom,
serial_target: SerialTarget::None,
cgb_mode: config.prefer_cgb,
_spooky: Default::default(),
}
} }
pub fn with_sram_buffer(mut self, buffer: Arc<RwLock<Vec<u8>>>) -> Self { pub fn with_sram_buffer(mut self, buffer: Arc<RwLock<Vec<u8>>>) -> Self {
@ -228,8 +309,17 @@ where
self self
} }
pub fn with_bootrom(mut self, bootrom: Option<RomFile>, show_bootrom: bool) -> Self { pub fn with_dmg_bootrom(mut self, dmg_bootrom: Option<RomFile>) -> Self {
self.bootrom = bootrom; self.dmg_bootrom = dmg_bootrom;
self
}
pub fn with_cgb_bootrom(mut self, cgb_bootrom: Option<RomFile>) -> Self {
self.cgb_bootrom = cgb_bootrom;
self
}
pub fn with_show_bootrom(mut self, show_bootrom: bool) -> Self {
self.show_bootrom = show_bootrom; self.show_bootrom = show_bootrom;
self self
} }

View file

@ -5,24 +5,17 @@ use crate::{
util::pause, util::pause,
}; };
use connect::{ use connect::{
AudioOutput, CameraWrapper, CameraWrapperRef, EmulatorCoreTrait, EmulatorMessage, AudioOutput, CameraWrapper, EmulatorCoreTrait, EmulatorMessage, EmulatorOptions, PocketCamera,
EmulatorOptions, PocketCamera, Renderer, RomFile, SramType, Renderer, RomFile,
}; };
use processor::{ use processor::{
memory::{ memory::{mmio::gpu::Colour, rom::CgbRomType, OutputTargets},
mmio::gpu::Colour,
rom::{sram_save::SaveDataLocation, CgbRomType},
OutputTargets, Rom,
},
Cpu, Cpu,
}; };
use std::{ use std::{
fs::{self},
io::{stdout, Write}, io::{stdout, Write},
marker::PhantomData, marker::PhantomData,
path::PathBuf,
process::exit, process::exit,
str::FromStr,
sync::{mpsc::Receiver, Arc, Mutex}, sync::{mpsc::Receiver, Arc, Mutex},
}; };
@ -35,6 +28,8 @@ compile_error!("select only one rendering backend!");
#[cfg_attr(feature = "vulkan-renderer", path = "renderer/vulkan/vulkan.rs")] #[cfg_attr(feature = "vulkan-renderer", path = "renderer/vulkan/vulkan.rs")]
pub mod renderer; pub mod renderer;
#[cfg(feature = "config")]
pub mod config;
pub mod connect; pub mod connect;
mod constants; mod constants;
mod processor; mod processor;
@ -62,76 +57,37 @@ where
{ {
pub fn init( pub fn init(
receiver: Receiver<EmulatorMessage>, receiver: Receiver<EmulatorMessage>,
mut options: EmulatorOptions<ColourFormat, R>, mut options: EmulatorOptions<ColourFormat, R, C>,
camera: C, camera: Arc<Mutex<CameraWrapper<C>>>,
) -> Self { ) -> Self {
let camera: CameraWrapperRef<C> = Arc::new(Mutex::new(CameraWrapper::new(camera))); let rom = options.rom;
let maybe_save = options.save.map(|i| match i { let is_cgb_mode = rom.rom_type == CgbRomType::CgbOnly || options.cgb_mode;
SramType::File(sram_path) => { let bootrom = if is_cgb_mode {
SaveDataLocation::File(PathBuf::from_str(&sram_path).unwrap()) options.cgb_bootrom.unwrap_or(RomFile::Raw(
} include_bytes!("../../sameboy-bootroms/cgb_boot.bin").to_vec(),
SramType::RawBuffer(buffer) => SaveDataLocation::Raw(buffer), ))
});
let rom = match options.rom {
RomFile::Path(path) => {
let maybe_save = if options.no_save {
None
} else { } else {
Some(maybe_save.unwrap_or(SaveDataLocation::File( options.dmg_bootrom.unwrap_or(RomFile::Raw(
PathBuf::from_str(&path).unwrap().with_extension("sav"), include_bytes!("../../sameboy-bootroms/dmg_boot.bin").to_vec(),
))) ))
};
match fs::read(path) {
Ok(data) => Rom::load(data, maybe_save, camera.clone()),
Err(e) => {
eprintln!("Error reading ROM: {e}");
exit(1);
} }
} .load_data()
} .expect("Error loading bootrom!");
RomFile::Raw(data) => Rom::load(data, maybe_save, camera.clone()),
};
let (bootrom, cgb) = if let Some(b) = options.bootrom {
let bootrom = match b {
RomFile::Path(path) => match fs::read(path) {
Ok(data) => data,
Err(e) => {
eprintln!("Error reading bootROM: {e}");
exit(1);
}
},
RomFile::Raw(data) => data,
};
let cgb =
rom.rom_type == CgbRomType::CgbOnly || options.cgb_mode || bootrom.len() > 256;
(bootrom, cgb)
} else {
let cgb = rom.rom_type == CgbRomType::CgbOnly || options.cgb_mode;
let bootrom = if cgb {
include_bytes!("../../sameboy-bootroms/cgb_boot.bin").to_vec()
} else {
include_bytes!("../../sameboy-bootroms/dmg_boot.bin").to_vec()
};
(bootrom, cgb)
};
options.window.prepare(WIDTH, HEIGHT); options.window.prepare(WIDTH, HEIGHT);
options.window.set_title(format!( options.window.set_title(format!(
"{} on {} on {}", "{} on {} on {}",
rom.get_title(), rom.get_title(),
rom.mbc_type(), rom.mbc_type(),
if cgb { "CGB" } else { "DMG" } if is_cgb_mode { "CGB" } else { "DMG" }
)); ));
Self::new( Self::new(
receiver, receiver,
Cpu::new( Cpu::new(
Memory::init( Memory::init(
cgb, is_cgb_mode,
bootrom, bootrom,
rom, rom,
OutputTargets::new( OutputTargets::new(

View file

@ -12,7 +12,7 @@ mod mbcs;
pub mod sram_save; pub mod sram_save;
#[derive(Serialize, Deserialize, Debug, PartialEq)] #[derive(Serialize, Deserialize, Debug, PartialEq)]
pub(crate) enum CgbRomType { pub enum CgbRomType {
Dmg, Dmg,
CgbOptional, CgbOptional,
CgbOnly, CgbOnly,
@ -24,7 +24,7 @@ where
{ {
title: String, title: String,
mbc: Box<dyn Mbc>, mbc: Box<dyn Mbc>,
pub(crate) rom_type: CgbRomType, pub rom_type: CgbRomType,
spooky: PhantomData<C>, spooky: PhantomData<C>,
} }