Implemenet GBA Halt control

Former-commit-id: 1b09cb881b4e68f410abe6e1f6a161cd55a4626a
This commit is contained in:
Michel Heily 2019-11-12 18:55:26 +02:00
parent dcab1e6328
commit 88b908f2a0
2 changed files with 29 additions and 15 deletions

View file

@ -1,12 +1,11 @@
/// Struct containing everything /// Struct containing everything
use super::arm7tdmi::{exception::Exception, Core, CpuState, DecodedInstruction}; use super::arm7tdmi::Core;
use super::cartridge::Cartridge; use super::cartridge::Cartridge;
use super::gpu::*; use super::gpu::*;
use super::interrupt::*; use super::interrupt::*;
use super::iodev::*; use super::iodev::*;
use super::sysbus::SysBus; use super::sysbus::SysBus;
use super::GBAResult;
use super::SyncedIoDevice; use super::SyncedIoDevice;
use crate::backend::*; use crate::backend::*;
@ -45,14 +44,6 @@ impl GameBoyAdvance {
self.sysbus.io.keyinput = self.backend.get_key_state(); self.sysbus.io.keyinput = self.backend.get_key_state();
} }
// TODO deprecate
pub fn step(&mut self) -> GBAResult<DecodedInstruction> {
let previous_cycles = self.cpu.cycles;
let executed_insn = self.cpu.step_one(&mut self.sysbus)?;
let cycles = self.cpu.cycles - previous_cycles;
Ok(executed_insn)
}
pub fn step_new(&mut self) { pub fn step_new(&mut self) {
let mut irqs = IrqBitmask(0); let mut irqs = IrqBitmask(0);
let previous_cycles = self.cpu.cycles; let previous_cycles = self.cpu.cycles;
@ -63,14 +54,21 @@ impl GameBoyAdvance {
&mut (*ptr).io as &mut IoDevices &mut (*ptr).io as &mut IoDevices
}; };
if !io.dmac.perform_work(&mut self.sysbus, &mut irqs) { let cycles = if !io.dmac.perform_work(&mut self.sysbus, &mut irqs) {
if io.intc.irq_pending() { if io.intc.irq_pending() {
self.cpu.irq(&mut self.sysbus); self.cpu.irq(&mut self.sysbus);
io.haltcnt = HaltState::Running;
} }
self.cpu.step(&mut self.sysbus).unwrap();
}
let cycles = self.cpu.cycles - previous_cycles; if HaltState::Running == io.haltcnt {
self.cpu.step(&mut self.sysbus).unwrap();
self.cpu.cycles - previous_cycles
} else {
1
}
} else {
0
};
io.timers.step(cycles, &mut self.sysbus, &mut irqs); io.timers.step(cycles, &mut self.sysbus, &mut irqs);
if let Some(new_gpu_state) = io.gpu.step(cycles, &mut self.sysbus, &mut irqs) { if let Some(new_gpu_state) = io.gpu.step(cycles, &mut self.sysbus, &mut irqs) {

View file

@ -9,6 +9,13 @@ use super::timer::Timers;
use consts::*; use consts::*;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum HaltState {
Running,
Halt, // In Halt mode, the CPU is paused as long as (IE AND IF)=0,
Stop, // In Stop mode, most of the hardware including sound and video are paused
}
#[derive(Debug)] #[derive(Debug)]
pub struct IoDevices { pub struct IoDevices {
pub intc: InterruptController, pub intc: InterruptController,
@ -18,6 +25,7 @@ pub struct IoDevices {
pub keyinput: u16, pub keyinput: u16,
pub post_boot_flag: bool, pub post_boot_flag: bool,
pub waitcnt: WaitControl, // TODO also implement 4000800 pub waitcnt: WaitControl, // TODO also implement 4000800
pub haltcnt: HaltState,
mem: BoxedMemory, mem: BoxedMemory,
} }
@ -31,6 +39,7 @@ impl IoDevices {
intc: InterruptController::new(), intc: InterruptController::new(),
mem: BoxedMemory::new(vec![0; 0x800].into_boxed_slice()), mem: BoxedMemory::new(vec![0; 0x800].into_boxed_slice()),
post_boot_flag: false, post_boot_flag: false,
haltcnt: HaltState::Running,
keyinput: keypad::KEYINPUT_ALL_RELEASED, keyinput: keypad::KEYINPUT_ALL_RELEASED,
waitcnt: WaitControl(0), waitcnt: WaitControl(0),
} }
@ -223,7 +232,14 @@ impl Bus for IoDevices {
REG_WAITCNT => io.waitcnt.0 = value, REG_WAITCNT => io.waitcnt.0 = value,
REG_POSTFLG => io.post_boot_flag = value != 0, REG_POSTFLG => io.post_boot_flag = value != 0,
REG_HALTCNT => {} REG_HALTCNT => {
if value & 0x80 != 0 {
io.haltcnt = HaltState::Stop;
panic!("Can't handle HaltCtrl == Stop yet");
} else {
io.haltcnt = HaltState::Halt;
}
}
_ => { _ => {
println!( println!(
"Unimplemented write to {:x} {}", "Unimplemented write to {:x} {}",