Start working on Interrupts.
it kinda works now, but needs testing. Former-commit-id: 8510314cce248a737d492d935cf5b48f86d920ed
This commit is contained in:
parent
66a484e3ae
commit
e962150aaf
|
@ -375,7 +375,7 @@ mod tests {
|
|||
let mut core = Core::new();
|
||||
|
||||
let bytes = vec![];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
// swi #0x1337
|
||||
let decoded = ArmInstruction::decode(0xef001337, 0).unwrap();
|
||||
|
@ -406,7 +406,7 @@ mod tests {
|
|||
core.pc = 0x20 + 8;
|
||||
|
||||
let bytes = vec![];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
core.exec_arm(&mut mem, decoded).unwrap();
|
||||
assert_eq!(core.did_pipeline_flush(), true);
|
||||
|
@ -429,7 +429,7 @@ mod tests {
|
|||
core.pc = 0x20 + 8;
|
||||
|
||||
let bytes = vec![];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
core.exec_arm(&mut mem, decoded).unwrap();
|
||||
assert_eq!(core.did_pipeline_flush(), true);
|
||||
|
@ -472,7 +472,7 @@ mod tests {
|
|||
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
core.exec_arm(&mut mem, decoded).unwrap();
|
||||
assert_eq!(core.gpr[2], 0x1337);
|
||||
|
@ -513,7 +513,7 @@ mod tests {
|
|||
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
core.exec_arm(&mut mem, decoded).unwrap();
|
||||
assert_eq!(mem.read_32(0), 0xabababab);
|
||||
|
@ -538,7 +538,7 @@ mod tests {
|
|||
/* c: */ 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
/* 10: */ 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
assert_ne!(mem.read_32(core.get_reg(REG_SP) + 0x10), 0x12345678);
|
||||
core.exec_arm(&mut mem, decoded).unwrap();
|
||||
|
|
|
@ -36,11 +36,12 @@ impl Core {
|
|||
let new_mode = CpuMode::from(e);
|
||||
if self.verbose {
|
||||
println!(
|
||||
"{}: {:?}, pc: {:#x}, new_mode: {:?}",
|
||||
"{}: {:?}, pc: {:#x}, new_mode: {:?} old_mode: {:?}",
|
||||
"Exception".cyan(),
|
||||
e,
|
||||
self.pc,
|
||||
new_mode
|
||||
new_mode,
|
||||
self.cpsr.mode(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ mod tests {
|
|||
#[test]
|
||||
fn mov_low_reg() {
|
||||
let bytes = vec![];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
let mut core = Core::new();
|
||||
core.set_reg(0, 0);
|
||||
|
||||
|
@ -390,7 +390,7 @@ mod tests {
|
|||
/* 8: */ 0x00, 0x00, 0x00, 0x00,
|
||||
/* c: */ 0x78, 0x56, 0x34, 0x12,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
let mut core = Core::new();
|
||||
core.set_reg(0, 0);
|
||||
|
||||
|
@ -420,7 +420,7 @@ mod tests {
|
|||
/* 0ch: */ 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
/* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
assert_eq!(format!("{}", str_insn), "str\tr0, [r4, r1]");
|
||||
assert_eq!(format!("{}", ldr_insn), "ldrb\tr2, [r4, r1]");
|
||||
|
@ -440,7 +440,7 @@ mod tests {
|
|||
/* 08h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
/* 10h: */ 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice(), 0xffff_ffff);
|
||||
|
||||
core.gpr[4] = 0x12345678;
|
||||
core.gpr[3] = 0x2;
|
||||
|
|
|
@ -11,6 +11,8 @@ use super::EmuIoDev;
|
|||
use super::{GBAError, GBAResult};
|
||||
use crate::backend::*;
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
|
||||
pub struct GameBoyAdvance {
|
||||
backend: Box<EmulatorBackend>,
|
||||
pub cpu: Core,
|
||||
|
@ -86,23 +88,27 @@ impl GameBoyAdvance {
|
|||
let previous_cycles = self.cpu.cycles;
|
||||
self.cpu.step(&mut self.sysbus).unwrap();
|
||||
let cycles = self.cpu.cycles - previous_cycles;
|
||||
self.gpu.step(cycles, &mut self.sysbus);
|
||||
let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
|
||||
if let Some(irq) = irq {
|
||||
self.request_irq(irq);
|
||||
}
|
||||
}
|
||||
|
||||
fn interrupts_disabled(&self) -> bool {
|
||||
self.sysbus.ioregs.read_reg(REG_IME) & 1 == 0
|
||||
self.cpu.cpsr.irq_disabled() | (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);
|
||||
// }
|
||||
if self.interrupts_disabled() {
|
||||
return;
|
||||
}
|
||||
let irq_bit_index = irq as usize;
|
||||
let reg_ie = self.sysbus.ioregs.read_reg(REG_IE);
|
||||
if reg_ie.bit(irq_bit_index) {
|
||||
self.sysbus.ioregs.write_reg(REG_IF, (1 << irq_bit_index) as u16);
|
||||
println!("entering {:?}", irq);
|
||||
self.cpu.exception(Exception::Irq);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self) -> GBAResult<DecodedInstruction> {
|
||||
|
@ -125,12 +131,10 @@ impl GameBoyAdvance {
|
|||
// let (dma_cycles, _) = self.dma3.step(cycles, &mut self.sysbus);
|
||||
// cycles += dma_cycles;
|
||||
|
||||
/* let (_, irq) = */
|
||||
self.gpu.step(cycles, &mut self.sysbus);
|
||||
// if let Some(irq) = irq {
|
||||
// self.request_irq(irq);
|
||||
// }
|
||||
// cycles += lcd_cycles;
|
||||
let (_, irq) = self.gpu.step(cycles, &mut self.sysbus);
|
||||
if let Some(irq) = irq {
|
||||
self.request_irq(irq);
|
||||
}
|
||||
|
||||
Ok(executed_insn)
|
||||
}
|
||||
|
|
|
@ -9,20 +9,32 @@ use super::arm7tdmi::Addr;
|
|||
|
||||
const VIDEO_RAM_SIZE: usize = 128 * 1024;
|
||||
const WORK_RAM_SIZE: usize = 256 * 1024;
|
||||
const INTERNAL_RAM: usize = 32 * 1024;
|
||||
const INTERNAL_RAM_SIZE: usize = 32 * 1024;
|
||||
const PALETTE_RAM_SIZE: usize = 1 * 1024;
|
||||
const OAM_SIZE: usize = 1 * 1024;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BoxedMemory(Box<[u8]>, WaitState);
|
||||
|
||||
impl BoxedMemory {
|
||||
pub fn new(boxed_slice: Box<[u8]>) -> BoxedMemory {
|
||||
BoxedMemory(boxed_slice, Default::default())
|
||||
pub struct BoxedMemory {
|
||||
mem: Box<[u8]>,
|
||||
ws: WaitState,
|
||||
mask: u32,
|
||||
}
|
||||
|
||||
pub fn new_with_waitstate(boxed_slice: Box<[u8]>, ws: WaitState) -> BoxedMemory {
|
||||
BoxedMemory(boxed_slice, ws)
|
||||
impl BoxedMemory {
|
||||
pub fn new(boxed_slice: Box<[u8]>, mask: u32) -> BoxedMemory {
|
||||
BoxedMemory {
|
||||
mem: boxed_slice,
|
||||
mask: mask,
|
||||
ws: WaitState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_waitstate(boxed_slice: Box<[u8]>, mask: u32, ws: WaitState) -> BoxedMemory {
|
||||
BoxedMemory {
|
||||
mem: boxed_slice,
|
||||
mask: mask,
|
||||
ws: ws,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,50 +63,52 @@ impl Default for WaitState {
|
|||
|
||||
impl Bus for BoxedMemory {
|
||||
fn read_32(&self, addr: Addr) -> u32 {
|
||||
(&self.0[addr as usize..])
|
||||
(&self.mem[(addr & self.mask) as usize..])
|
||||
.read_u32::<LittleEndian>()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn read_16(&self, addr: Addr) -> u16 {
|
||||
(&self.0[addr as usize..])
|
||||
(&self.mem[(addr & self.mask) as usize..])
|
||||
.read_u16::<LittleEndian>()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn read_8(&self, addr: Addr) -> u8 {
|
||||
(&self.0[addr as usize..])[0]
|
||||
(&self.mem[(addr & self.mask) as usize..])[0]
|
||||
}
|
||||
|
||||
fn write_32(&mut self, addr: Addr, value: u32) {
|
||||
(&mut self.0[addr as usize..])
|
||||
(&mut self.mem[(addr & self.mask) as usize..])
|
||||
.write_u32::<LittleEndian>(value)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn write_16(&mut self, addr: Addr, value: u16) {
|
||||
(&mut self.0[addr as usize..])
|
||||
(&mut self.mem[(addr & self.mask) as usize..])
|
||||
.write_u16::<LittleEndian>(value)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn write_8(&mut self, addr: Addr, value: u8) {
|
||||
(&mut self.0[addr as usize..]).write_u8(value).unwrap()
|
||||
(&mut self.mem[(addr & self.mask) as usize..])
|
||||
.write_u8(value)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_bytes(&self, addr: Addr) -> &[u8] {
|
||||
&self.0[addr as usize..]
|
||||
&self.mem[(addr & self.mask) as usize..]
|
||||
}
|
||||
|
||||
fn get_bytes_mut(&mut self, addr: Addr) -> &mut [u8] {
|
||||
&mut self.0[addr as usize..]
|
||||
&mut self.mem[(addr & self.mask) as usize..]
|
||||
}
|
||||
|
||||
fn get_cycles(&self, _addr: Addr, access: MemoryAccess) -> usize {
|
||||
match access.1 {
|
||||
MemoryAccessWidth::MemoryAccess8 => self.1.access8,
|
||||
MemoryAccessWidth::MemoryAccess16 => self.1.access16,
|
||||
MemoryAccessWidth::MemoryAccess32 => self.1.access32,
|
||||
MemoryAccessWidth::MemoryAccess8 => self.ws.access8,
|
||||
MemoryAccessWidth::MemoryAccess16 => self.ws.access16,
|
||||
MemoryAccessWidth::MemoryAccess32 => self.ws.access32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,22 +165,28 @@ pub struct SysBus {
|
|||
impl SysBus {
|
||||
pub fn new(bios_rom: Vec<u8>, gamepak: Cartridge) -> SysBus {
|
||||
SysBus {
|
||||
bios: BoxedMemory::new(bios_rom.into_boxed_slice()),
|
||||
bios: BoxedMemory::new(bios_rom.into_boxed_slice(), 0xff_ffff),
|
||||
onboard_work_ram: BoxedMemory::new_with_waitstate(
|
||||
vec![0; WORK_RAM_SIZE].into_boxed_slice(),
|
||||
(WORK_RAM_SIZE as u32) - 1,
|
||||
WaitState::new(3, 3, 6),
|
||||
),
|
||||
internal_work_ram: BoxedMemory::new(vec![0; INTERNAL_RAM].into_boxed_slice()),
|
||||
internal_work_ram: BoxedMemory::new(
|
||||
vec![0; INTERNAL_RAM_SIZE].into_boxed_slice(),
|
||||
0x7fff,
|
||||
),
|
||||
ioregs: IoRegs::default(),
|
||||
palette_ram: BoxedMemory::new_with_waitstate(
|
||||
vec![0; PALETTE_RAM_SIZE].into_boxed_slice(),
|
||||
(PALETTE_RAM_SIZE as u32) - 1,
|
||||
WaitState::new(1, 1, 2),
|
||||
),
|
||||
vram: BoxedMemory::new_with_waitstate(
|
||||
vec![0; VIDEO_RAM_SIZE].into_boxed_slice(),
|
||||
(VIDEO_RAM_SIZE as u32) - 1,
|
||||
WaitState::new(1, 1, 2),
|
||||
),
|
||||
oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice()),
|
||||
oam: BoxedMemory::new(vec![0; OAM_SIZE].into_boxed_slice(), (OAM_SIZE as u32) - 1),
|
||||
gamepak: gamepak,
|
||||
dummy: DummyBus([0; 4]),
|
||||
}
|
||||
|
@ -175,11 +195,11 @@ impl SysBus {
|
|||
fn map(&self, addr: Addr) -> &Bus {
|
||||
match addr as usize {
|
||||
0x0000_0000...0x0000_3fff => &self.bios,
|
||||
0x0200_0000...0x0203_ffff => &self.onboard_work_ram,
|
||||
0x0300_0000...0x0300_7fff => &self.internal_work_ram,
|
||||
0x0200_0000...0x02ff_ffff => &self.onboard_work_ram,
|
||||
0x0300_0000...0x03ff_ffff => &self.internal_work_ram,
|
||||
0x0400_0000...0x0400_03fe => &self.ioregs,
|
||||
0x0500_0000...0x0500_03ff => &self.palette_ram,
|
||||
0x0600_0000...0x0601_7fff => &self.vram,
|
||||
0x0500_0000...0x05ff_ffff => &self.palette_ram,
|
||||
0x0600_0000...0x06ff_ffff => &self.vram,
|
||||
0x0700_0000...0x0700_03ff => &self.oam,
|
||||
0x0800_0000...0x09ff_ffff => &self.gamepak,
|
||||
_ => &self.dummy,
|
||||
|
@ -190,11 +210,11 @@ impl SysBus {
|
|||
fn map_mut(&mut self, addr: Addr) -> &mut Bus {
|
||||
match addr as usize {
|
||||
0x0000_0000...0x0000_3fff => &mut self.bios,
|
||||
0x0200_0000...0x0203_ffff => &mut self.onboard_work_ram,
|
||||
0x0300_0000...0x0300_7fff => &mut self.internal_work_ram,
|
||||
0x0200_0000...0x02ff_ffff => &mut self.onboard_work_ram,
|
||||
0x0300_0000...0x03ff_ffff => &mut self.internal_work_ram,
|
||||
0x0400_0000...0x0400_03fe => &mut self.ioregs,
|
||||
0x0500_0000...0x0500_03ff => &mut self.palette_ram,
|
||||
0x0600_0000...0x0601_7fff => &mut self.vram,
|
||||
0x0500_0000...0x05ff_ffff => &mut self.palette_ram,
|
||||
0x0600_0000...0x06ff_ffff => &mut self.vram,
|
||||
0x0700_0000...0x0700_03ff => &mut self.oam,
|
||||
0x0800_0000...0x09ff_ffff => &mut self.gamepak,
|
||||
_ => &mut self.dummy,
|
||||
|
|
Reference in a new issue