Newer
Older
// parses the provided command line arguments and uses them to
// obtain structured values
let args = Args::parse();
// in case the default ROM path is provided and the file does not
// exist then fails gracefully
let path = Path::new(&args.rom_path);
if args.rom_path == DEFAULT_ROM_PATH && !path.exists() {
println!("No ROM file provided, please provide one using the [ROM_PATH] argument");
// tries to build the target mode from the mode argument
// parsing it if it does not contain the "auto" value
let mode = if args.mode == "auto" {
GameBoyMode::Dmg
} else {
GameBoyMode::from_string(&args.mode)
};
let auto_mode = args.mode == "auto";
// creates a new Game Boy instance and loads both the boot ROM
// and the initial game ROM to "start the engine"
let mut game_boy = GameBoy::new(Some(mode));
let mode = Cartridge::from_file(&args.rom_path).unwrap().gb_mode();
game_boy.set_mode(mode);
}
let device: Box<dyn SerialDevice> = build_device(&args.device);
game_boy.set_ppu_enabled(!args.no_ppu);
game_boy.set_apu_enabled(!args.no_apu);
game_boy.set_dma_enabled(!args.no_dma);
game_boy.set_timer_enabled(!args.no_timer);
game_boy.attach_serial(device);
game_boy.load(!args.no_boot && args.boot_rom_path.is_empty());
if args.no_boot {
game_boy.load_boot_state();
}
game_boy.load_boot_path(&args.boot_rom_path).unwrap();
}
// prints the current version of the emulator (informational message)
println!("========= {} =========\n{}", Info::name(), game_boy);
// creates a new generic emulator structure then starts
// both the video and audio sub-systems, loads default
auto_mode: Some(auto_mode),
unlimited: Some(args.unlimited),
features: if args.headless || args.benchmark {
Some(vec![])
} else {
Some(vec!["video", "audio", "no-vsync"])
},
};
let mut emulator = Emulator::new(game_boy, options);
emulator.start(SCREEN_SCALE);
emulator.load_rom(Some(&args.rom_path)).unwrap();
emulator.toggle_palette();
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
fn build_device(device: &str) -> Box<dyn SerialDevice> {
match device {
"null" => Box::<NullDevice>::default(),
"stdout" => Box::<StdoutDevice>::default(),
"printer" => {
let mut printer = Box::<PrinterDevice>::default();
printer.set_callback(|image_buffer| {
let file_name = format!("printer-{}.png", Utc::now().format("%Y%m%d-%H%M%S"));
image::save_buffer(
Path::new(&file_name),
image_buffer,
160,
(image_buffer.len() / 4 / 160) as u32,
ColorType::Rgba8,
)
.unwrap();
});
printer
}
_ => panic!("Unsupported device: {}", device),
}
}
fn key_to_pad(keycode: Keycode) -> Option<PadKey> {
Keycode::Up => Some(PadKey::Up),
Keycode::Down => Some(PadKey::Down),
Keycode::Left => Some(PadKey::Left),
Keycode::Right => Some(PadKey::Right),
Keycode::Return => Some(PadKey::Start),
Keycode::Return2 => Some(PadKey::Start),
Keycode::Space => Some(PadKey::Select),
Keycode::A => Some(PadKey::A),
Keycode::S => Some(PadKey::B),
_ => None,