From 6b225d776d0c70131e5baefd96a0800f0638da92 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Mon, 1 Jul 2019 17:45:29 +0300 Subject: [PATCH] Implement all memory mappings. Reformat many files. Former-commit-id: c0a62b610e62d2db2a4daf4aeef40068820daa52 --- src/arm7tdmi/arm/display.rs | 2 +- src/arm7tdmi/arm/exec.rs | 65 +++++++++---- src/arm7tdmi/bus.rs | 50 +++++++--- src/arm7tdmi/cpu.rs | 12 +-- src/arm7tdmi/mod.rs | 4 +- src/bin/cli.yml | 8 +- src/bin/main.rs | 11 +-- src/debugger/command.rs | 28 ++---- src/debugger/mod.rs | 2 +- src/sysbus.rs | 181 +++++++++++++++++++++--------------- src/util.rs | 2 +- 11 files changed, 219 insertions(+), 146 deletions(-) diff --git a/src/arm7tdmi/arm/display.rs b/src/arm7tdmi/arm/display.rs index 4531fe2..97fa952 100644 --- a/src/arm7tdmi/arm/display.rs +++ b/src/arm7tdmi/arm/display.rs @@ -1,10 +1,10 @@ use std::fmt; -use crate::arm7tdmi::{Addr, reg_string, REG_PC}; use super::{ ArmCond, ArmHalfwordTransferType, ArmInstruction, ArmInstructionFormat, ArmOpCode, ArmRegisterShift, ArmShiftType, ArmShiftedValue, }; +use crate::arm7tdmi::{reg_string, Addr, REG_PC}; impl fmt::Display for ArmCond { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/arm7tdmi/arm/exec.rs b/src/arm7tdmi/arm/exec.rs index 8adb164..74a07a2 100644 --- a/src/arm7tdmi/arm/exec.rs +++ b/src/arm7tdmi/arm/exec.rs @@ -1,8 +1,8 @@ use crate::bit::BitIndex; +use crate::arm7tdmi::bus::{Bus, MemoryAccess, MemoryAccessType::*, MemoryAccessWidth::*}; use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction}; use crate::arm7tdmi::exception::Exception; -use crate::arm7tdmi::bus::{Bus, MemoryAccess, MemoryAccessType::*, MemoryAccessWidth::*}; use crate::arm7tdmi::{Addr, CpuError, CpuInstruction, CpuResult, CpuState, REG_PC}; use crate::sysbus::SysBus; @@ -15,7 +15,11 @@ use super::{ impl Core { pub fn exec_arm(&mut self, sysbus: &mut SysBus, insn: ArmInstruction) -> CpuExecResult { if !self.check_arm_cond(insn.cond) { - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, Seq + MemoryAccess32); + self.add_cycles( + insn.pc + (self.word_size() as u32), + sysbus, + Seq + MemoryAccess32, + ); self.add_cycle(); return Ok(CpuPipelineAction::IncPC); } @@ -40,7 +44,7 @@ impl Core { if insn.link_flag() { self.set_reg(14, self.pc & !0b1); } - + // +1N self.add_cycles(self.pc, sysbus, NonSeq + MemoryAccess32); @@ -48,7 +52,11 @@ impl Core { // +2S self.add_cycles(self.pc, sysbus, Seq + MemoryAccess32); - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, Seq + MemoryAccess32); + self.add_cycles( + self.pc + (self.word_size() as u32), + sysbus, + Seq + MemoryAccess32, + ); Ok(CpuPipelineAction::Flush) } @@ -68,12 +76,16 @@ impl Core { // +1N self.add_cycles(self.pc, sysbus, NonSeq + MemoryAccess32); - + self.pc = rn & !1; // +2S self.add_cycles(self.pc, sysbus, Seq + MemoryAccess32); - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, Seq + MemoryAccess32); + self.add_cycles( + self.pc + (self.word_size() as u32), + sysbus, + Seq + MemoryAccess32, + ); Ok(CpuPipelineAction::Flush) } @@ -159,7 +171,7 @@ impl Core { } /// Logical/Arithmetic ALU operations - /// + /// /// Cycles: 1S+x+y (from GBATEK) /// Add x=1I cycles if Op2 shifted-by-register. Add y=1S+1N cycles if Rd=R15. fn exec_data_processing( @@ -208,7 +220,11 @@ impl Core { } // +1S - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, Seq + MemoryAccess32); + self.add_cycles( + self.pc + (self.word_size() as u32), + sysbus, + Seq + MemoryAccess32, + ); Ok(pipeline_action) } @@ -219,12 +235,16 @@ impl Core { ArmShiftedValue::ShiftedRegister { reg, shift, - added: Some(added) + added: Some(added), } => { let abs = self.register_shift(reg, shift).unwrap(); - if added { abs } else { -abs } + if added { + abs + } else { + -abs + } } - _ => panic!("bad barrel shift") + _ => panic!("bad barrel shift"), } } @@ -240,7 +260,6 @@ impl Core { sysbus: &mut SysBus, insn: ArmInstruction, ) -> CpuResult { - if insn.write_back_flag() && insn.rd() == insn.rn() { return Err(CpuError::IllegalInstruction); } @@ -258,7 +277,7 @@ impl Core { let effective_addr = (addr as i32).wrapping_add(offset) as Addr; addr = if insn.pre_index_flag() { effective_addr - } else { + } else { addr }; @@ -273,8 +292,12 @@ impl Core { sysbus.read_32(addr) }; // +1S - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, Seq + MemoryAccess32); - + self.add_cycles( + self.pc + (self.word_size() as u32), + sysbus, + Seq + MemoryAccess32, + ); + self.set_reg(insn.rd(), data); // +1I @@ -284,7 +307,11 @@ impl Core { // +1S self.add_cycles(self.pc, sysbus, Seq + MemoryAccess32); // +1N - self.add_cycles(self.pc + (self.word_size() as u32), sysbus, NonSeq + MemoryAccess32); + self.add_cycles( + self.pc + (self.word_size() as u32), + sysbus, + NonSeq + MemoryAccess32, + ); pipeline_action = CpuPipelineAction::Flush; } } else { @@ -293,11 +320,11 @@ impl Core { if insn.transfer_size() == 1 { // +1N self.add_cycles(dest, sysbus, NonSeq + MemoryAccess8); - sysbus.write_8(addr, value as u8); + sysbus.write_8(addr, value as u8).expect("bus error"); } else { // +1N self.add_cycles(dest, sysbus, NonSeq + MemoryAccess32); - sysbus.write_32(addr, value); + sysbus.write_32(addr, value).expect("bus error"); }; } @@ -305,6 +332,6 @@ impl Core { self.set_reg(insn.rn(), effective_addr as u32) } - Ok(CpuPipelineAction::IncPC) + Ok(pipeline_action) } } diff --git a/src/arm7tdmi/bus.rs b/src/arm7tdmi/bus.rs index 260e9bd..7f0427b 100644 --- a/src/arm7tdmi/bus.rs +++ b/src/arm7tdmi/bus.rs @@ -1,19 +1,20 @@ +use super::Addr; use std::io; use std::ops::Add; -use super::Addr; + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; pub enum MemoryAccessType { NonSeq, - Seq + Seq, } pub enum MemoryAccessWidth { MemoryAccess8, MemoryAccess16, - MemoryAccess32 + MemoryAccess32, } - impl Add for MemoryAccessType { type Output = MemoryAccess; @@ -22,17 +23,40 @@ impl Add for MemoryAccessType { } } -pub struct MemoryAccess(MemoryAccessType, MemoryAccessWidth); +pub struct MemoryAccess(pub MemoryAccessType, pub MemoryAccessWidth); pub trait Bus { - fn read_32(&self, addr: Addr) -> u32; - fn read_16(&self, addr: Addr) -> u16; - fn read_8(&self, addr: Addr) -> u8; - fn write_32(&mut self, addr: Addr, value: u32) -> Result<(), io::Error>; - fn write_16(&mut self, addr: Addr, value: u16) -> Result<(), io::Error>; - fn write_8(&mut self, addr: Addr, value: u8) -> Result<(), io::Error>; + fn read_32(&self, addr: Addr) -> u32 { + self.get_bytes(addr, 4).read_u32::().unwrap() + } + + fn read_16(&self, addr: Addr) -> u16 { + self.get_bytes(addr, 2).read_u16::().unwrap() + } + + fn read_8(&self, addr: Addr) -> u8 { + self.get_bytes(addr, 1)[0] + } + + fn write_32(&mut self, addr: Addr, value: u32) -> Result<(), io::Error> { + self.get_bytes_mut(addr, 4).write_u32::(value) + } + + fn write_16(&mut self, addr: Addr, value: u16) -> Result<(), io::Error> { + self.get_bytes_mut(addr, 2).write_u16::(value) + } + + fn write_8(&mut self, addr: Addr, value: u8) -> Result<(), io::Error> { + self.get_bytes_mut(addr, 1).write_u8(value) + } + /// Return a slice of bytes + /// Will panic if requested range is out of bounds + fn get_bytes(&self, addr: Addr, len: usize) -> &[u8]; + + /// Return a mutable slice of bytes + /// Will panic if requested range is out of bounds + fn get_bytes_mut(&mut self, addr: Addr, len: usize) -> &mut [u8]; - fn get_bytes(&self, addr: Addr, size: usize) -> Option<&[u8]>; /// returns the number of cycles needed for this memory access fn get_cycles(&self, addr: Addr, access: MemoryAccess) -> usize; -} \ No newline at end of file +} diff --git a/src/arm7tdmi/cpu.rs b/src/arm7tdmi/cpu.rs index 62da056..e61c992 100644 --- a/src/arm7tdmi/cpu.rs +++ b/src/arm7tdmi/cpu.rs @@ -1,6 +1,6 @@ -use std::ops::Add; use std::convert::TryFrom; use std::fmt; +use std::ops::Add; use ansi_term::{Colour, Style}; @@ -8,10 +8,10 @@ use crate::sysbus::SysBus; pub use super::exception::Exception; use super::{ - CpuState, CpuMode, reg_string, CpuResult, Addr, - psr::RegPSR, + arm::*, bus::{Bus, MemoryAccess, MemoryAccessType::*, MemoryAccessWidth::*}, - arm::* + psr::RegPSR, + reg_string, Addr, CpuMode, CpuResult, CpuState, }; #[derive(Debug, Default)] @@ -198,9 +198,7 @@ impl Core { let action = self.exec_arm(sysbus, d)?; Ok((Some(d), action)) } - None => { - Ok((None, CpuPipelineAction::IncPC)) - }, + None => Ok((None, CpuPipelineAction::IncPC)), }; self.pipeline.fetched = Some((self.pc, new_fetched)); diff --git a/src/arm7tdmi/mod.rs b/src/arm7tdmi/mod.rs index 89f22bf..c86b58c 100644 --- a/src/arm7tdmi/mod.rs +++ b/src/arm7tdmi/mod.rs @@ -1,14 +1,14 @@ use std::fmt; pub mod arm; -use arm::{ArmInstruction, ArmDecodeError}; +use arm::{ArmDecodeError, ArmInstruction}; pub mod cpu; +pub use cpu::*; pub mod bus; mod exception; mod psr; - pub const REG_PC: usize = 15; pub const REG_LR: usize = 14; pub const REG_SP: usize = 13; diff --git a/src/bin/cli.yml b/src/bin/cli.yml index edf2229..e69866b 100644 --- a/src/bin/cli.yml +++ b/src/bin/cli.yml @@ -5,11 +5,17 @@ subcommands: - debug: about: debug the bios with the arm core emulation args: - - BIOS: + - bios: help: Sets the bios file to use required: false default_value: gba_bios.bin index: 1 + - game_rom: + short: g + long: game-rom + takes_value: true + help: Sets the game-rom file to use + required: true - disass: about: disassemble an arm binary file args: diff --git a/src/bin/main.rs b/src/bin/main.rs index 1826767..3704a60 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -8,9 +8,9 @@ use clap::{App, ArgMatches}; extern crate rustboyadvance_ng; use rustboyadvance_ng::arm7tdmi; -use rustboyadvance_ng::sysbus::SysBus; use rustboyadvance_ng::debugger::{Debugger, DebuggerError}; use rustboyadvance_ng::disass::Disassembler; +use rustboyadvance_ng::sysbus::SysBus; use rustboyadvance_ng::util::read_bin_file; #[derive(Debug)] @@ -18,7 +18,7 @@ pub enum GBAError { IO(io::Error), ArmDecodeError(arm7tdmi::arm::ArmDecodeError), CpuError(arm7tdmi::CpuError), - DebuggerError(DebuggerError) + DebuggerError(DebuggerError), } pub type GBAResult = Result; @@ -59,11 +59,10 @@ fn run_disass(matches: &ArgMatches) -> GBAResult<()> { } fn run_debug(matches: &ArgMatches) -> GBAResult<()> { - let gba_bios_path = matches.value_of("BIOS").unwrap_or_default(); - println!("Loading BIOS: {}", gba_bios_path); - let bios_bin = read_bin_file(gba_bios_path)?; + let bios_bin = read_bin_file(matches.value_of("bios").unwrap_or_default())?; + let rom_bin = read_bin_file(matches.value_of("game_rom").unwrap())?; - let sysbus = SysBus::new(bios_bin); + let sysbus = SysBus::new(bios_bin, rom_bin); let mut core = arm7tdmi::cpu::Core::new(); core.reset(); core.set_verbose(true); diff --git a/src/debugger/command.rs b/src/debugger/command.rs index c5a844e..7506483 100644 --- a/src/debugger/command.rs +++ b/src/debugger/command.rs @@ -1,5 +1,5 @@ -use crate::arm7tdmi::{reg_string, REG_PC}; use crate::arm7tdmi::bus::Bus; +use crate::arm7tdmi::{reg_string, REG_PC}; use crate::debugger::Debugger; use crate::disass::Disassembler; @@ -59,11 +59,11 @@ impl Command { match debugger.cpu.step_debugger(&mut debugger.sysbus) { Ok(insn) => { println!( - "@0x{:08x}:\n\t{}", - insn.pc, - Colour::Yellow.italic().paint(format!("{} ", insn)) - ); - }, + "@0x{:08x}:\n\t{}", + insn.pc, + Colour::Yellow.italic().paint(format!("{} ", insn)) + ); + } Err(e) => { println!("{}: {}", "cpu encountered an error".red(), e); println!("cpu: {:x?}", debugger.cpu); @@ -72,23 +72,11 @@ impl Command { }; }, HexDump(addr, nbytes) => { - let bytes = match debugger.sysbus.get_bytes(addr, nbytes) { - Some(bytes) => bytes, - None => { - println!("requested content out of bounds"); - return; - } - }; + let bytes = debugger.sysbus.get_bytes(addr, nbytes); hexdump::hexdump(bytes); } Disass(addr, n) => { - let bytes = match debugger.sysbus.get_bytes(addr, 4 * n) { - Some(bytes) => bytes, - None => { - println!("requested content out of bounds"); - return; - } - }; + let bytes = debugger.sysbus.get_bytes(addr, 4 * n); let disass = Disassembler::new(addr, bytes); for (_, line) in disass { println!("{}", line) diff --git a/src/debugger/mod.rs b/src/debugger/mod.rs index 29f19b2..e1720d3 100644 --- a/src/debugger/mod.rs +++ b/src/debugger/mod.rs @@ -171,7 +171,7 @@ impl Debugger { if let Some(Command::Disass(addr, n)) = self.previous_command { (addr + (4 * n as u32), 10) } else { - (self.cpu.get_reg(15), 10) + (self.cpu.get_next_pc(), 10) } } _ => { diff --git a/src/sysbus.rs b/src/sysbus.rs index 7c67fde..f2b4c9e 100644 --- a/src/sysbus.rs +++ b/src/sysbus.rs @@ -1,132 +1,163 @@ use std::io; +use super::arm7tdmi::bus::{Bus, MemoryAccess, MemoryAccessWidth}; use super::arm7tdmi::Addr; -use super::arm7tdmi::bus::{Bus, MemoryAccess, MemoryAccessType, MemoryAccessWidth}; - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; const VIDEO_RAM_SIZE: usize = 128 * 1024; const WORK_RAM_SIZE: usize = 256 * 1024; const INTERNAL_RAM: usize = 32 * 1024; -const PALETTE_AM_SIZE: usize = 1 * 1024; +const PALETTE_RAM_SIZE: usize = 1 * 1024; const OAM_SIZE: usize = 1 * 1024; -const BIOS_SIZE: usize = 16 * 1024; -const GAMEPAK_ROM_SIZE: usize = 32 * 1024 * 1024; #[derive(Debug)] -struct BiosROM(Vec); +struct BoxedMemory(Box<[u8]>, WaitState); -impl Bus for BiosROM { - fn read_32(&self, addr: Addr) -> u32 { - let addr = addr as usize; - (&self.0[addr..addr + 4]) - .read_u32::() - .unwrap() - } +#[derive(Debug)] +struct WaitState { + access8: usize, + access16: usize, + access32: usize, +} - fn read_16(&self, addr: Addr) -> u16 { - let addr = addr as usize; - (&self.0[addr..addr + 4]) - .read_u16::() - .unwrap() - } - - fn read_8(&self, addr: Addr) -> u8 { - self.0[addr as usize] - } - - fn write_32(&mut self, addr: Addr, value: u32) -> Result<(), io::Error> { - let mut wrt = io::Cursor::new(&mut self.0); - wrt.set_position(addr as u64); - wrt.write_u32::(value) - } - - fn write_16(&mut self, addr: Addr, value: u16) -> Result<(), io::Error> { - let mut wrt = io::Cursor::new(&mut self.0); - wrt.set_position(addr as u64); - wrt.write_u16::(value) - } - - fn write_8(&mut self, addr: Addr, value: u8) -> Result<(), io::Error> { - let mut wrt = io::Cursor::new(&mut self.0); - wrt.write_u8(value) - } - - fn get_bytes(&self, addr: Addr, size: usize) -> Option<&[u8]> { - let addr = addr as usize; - if addr + size > self.0.len() { - None - } else { - Some(&self.0[addr..addr + size]) +impl WaitState { + fn new(access8: usize, access16: usize, access32: usize) -> WaitState { + WaitState { + access8, + access16, + access32, } } - - fn get_cycles(&self, _addr: Addr, _access: MemoryAccess) -> usize { - 1 - } } -#[derive(Debug)] -enum SysBusDevice { - BiosROM(BiosROM) +impl Default for WaitState { + fn default() -> WaitState { + WaitState::new(1, 1, 1) + } +} + +impl Bus for BoxedMemory { + fn get_bytes(&self, addr: Addr, size: usize) -> &[u8] { + let addr = addr as usize; + &self.0[addr..addr + size] + } + + fn get_bytes_mut(&mut self, addr: Addr, size: usize) -> &mut [u8] { + let addr = addr as usize; + &mut self.0[addr..addr + size] + } + + 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, + } + } } #[derive(Debug)] pub struct SysBus { - bios: BiosROM + bios: BoxedMemory, + onboard_work_ram: BoxedMemory, + internal_work_ram: BoxedMemory, + /// Currently model the IOMem as regular buffer, later make it into something more sophisticated. + ioregs: BoxedMemory, + palette_ram: BoxedMemory, + vram: BoxedMemory, + oam: BoxedMemory, + gamepak_flashrom: BoxedMemory, } impl SysBus { - pub fn new(bios_rom: Vec) -> SysBus { - SysBus { bios: BiosROM(bios_rom) } - } - - fn map(&self, addr: Addr) -> & impl Bus { - match addr as usize { - 0...BIOS_SIZE => &self.bios, - _ => panic!("unmapped address") + pub fn new(bios_rom: Vec, game_rom: Vec) -> SysBus { + SysBus { + bios: BoxedMemory(bios_rom.into_boxed_slice(), Default::default()), + onboard_work_ram: BoxedMemory( + vec![0; WORK_RAM_SIZE].into_boxed_slice(), + Default::default(), + ), + internal_work_ram: BoxedMemory( + vec![0; INTERNAL_RAM].into_boxed_slice(), + Default::default(), + ), + ioregs: BoxedMemory(vec![0; 1024].into_boxed_slice(), Default::default()), + palette_ram: BoxedMemory( + vec![0; PALETTE_RAM_SIZE].into_boxed_slice(), + WaitState::new(1, 1, 2), + ), + vram: BoxedMemory( + vec![0; VIDEO_RAM_SIZE].into_boxed_slice(), + WaitState::new(1, 1, 2), + ), + oam: BoxedMemory(vec![0; OAM_SIZE].into_boxed_slice(), Default::default()), + gamepak_flashrom: BoxedMemory(game_rom.into_boxed_slice(), WaitState::new(5, 5, 8)), } } + fn map(&self, addr: Addr) -> &impl 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, + 0x0400_0000...0x0400_03fe => &self.ioregs, + 0x0500_0000...0x0500_03ff => &self.palette_ram, + 0x0600_0000...0x0601_7fff => &self.vram, + 0x0700_0000...0x0700_03ff => &self.oam, + 0x0800_0000...0x09ff_ffff => &self.gamepak_flashrom, + _ => panic!("unmapped address @0x{:08x}", addr), + } + } + + /// TODO proc-macro for generating this function fn map_mut(&mut self, addr: Addr) -> &mut impl Bus { match addr as usize { - 0...BIOS_SIZE => &mut self.bios, - _ => panic!("unmapped address") + 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, + 0x0400_0000...0x0400_03fe => &mut self.ioregs, + 0x0500_0000...0x0500_03ff => &mut self.palette_ram, + 0x0600_0000...0x0601_7fff => &mut self.vram, + 0x0700_0000...0x0700_03ff => &mut self.oam, + 0x0800_0000...0x09ff_ffff => &mut self.gamepak_flashrom, + _ => panic!("unmapped address @0x{:08x}", addr), } } } impl Bus for SysBus { fn read_32(&self, addr: Addr) -> u32 { - self.map(addr).read_32(addr) + self.map(addr).read_32(addr & 0xff_ffff) } fn read_16(&self, addr: Addr) -> u16 { - self.map(addr).read_16(addr) + self.map(addr).read_16(addr & 0xff_ffff) } fn read_8(&self, addr: Addr) -> u8 { - self.map(addr).read_8(addr) + self.map(addr).read_8(addr & 0xff_ffff) } fn write_32(&mut self, addr: Addr, value: u32) -> Result<(), io::Error> { - self.map_mut(addr).write_32(addr, value) + self.map_mut(addr).write_32(addr & 0xff_ffff, value) } fn write_16(&mut self, addr: Addr, value: u16) -> Result<(), io::Error> { - self.map_mut(addr).write_16(addr, value) + self.map_mut(addr).write_16(addr & 0xff_ffff, value) } fn write_8(&mut self, addr: Addr, value: u8) -> Result<(), io::Error> { - self.map_mut(addr).write_8(addr, value) + self.map_mut(addr).write_8(addr & 0xff_ffff, value) } + fn get_bytes(&self, addr: Addr, size: usize) -> &[u8] { + self.map(addr).get_bytes(addr & 0xff_ffff, size) + } - fn get_bytes(&self, addr: Addr, size: usize) -> Option<&[u8]> { - self.map(addr).get_bytes(addr, size) + fn get_bytes_mut(&mut self, addr: Addr, size: usize) -> &mut [u8] { + self.map_mut(addr).get_bytes_mut(addr & 0xff_ffff, size) } fn get_cycles(&self, addr: Addr, access: MemoryAccess) -> usize { - self.map(addr).get_cycles(addr, access) + self.map(addr).get_cycles(addr & 0xff_ffff, access) } } diff --git a/src/util.rs b/src/util.rs index 90f0ab8..6d169eb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -7,4 +7,4 @@ pub fn read_bin_file(filename: &str) -> io::Result> { let mut file = File::open(filename)?; file.read_to_end(&mut buf)?; Ok(buf) -} \ No newline at end of file +}