2019-07-06 23:33:54 +01:00
|
|
|
/// Struct containing everything
|
|
|
|
///
|
2019-07-15 05:35:09 +01:00
|
|
|
use super::arm7tdmi::{exception::*, Core, DecodedInstruction};
|
2019-07-06 13:53:36 +01:00
|
|
|
use super::cartridge::Cartridge;
|
2019-07-06 23:33:54 +01:00
|
|
|
use super::dma::DmaChannel;
|
2019-07-20 12:44:49 +01:00
|
|
|
use super::gpu::*;
|
2019-07-15 05:35:09 +01:00
|
|
|
use super::interrupt::*;
|
2019-07-06 23:33:54 +01:00
|
|
|
use super::ioregs::consts::*;
|
2019-07-06 13:53:36 +01:00
|
|
|
use super::sysbus::SysBus;
|
2019-07-20 14:46:00 +01:00
|
|
|
use super::EmuIoDev;
|
|
|
|
use super::{GBAError, GBAResult};
|
2019-07-06 13:53:36 +01:00
|
|
|
|
|
|
|
pub struct GameBoyAdvance {
|
|
|
|
pub cpu: Core,
|
|
|
|
pub sysbus: SysBus,
|
|
|
|
|
|
|
|
// io devices
|
2019-07-15 23:21:11 +01:00
|
|
|
pub gpu: Gpu,
|
2019-07-11 16:17:28 +01:00
|
|
|
pub dma0: DmaChannel,
|
|
|
|
pub dma1: DmaChannel,
|
|
|
|
pub dma2: DmaChannel,
|
|
|
|
pub dma3: DmaChannel,
|
2019-07-06 13:53:36 +01:00
|
|
|
|
|
|
|
post_bool_flags: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl GameBoyAdvance {
|
|
|
|
pub fn new(cpu: Core, bios_rom: Vec<u8>, gamepak: Cartridge) -> GameBoyAdvance {
|
|
|
|
let sysbus = SysBus::new(bios_rom, gamepak);
|
|
|
|
|
|
|
|
GameBoyAdvance {
|
|
|
|
cpu: cpu,
|
|
|
|
sysbus: sysbus,
|
|
|
|
|
2019-07-15 23:21:11 +01:00
|
|
|
gpu: Gpu::new(),
|
2019-07-06 23:33:54 +01:00
|
|
|
dma0: DmaChannel::new(REG_DMA0SAD, REG_DMA0DAD, REG_DMA0DAD),
|
|
|
|
dma1: DmaChannel::new(REG_DMA1SAD, REG_DMA1DAD, REG_DMA1DAD),
|
|
|
|
dma2: DmaChannel::new(REG_DMA2SAD, REG_DMA2DAD, REG_DMA2DAD),
|
|
|
|
dma3: DmaChannel::new(REG_DMA3SAD, REG_DMA3DAD, REG_DMA3DAD),
|
2019-07-06 13:53:36 +01:00
|
|
|
|
|
|
|
post_bool_flags: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-15 05:35:09 +01:00
|
|
|
fn emulate_n_cycles(&mut self, mut n: usize) {
|
|
|
|
let mut cycles = 0;
|
2019-07-11 16:17:28 +01:00
|
|
|
loop {
|
2019-07-15 05:35:09 +01:00
|
|
|
let previous_cycles = self.cpu.cycles;
|
2019-07-11 16:17:28 +01:00
|
|
|
self.cpu.step_one(&mut self.sysbus).unwrap();
|
2019-07-15 05:35:09 +01:00
|
|
|
let new_cycles = self.cpu.cycles - previous_cycles;
|
|
|
|
|
2019-07-15 23:21:11 +01:00
|
|
|
self.gpu.step(new_cycles, &mut self.sysbus);
|
2019-07-15 05:35:09 +01:00
|
|
|
cycles += new_cycles;
|
|
|
|
|
|
|
|
if n <= cycles {
|
2019-07-11 16:17:28 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn frame(&mut self) {
|
2019-07-15 23:21:11 +01:00
|
|
|
while self.gpu.state == GpuState::VBlank {
|
2019-07-15 05:35:09 +01:00
|
|
|
self.emulate();
|
2019-07-11 16:17:28 +01:00
|
|
|
}
|
2019-07-15 23:21:11 +01:00
|
|
|
while self.gpu.state != GpuState::VBlank {
|
2019-07-15 05:35:09 +01:00
|
|
|
self.emulate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn emulate(&mut self) {
|
|
|
|
let previous_cycles = self.cpu.cycles;
|
|
|
|
self.cpu.step(&mut self.sysbus).unwrap();
|
|
|
|
let cycles = self.cpu.cycles - previous_cycles;
|
2019-07-15 23:21:11 +01:00
|
|
|
self.gpu.step(cycles, &mut self.sysbus);
|
2019-07-15 05:35:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn interrupts_disabled(&self) -> bool {
|
|
|
|
self.sysbus.ioregs.read_reg(REG_IME) & 1 == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn request_irq(&mut self, irq: Interrupt) {
|
|
|
|
// if self.interrupts_disabled() {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// let irq_bit = irq as usize;
|
|
|
|
// let reg_ie = self.sysbus.ioregs.read_reg(REG_IE);
|
|
|
|
// if reg_ie & (1 << irq_bit) != 0 {
|
|
|
|
// println!("entering {:?}", irq);
|
|
|
|
// self.cpu.exception(Exception::Irq);
|
|
|
|
// }
|
2019-07-11 16:17:28 +01:00
|
|
|
}
|
|
|
|
|
2019-07-06 13:53:36 +01:00
|
|
|
pub fn step(&mut self) -> GBAResult<DecodedInstruction> {
|
|
|
|
let previous_cycles = self.cpu.cycles;
|
2019-07-11 16:17:28 +01:00
|
|
|
let executed_insn = self.cpu.step_one(&mut self.sysbus)?;
|
|
|
|
|
|
|
|
let mut cycles = self.cpu.cycles - previous_cycles;
|
|
|
|
|
|
|
|
// // drop interrupts at the moment
|
2019-07-06 23:33:54 +01:00
|
|
|
|
2019-07-11 16:17:28 +01:00
|
|
|
// let (dma_cycles, _) = self.dma0.step(cycles, &mut self.sysbus);
|
|
|
|
// cycles += dma_cycles;
|
2019-07-06 23:33:54 +01:00
|
|
|
|
2019-07-11 16:17:28 +01:00
|
|
|
// let (dma_cycles, _) = self.dma1.step(cycles, &mut self.sysbus);
|
|
|
|
// cycles += dma_cycles;
|
2019-07-06 23:33:54 +01:00
|
|
|
|
2019-07-11 16:17:28 +01:00
|
|
|
// let (dma_cycles, _) = self.dma2.step(cycles, &mut self.sysbus);
|
|
|
|
// cycles += dma_cycles;
|
2019-07-06 23:33:54 +01:00
|
|
|
|
2019-07-11 16:17:28 +01:00
|
|
|
// let (dma_cycles, _) = self.dma3.step(cycles, &mut self.sysbus);
|
|
|
|
// cycles += dma_cycles;
|
2019-07-06 13:53:36 +01:00
|
|
|
|
2019-07-15 05:35:09 +01:00
|
|
|
/* let (_, irq) = */
|
2019-07-15 23:21:11 +01:00
|
|
|
self.gpu.step(cycles, &mut self.sysbus);
|
2019-07-15 05:35:09 +01:00
|
|
|
// if let Some(irq) = irq {
|
|
|
|
// self.request_irq(irq);
|
|
|
|
// }
|
2019-07-11 16:17:28 +01:00
|
|
|
// cycles += lcd_cycles;
|
2019-07-06 13:53:36 +01:00
|
|
|
|
2019-07-11 16:17:28 +01:00
|
|
|
Ok(executed_insn)
|
2019-07-06 13:53:36 +01:00
|
|
|
}
|
|
|
|
}
|