diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/src/main.rs b/src/main.rs index f0a7361..b057486 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,38 +5,15 @@ pub mod gamepad; pub mod interrupts_timers; pub mod io; pub mod opcodes; +pub mod serial; pub mod state; -use crate::gamepad::Gamepad; -use crate::state::{GBState, MemError}; +use crate::gamepad::{Gamepad, Input}; +use crate::state::GBState; use clap::Parser; use std::time::SystemTime; use std::{thread, time}; -pub fn exec_opcode(state: &mut GBState) -> Result<u64, MemError> { - let opcode = state.mem.r(state.cpu.pc)?; - - if state.is_debug { - println!( - "{:02x}:{:04x} = {:02x} (IME: {})", - state.mem.rom_bank, state.cpu.pc, opcode, state.mem.ime - ); - } - - state.cpu.pc += 1; - - let n1 = (opcode >> 3) & 0b111; - let n2 = opcode & 0b111; - - match opcode >> 6 { - 0b00 => opcodes::op00(state, n1, n2), - 0b01 => opcodes::op01(state, n1, n2), - 0b10 => opcodes::op10(state, n1, n2), - 0b11 => opcodes::op11(state, n1, n2), - _ => panic!(), - } -} - #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { @@ -45,7 +22,16 @@ struct Cli { /// Setting this saves battery by using thread::sleep instead of spin_sleeping. It can result in lag and inconsistent timing. #[arg(long)] - thread_sleep: bool, + loop_lock_timing: bool, + + #[arg(long)] + fifo_input: Option<String>, + + #[arg(long)] + fifo_output: Option<String>, + + #[arg(short, long, default_value_t = false)] + keyboard: bool, #[arg(short, long, default_value_t = 1.0)] speed: f32, @@ -56,11 +42,17 @@ fn main() { println!("Initializing Gamepad..."); - let mut gamepad = Gamepad::new(); - println!("Starting {:?}...", &cli.rom); - let mut state = GBState::new(); + let mut state = match (cli.fifo_input, cli.fifo_output) { + (Some(fifo_input), Some(fifo_output)) => { + GBState::new(Box::new(serial::FIFOSerial::new(fifo_input, fifo_output))) + } + (None, None) => GBState::new(Box::new(serial::UnconnectedSerial {})), + _ => panic!("If using fifo serial, both input and output should be set"), + }; + + let mut gamepad = Gamepad::new(); let save_file = format!("{}.sav", &cli.rom); @@ -87,7 +79,7 @@ fn main() { } was_previously_halted = state.mem.halt; let c = if !state.mem.halt { - exec_opcode(&mut state).unwrap() + state.exec_opcode().unwrap() } else { halt_time += 4; 4 @@ -97,18 +89,27 @@ fn main() { state.tima_timer(c); state.update_display_interrupts(c); state.check_interrupts().unwrap(); + state.mem.update_serial(); nanos_sleep += c as i128 * (consts::CPU_CYCLE_LENGTH_NANOS as f32 / cli.speed) as i128; if nanos_sleep > 0 { - gamepad.update_events(); + let (action_button_reg, direction_button_reg) = if cli.keyboard { + ( + state.mem.display.get_action_gamepad_reg(), + state.mem.display.get_direction_gamepad_reg(), + ) + } else { + gamepad.update_events(); - let action_button_reg = gamepad.get_action_gamepad_reg(); - let direction_button_reg = gamepad.get_direction_gamepad_reg(); - gamepad.check_special_actions(&mut state); + ( + gamepad.get_action_gamepad_reg(), + gamepad.get_direction_gamepad_reg(), + ) + }; + // gamepad.check_special_actions(&mut state.is_debug); if state.mem.joypad_is_action - && (action_button_reg & (state.mem.joypad_reg >> 4)) - != (state.mem.joypad_reg >> 4) + && (action_button_reg & (state.mem.joypad_reg >> 4)) != (state.mem.joypad_reg >> 4) || (!state.mem.joypad_is_action && (direction_button_reg & state.mem.joypad_reg & 0b1111) != (state.mem.joypad_reg & 0b1111)) @@ -118,16 +119,18 @@ fn main() { state.mem.joypad_reg = direction_button_reg | (action_button_reg << 4); - if cli.thread_sleep { + if !cli.loop_lock_timing { thread::sleep(time::Duration::from_nanos(nanos_sleep as u64 / 10)); } else { while SystemTime::now().duration_since(now).unwrap().as_nanos() < nanos_sleep as u128 - {} + { + for _ in 0..100_000_000 {} + } } nanos_sleep = - nanos_sleep - SystemTime::now().duration_since(now).unwrap().as_nanos() as i128; + nanos_sleep - SystemTime::now().duration_since(now).unwrap().as_nanos() as i128; now = SystemTime::now(); if last_ram_bank_enabled && !state.mem.ram_bank_enabled { |