Skip to content
Snippets Groups Projects
main.rs 40.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •     // 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();
        }
    
        if !args.boot_rom_path.is_empty() {
    
            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
    
        // ROM file and starts running it
    
        let options = EmulatorOptions {
    
            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.apply_cheats(&args.cheats);
    
        emulator.toggle_palette();
    
        run(args, &mut emulator);
    
    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,