Implemenet GBA Halt control
Former-commit-id: 1b09cb881b4e68f410abe6e1f6a161cd55a4626a
This commit is contained in:
parent
dcab1e6328
commit
88b908f2a0
|
@ -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) {
|
||||||
|
|
|
@ -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} {}",
|
||||||
|
|
Reference in a new issue