chore: Refactor into crates
Been wanting to do this for a long time. This does impose performance issues when building with the vanilla release profile, as cargo does not perform optimizations across crate boundary (we care mostly about inlining). so I added release-lto profile Also fixed some broken stuff I found across the project, meh Former-commit-id: 06d03263cc6245313f3ea22c715479ab6da7c4d4 Former-commit-id: f93abd10c67ea8a3b8072b47462be5eca4f3e02b
This commit is contained in:
parent
1535062e6c
commit
28fb9ffa70
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -69,6 +69,22 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arm7tdmi"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term 0.12.1",
|
||||||
|
"bit",
|
||||||
|
"byteorder",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"colored",
|
||||||
|
"enum-primitive-derive",
|
||||||
|
"num 0.2.1",
|
||||||
|
"num-traits 0.2.12",
|
||||||
|
"rustboyadvance-utils",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -1351,6 +1367,7 @@ name = "rustboyadvance-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.12.1",
|
"ansi_term 0.12.1",
|
||||||
|
"arm7tdmi",
|
||||||
"arrayvec 0.5.2",
|
"arrayvec 0.5.2",
|
||||||
"bincode",
|
"bincode",
|
||||||
"bit",
|
"bit",
|
||||||
|
@ -1371,14 +1388,13 @@ dependencies = [
|
||||||
"goblin",
|
"goblin",
|
||||||
"hex-literal",
|
"hex-literal",
|
||||||
"hexdump",
|
"hexdump",
|
||||||
"instant",
|
|
||||||
"lazy_static 1.4.0",
|
"lazy_static 1.4.0",
|
||||||
"log 0.4.11",
|
"log 0.4.11",
|
||||||
"memmem",
|
"memmem",
|
||||||
"nom",
|
"nom",
|
||||||
"num 0.2.1",
|
"num 0.2.1",
|
||||||
"num-traits 0.2.12",
|
"num-traits 0.2.12",
|
||||||
"ringbuf",
|
"rustboyadvance-utils",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
"serde",
|
"serde",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
@ -1433,11 +1449,20 @@ dependencies = [
|
||||||
"log 0.4.11",
|
"log 0.4.11",
|
||||||
"ringbuf",
|
"ringbuf",
|
||||||
"rustboyadvance-core",
|
"rustboyadvance-core",
|
||||||
|
"rustboyadvance-utils",
|
||||||
"sdl2 0.33.0",
|
"sdl2 0.33.0",
|
||||||
"spin_sleep",
|
"spin_sleep",
|
||||||
"winres",
|
"winres",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustboyadvance-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"ringbuf",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustboyadvance-wasm"
|
name = "rustboyadvance-wasm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"core",
|
"core",
|
||||||
|
"arm7tdmi",
|
||||||
|
"utils",
|
||||||
"platform/rustboyadvance-sdl2",
|
"platform/rustboyadvance-sdl2",
|
||||||
"platform/rustboyadvance-libretro",
|
"platform/rustboyadvance-libretro",
|
||||||
"platform/rustboyadvance-minifb",
|
"platform/rustboyadvance-minifb",
|
||||||
|
|
21
arm7tdmi/Cargo.toml
Normal file
21
arm7tdmi/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "arm7tdmi"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rustboyadvance-utils = {"path" = "../utils" }
|
||||||
|
bit = "^0.1"
|
||||||
|
cfg-if = "1.0.0"
|
||||||
|
serde = { version = "1.0.104", features = ["derive", "rc"] }
|
||||||
|
ansi_term = "0.12.1"
|
||||||
|
colored = "1.9"
|
||||||
|
byteorder = "1"
|
||||||
|
num = "0.2.1"
|
||||||
|
num-traits = "0.2"
|
||||||
|
enum-primitive-derive = "^0.1"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bit = "^0.1"
|
|
@ -1,3 +1,4 @@
|
||||||
|
/// This build script creates ARM_LUT and THUMB_LUT opcode lookup table used cpu.rs
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -6,7 +7,7 @@ use std::path::Path;
|
||||||
extern crate bit;
|
extern crate bit;
|
||||||
use bit::BitIndex;
|
use bit::BitIndex;
|
||||||
|
|
||||||
// copied and slightly adjusted from src/core/arm7tdmi/thumb/mod.rs
|
// copied and slightly adjusted from arm7tdmi/thumb/mod.rs
|
||||||
fn thumb_decode(i: u16) -> (&'static str, String) {
|
fn thumb_decode(i: u16) -> (&'static str, String) {
|
||||||
let offset5 = i.bit_range(6..11) as u8;
|
let offset5 = i.bit_range(6..11) as u8;
|
||||||
let load = i.bit(11);
|
let load = i.bit(11);
|
||||||
|
@ -180,7 +181,7 @@ trait BitAsInt<T: From<bool>>: BitIndex {
|
||||||
|
|
||||||
impl BitAsInt<u32> for u32 {}
|
impl BitAsInt<u32> for u32 {}
|
||||||
|
|
||||||
/// Returns a string representation of rustboyadvance_ng::core::arm7tdmi::arm::ArmFormat enum member
|
/// Returns a string representation of arm7tdmi::arm::ArmFormat enum member
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `i` - A 32bit ARM instruction
|
/// * `i` - A 32bit ARM instruction
|
||||||
///
|
///
|
||||||
|
@ -368,7 +369,7 @@ fn arm_decode(i: u32) -> (&'static str, String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
writeln!(file, "impl<I: MemoryInterface> Arm7tdmiCore<I> {{")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
" pub const THUMB_LUT: [ThumbInstructionInfo<I>; 1024] = ["
|
" pub const THUMB_LUT: [ThumbInstructionInfo<I>; 1024] = ["
|
||||||
|
@ -380,7 +381,7 @@ fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
file,
|
file,
|
||||||
" /* {:#x} */
|
" /* {:#x} */
|
||||||
ThumbInstructionInfo {{
|
ThumbInstructionInfo {{
|
||||||
handler_fn: Core::{},
|
handler_fn: Arm7tdmiCore::{},
|
||||||
#[cfg(feature = \"debugger\")]
|
#[cfg(feature = \"debugger\")]
|
||||||
fmt: ThumbFormat::{},
|
fmt: ThumbFormat::{},
|
||||||
}},",
|
}},",
|
||||||
|
@ -395,7 +396,7 @@ fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
writeln!(file, "impl<I: MemoryInterface> Arm7tdmiCore<I> {{")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
|
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
|
||||||
|
@ -406,7 +407,7 @@ fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
file,
|
file,
|
||||||
" /* {:#x} */
|
" /* {:#x} */
|
||||||
ArmInstructionInfo {{
|
ArmInstructionInfo {{
|
||||||
handler_fn: Core::{},
|
handler_fn: Arm7tdmiCore::{},
|
||||||
#[cfg(feature = \"debugger\")]
|
#[cfg(feature = \"debugger\")]
|
||||||
fmt: ArmFormat::{},
|
fmt: ArmFormat::{},
|
||||||
}} ,",
|
}} ,",
|
|
@ -1,7 +1,6 @@
|
||||||
use bit::BitIndex;
|
use bit::BitIndex;
|
||||||
|
|
||||||
use super::memory::MemoryInterface;
|
use crate::{memory::MemoryInterface, registers_consts::REG_PC, Arm7tdmiCore};
|
||||||
use super::{Core, REG_PC};
|
|
||||||
|
|
||||||
#[derive(Debug, Primitive, Eq, PartialEq)]
|
#[derive(Debug, Primitive, Eq, PartialEq)]
|
||||||
pub enum AluOpCode {
|
pub enum AluOpCode {
|
||||||
|
@ -110,7 +109,7 @@ impl BarrelShifterValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
pub fn lsl(&mut self, val: u32, amount: u32, carry: &mut bool) -> u32 {
|
pub fn lsl(&mut self, val: u32, amount: u32, carry: &mut bool) -> u32 {
|
||||||
match amount {
|
match amount {
|
||||||
0 => val,
|
0 => val,
|
|
@ -1,17 +1,19 @@
|
||||||
use crate::bit::BitIndex;
|
use crate::bit::BitIndex;
|
||||||
|
|
||||||
use super::super::alu::*;
|
use crate::{
|
||||||
use crate::arm7tdmi::psr::RegPSR;
|
alu::*,
|
||||||
use crate::arm7tdmi::CpuAction;
|
memory::{MemoryAccess, MemoryInterface},
|
||||||
use crate::arm7tdmi::{Addr, Core, CpuMode, CpuState, REG_LR, REG_PC};
|
psr::RegPSR,
|
||||||
|
registers_consts::{REG_LR, REG_PC},
|
||||||
|
Arm7tdmiCore, CpuAction, CpuMode, CpuState,
|
||||||
|
};
|
||||||
|
|
||||||
use super::super::memory::{MemoryAccess, MemoryInterface};
|
|
||||||
use MemoryAccess::*;
|
use MemoryAccess::*;
|
||||||
|
|
||||||
use super::ArmDecodeHelper;
|
use super::ArmDecodeHelper;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
pub fn arm_undefined(&mut self, insn: u32) -> CpuAction {
|
pub fn arm_undefined(&mut self, insn: u32) -> CpuAction {
|
||||||
panic!(
|
panic!(
|
||||||
"executing undefined arm instruction {:08x} at @{:08x}",
|
"executing undefined arm instruction {:08x} at @{:08x}",
|
|
@ -5,11 +5,12 @@ pub mod exec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::alu::*;
|
use super::alu::*;
|
||||||
use crate::arm7tdmi::{Addr, InstructionDecoder};
|
use super::memory::Addr;
|
||||||
|
use super::InstructionDecoder;
|
||||||
|
|
||||||
use crate::bit::BitIndex;
|
use bit::BitIndex;
|
||||||
use crate::byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use crate::num::FromPrimitive;
|
use num::FromPrimitive;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub use super::exception::Exception;
|
||||||
|
|
||||||
use super::{arm::ArmCond, psr::RegPSR, Addr, CpuMode, CpuState};
|
use super::{arm::ArmCond, psr::RegPSR, Addr, CpuMode, CpuState};
|
||||||
|
|
||||||
use crate::util::{Shared, WeakPointer};
|
use rustboyadvance_utils::{Shared, WeakPointer};
|
||||||
|
|
||||||
use super::memory::{MemoryAccess, MemoryInterface};
|
use super::memory::{MemoryAccess, MemoryInterface};
|
||||||
use MemoryAccess::*;
|
use MemoryAccess::*;
|
||||||
|
@ -19,14 +19,14 @@ use super::arm::ArmFormat;
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
||||||
pub struct ThumbInstructionInfo<I: MemoryInterface> {
|
pub struct ThumbInstructionInfo<I: MemoryInterface> {
|
||||||
pub handler_fn: fn(&mut Core<I>, insn: u16) -> CpuAction,
|
pub handler_fn: fn(&mut Arm7tdmiCore<I>, insn: u16) -> CpuAction,
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
pub fmt: ThumbFormat,
|
pub fmt: ThumbFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
||||||
pub struct ArmInstructionInfo<I: MemoryInterface> {
|
pub struct ArmInstructionInfo<I: MemoryInterface> {
|
||||||
pub handler_fn: fn(&mut Core<I>, insn: u32) -> CpuAction,
|
pub handler_fn: fn(&mut Arm7tdmiCore<I>, insn: u32) -> CpuAction,
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
pub fmt: ArmFormat,
|
pub fmt: ArmFormat,
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ impl Default for DebuggerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Core<I: MemoryInterface> {
|
pub struct Arm7tdmiCore<I: MemoryInterface> {
|
||||||
pub pc: u32,
|
pub pc: u32,
|
||||||
pub(super) bus: Shared<I>,
|
pub(super) bus: Shared<I>,
|
||||||
|
|
||||||
|
@ -121,10 +121,10 @@ pub struct Core<I: MemoryInterface> {
|
||||||
pub dbg: DebuggerState,
|
pub dbg: DebuggerState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
pub fn new(bus: Shared<I>) -> Core<I> {
|
pub fn new(bus: Shared<I>) -> Arm7tdmiCore<I> {
|
||||||
let cpsr = RegPSR::new(0x0000_00D3);
|
let cpsr = RegPSR::new(0x0000_00D3);
|
||||||
Core {
|
Arm7tdmiCore {
|
||||||
bus,
|
bus,
|
||||||
pc: 0,
|
pc: 0,
|
||||||
gpr: [0; 15],
|
gpr: [0; 15],
|
||||||
|
@ -139,12 +139,12 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn weak_ptr(&mut self) -> WeakPointer<Core<I>> {
|
pub fn weak_ptr(&mut self) -> WeakPointer<Arm7tdmiCore<I>> {
|
||||||
WeakPointer::new(self as *mut Core<I>)
|
WeakPointer::new(self as *mut Arm7tdmiCore<I>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_saved_state(bus: Shared<I>, state: SavedCpuState) -> Core<I> {
|
pub fn from_saved_state(bus: Shared<I>, state: SavedCpuState) -> Arm7tdmiCore<I> {
|
||||||
Core {
|
Arm7tdmiCore {
|
||||||
bus,
|
bus,
|
||||||
|
|
||||||
pc: state.pc,
|
pc: state.pc,
|
|
@ -1,5 +1,5 @@
|
||||||
use super::cpu::Core;
|
|
||||||
use super::memory::MemoryInterface;
|
use super::memory::MemoryInterface;
|
||||||
|
use super::Arm7tdmiCore;
|
||||||
use super::{CpuMode, CpuState};
|
use super::{CpuMode, CpuState};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
@ -16,7 +16,7 @@ pub enum Exception {
|
||||||
Fiq = 0x1c,
|
Fiq = 0x1c,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
pub fn exception(&mut self, e: Exception, lr: u32) {
|
pub fn exception(&mut self, e: Exception, lr: u32) {
|
||||||
use Exception::*;
|
use Exception::*;
|
||||||
let (new_mode, irq_disable, fiq_disable) = match e {
|
let (new_mode, irq_disable, fiq_disable) = match e {
|
|
@ -1,3 +1,12 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate enum_primitive_derive;
|
||||||
|
use bit;
|
||||||
|
use num;
|
||||||
|
use num_traits;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use num::Num;
|
use num::Num;
|
||||||
|
@ -14,16 +23,17 @@ pub use cpu::*;
|
||||||
pub mod alu;
|
pub mod alu;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub use alu::*;
|
pub use alu::*;
|
||||||
|
use memory::Addr;
|
||||||
pub mod exception;
|
pub mod exception;
|
||||||
pub mod psr;
|
pub mod psr;
|
||||||
pub use psr::*;
|
pub use psr::*;
|
||||||
pub mod disass;
|
pub mod disass;
|
||||||
|
|
||||||
|
pub mod registers_consts {
|
||||||
pub const REG_PC: usize = 15;
|
pub const REG_PC: usize = 15;
|
||||||
pub const REG_LR: usize = 14;
|
pub const REG_LR: usize = 14;
|
||||||
pub const REG_SP: usize = 13;
|
pub const REG_SP: usize = 13;
|
||||||
|
}
|
||||||
pub(self) use crate::Addr;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||||
pub enum DecodedInstruction {
|
pub enum DecodedInstruction {
|
|
@ -1,7 +1,8 @@
|
||||||
use super::cpu::Core;
|
use super::Arm7tdmiCore;
|
||||||
use super::Addr;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
pub type Addr = u32;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
||||||
pub enum MemoryAccess {
|
pub enum MemoryAccess {
|
||||||
NonSeq = 0,
|
NonSeq = 0,
|
||||||
|
@ -35,7 +36,7 @@ pub enum MemoryAccessWidth {
|
||||||
MemoryAccess32,
|
MemoryAccess32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait meant to abstract memory accesses and report the access type back to the user of the arm7tdmi::Core
|
/// A trait meant to abstract memory accesses and report the access type back to the user of the arm7tdmi::Arm7tdmiCore
|
||||||
///
|
///
|
||||||
/// struct Memory {
|
/// struct Memory {
|
||||||
/// data: [u8; 0x4000]
|
/// data: [u8; 0x4000]
|
||||||
|
@ -60,7 +61,7 @@ pub enum MemoryAccessWidth {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let mem = Shared::new(Memory { ... });
|
/// let mem = Shared::new(Memory { ... });
|
||||||
/// let cpu = arm7tdmi::Core::new(mem.clone())
|
/// let cpu = arm7tdmi::Arm7tdmiCore::new(mem.clone())
|
||||||
///
|
///
|
||||||
pub trait MemoryInterface {
|
pub trait MemoryInterface {
|
||||||
/// Read a byte
|
/// Read a byte
|
||||||
|
@ -80,7 +81,7 @@ pub trait MemoryInterface {
|
||||||
fn idle_cycle(&mut self);
|
fn idle_cycle(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: MemoryInterface> MemoryInterface for Core<I> {
|
impl<I: MemoryInterface> MemoryInterface for Arm7tdmiCore<I> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn load_8(&mut self, addr: u32, access: MemoryAccess) -> u8 {
|
fn load_8(&mut self, addr: u32, access: MemoryAccess) -> u8 {
|
||||||
self.bus.load_8(addr, access)
|
self.bus.load_8(addr, access)
|
||||||
|
@ -117,7 +118,7 @@ impl<I: MemoryInterface> MemoryInterface for Core<I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of memory access helpers
|
/// Implementation of memory access helpers
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn store_aligned_32(&mut self, addr: Addr, value: u32, access: MemoryAccess) {
|
pub(super) fn store_aligned_32(&mut self, addr: Addr, value: u32, access: MemoryAccess) {
|
||||||
self.store_32(addr & !0x3, value, access);
|
self.store_32(addr & !0x3, value, access);
|
|
@ -1,13 +1,17 @@
|
||||||
use crate::arm7tdmi::*;
|
use crate::{
|
||||||
|
exception::Exception,
|
||||||
|
memory::{MemoryAccess, MemoryInterface},
|
||||||
|
registers_consts::*,
|
||||||
|
Arm7tdmiCore, CpuAction,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::bit::BitIndex;
|
use bit::BitIndex;
|
||||||
|
|
||||||
use super::super::memory::{MemoryAccess, MemoryInterface};
|
|
||||||
use super::ThumbDecodeHelper;
|
use super::ThumbDecodeHelper;
|
||||||
use super::*;
|
use super::*;
|
||||||
use MemoryAccess::*;
|
use MemoryAccess::*;
|
||||||
|
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||||
/// Format 1
|
/// Format 1
|
||||||
/// Execution Time: 1S
|
/// Execution Time: 1S
|
||||||
pub(in super::super) fn exec_thumb_move_shifted_reg<const BS_OP: u8, const IMM: u8>(
|
pub(in super::super) fn exec_thumb_move_shifted_reg<const BS_OP: u8, const IMM: u8>(
|
|
@ -1,9 +1,10 @@
|
||||||
use super::alu::*;
|
use super::alu::*;
|
||||||
use super::arm::*;
|
use super::arm::*;
|
||||||
use super::{Addr, InstructionDecoder};
|
use super::memory::Addr;
|
||||||
use crate::bit::BitIndex;
|
use super::InstructionDecoder;
|
||||||
use crate::byteorder::{LittleEndian, ReadBytesExt};
|
use bit::BitIndex;
|
||||||
use crate::num::FromPrimitive;
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
use num::FromPrimitive;
|
||||||
|
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
pub mod disass;
|
pub mod disass;
|
|
@ -5,6 +5,8 @@ authors = ["Michel Heily <michelheily@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
arm7tdmi = { "path" = "../arm7tdmi" }
|
||||||
|
rustboyadvance-utils = { "path" = "../utils" }
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
serde = { version = "1.0.104", features = ["derive", "rc"] }
|
serde = { version = "1.0.104", features = ["derive", "rc"] }
|
||||||
bincode = "1.2.1"
|
bincode = "1.2.1"
|
||||||
|
@ -35,7 +37,6 @@ hex-literal = "0.2.1"
|
||||||
rustyline = { version = "6.0.0", optional = true }
|
rustyline = { version = "6.0.0", optional = true }
|
||||||
nom = { version = "5.0.0", optional = true }
|
nom = { version = "5.0.0", optional = true }
|
||||||
gdbstub = { version = "0.1.2", optional = true, features = ["std"] }
|
gdbstub = { version = "0.1.2", optional = true, features = ["std"] }
|
||||||
ringbuf = "0.2.2"
|
|
||||||
goblin = { version = "0.2", optional = true }
|
goblin = { version = "0.2", optional = true }
|
||||||
fuzzy-matcher = { version = "0.3.4", optional = true }
|
fuzzy-matcher = { version = "0.3.4", optional = true }
|
||||||
bit_reverse = "0.1.8"
|
bit_reverse = "0.1.8"
|
||||||
|
@ -43,12 +44,6 @@ yaml-rust = "0.4"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
smart-default = "0.6.0"
|
smart-default = "0.6.0"
|
||||||
|
|
||||||
[target.'cfg(target_arch="wasm32")'.dependencies]
|
|
||||||
instant = { version = "0.1.2", features = ["wasm-bindgen"] }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
bit = "^0.1"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use super::arm7tdmi;
|
use super::bus::{Bus, DebugRead};
|
||||||
use super::bus::{Addr, Bus, DebugRead};
|
|
||||||
use super::util::WeakPointer;
|
|
||||||
use super::SysBus;
|
use super::SysBus;
|
||||||
|
use arm7tdmi::{memory::Addr, Arm7tdmiCore};
|
||||||
|
|
||||||
|
use rustboyadvance_utils::WeakPointer;
|
||||||
|
|
||||||
/// Struct representing the sytem ROM
|
/// Struct representing the sytem ROM
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -11,7 +12,7 @@ pub struct Bios {
|
||||||
/// Last read value
|
/// Last read value
|
||||||
last_opcode: u32,
|
last_opcode: u32,
|
||||||
/// Arm pointer - used only to read the PC register
|
/// Arm pointer - used only to read the PC register
|
||||||
arm_core: WeakPointer<arm7tdmi::Core<SysBus>>,
|
arm_core: WeakPointer<Arm7tdmiCore<SysBus>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bios {
|
impl Bios {
|
||||||
|
@ -23,7 +24,7 @@ impl Bios {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn connect_arm_core(&mut self, arm_ptr: WeakPointer<arm7tdmi::Core<SysBus>>) {
|
pub(super) fn connect_arm_core(&mut self, arm_ptr: WeakPointer<Arm7tdmiCore<SysBus>>) {
|
||||||
self.arm_core = arm_ptr;
|
self.arm_core = arm_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub type Addr = u32;
|
pub use arm7tdmi::memory::Addr; // re-export
|
||||||
|
|
||||||
pub trait Bus {
|
pub trait Bus {
|
||||||
fn read_32(&mut self, addr: Addr) -> u32 {
|
fn read_32(&mut self, addr: Addr) -> u32 {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serde::de::{self, Deserialize, Deserializer, SeqAccess, Visitor};
|
||||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||||
|
|
||||||
use super::BackupMemoryInterface;
|
use super::BackupMemoryInterface;
|
||||||
use crate::util::write_bin_file;
|
use rustboyadvance_utils::write_bin_file;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BackupFile {
|
pub struct BackupFile {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::io::prelude::*;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::util::read_bin_file;
|
use rustboyadvance_utils::read_bin_file;
|
||||||
use zip::ZipArchive;
|
use zip::ZipArchive;
|
||||||
|
|
||||||
#[cfg(feature = "elf_support")]
|
#[cfg(feature = "elf_support")]
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::arm7tdmi::thumb::ThumbInstruction;
|
||||||
use crate::arm7tdmi::CpuState;
|
use crate::arm7tdmi::CpuState;
|
||||||
use crate::bus::{Addr, Bus, DebugRead};
|
use crate::bus::{Addr, Bus, DebugRead};
|
||||||
use crate::disass::Disassembler;
|
use crate::disass::Disassembler;
|
||||||
use crate::util::{read_bin_file, write_bin_file};
|
use rustboyadvance_utils::{read_bin_file, write_bin_file};
|
||||||
|
|
||||||
// use super::palette_view::create_palette_view;
|
// use super::palette_view::create_palette_view;
|
||||||
// use super::tile_view::create_tile_view;
|
// use super::tile_view::create_tile_view;
|
||||||
|
|
|
@ -5,7 +5,6 @@ use std::rc::Rc;
|
||||||
use bincode;
|
use bincode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::arm7tdmi;
|
|
||||||
use super::cartridge::Cartridge;
|
use super::cartridge::Cartridge;
|
||||||
use super::dma::DmaController;
|
use super::dma::DmaController;
|
||||||
use super::gpu::*;
|
use super::gpu::*;
|
||||||
|
@ -15,14 +14,16 @@ use super::sched::{EventType, Scheduler, SchedulerConnect, SharedScheduler};
|
||||||
use super::sound::SoundController;
|
use super::sound::SoundController;
|
||||||
use super::sysbus::SysBus;
|
use super::sysbus::SysBus;
|
||||||
use super::timer::Timers;
|
use super::timer::Timers;
|
||||||
use super::util::Shared;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_video_interface"))]
|
#[cfg(not(feature = "no_video_interface"))]
|
||||||
use super::VideoInterface;
|
use super::VideoInterface;
|
||||||
use super::{AudioInterface, InputInterface};
|
use super::{AudioInterface, InputInterface};
|
||||||
|
|
||||||
|
use arm7tdmi::{self, Arm7tdmiCore};
|
||||||
|
use rustboyadvance_utils::Shared;
|
||||||
|
|
||||||
pub struct GameBoyAdvance {
|
pub struct GameBoyAdvance {
|
||||||
pub cpu: Box<arm7tdmi::Core<SysBus>>,
|
pub cpu: Box<Arm7tdmiCore<SysBus>>,
|
||||||
pub sysbus: Shared<SysBus>,
|
pub sysbus: Shared<SysBus>,
|
||||||
pub io_devs: Shared<IoDevices>,
|
pub io_devs: Shared<IoDevices>,
|
||||||
pub scheduler: SharedScheduler,
|
pub scheduler: SharedScheduler,
|
||||||
|
@ -103,7 +104,7 @@ impl GameBoyAdvance {
|
||||||
gamepak,
|
gamepak,
|
||||||
));
|
));
|
||||||
|
|
||||||
let cpu = Box::new(arm7tdmi::Core::new(sysbus.clone()));
|
let cpu = Box::new(Arm7tdmiCore::new(sysbus.clone()));
|
||||||
|
|
||||||
let mut gba = GameBoyAdvance {
|
let mut gba = GameBoyAdvance {
|
||||||
cpu,
|
cpu,
|
||||||
|
@ -150,7 +151,7 @@ impl GameBoyAdvance {
|
||||||
decoded.ewram,
|
decoded.ewram,
|
||||||
decoded.iwram,
|
decoded.iwram,
|
||||||
));
|
));
|
||||||
let mut arm7tdmi = Box::new(arm7tdmi::Core::from_saved_state(
|
let mut arm7tdmi = Box::new(Arm7tdmiCore::from_saved_state(
|
||||||
sysbus.clone(),
|
sysbus.clone(),
|
||||||
decoded.cpu_state,
|
decoded.cpu_state,
|
||||||
));
|
));
|
||||||
|
|
|
@ -10,6 +10,44 @@ use gdbstub::{Access, Target, TargetState};
|
||||||
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use gdbstub;
|
||||||
|
use gdbstub::GdbStub;
|
||||||
|
use std::fmt;
|
||||||
|
use std::net::TcpListener;
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
|
|
||||||
|
pub fn spawn_and_run_gdb_server<A: ToSocketAddrs + fmt::Display>(
|
||||||
|
#[allow(unused)] target: &mut GameBoyAdvance,
|
||||||
|
#[allow(unused)] addr: A,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
#[cfg(feature = "gdb")]
|
||||||
|
{
|
||||||
|
info!("spawning gdbserver, listening on {}", addr);
|
||||||
|
|
||||||
|
let sock = TcpListener::bind(addr)?;
|
||||||
|
let (stream, addr) = sock.accept()?;
|
||||||
|
|
||||||
|
info!("got connection from {}", addr);
|
||||||
|
|
||||||
|
let mut gdb = GdbStub::new(stream);
|
||||||
|
let result = match gdb.run(target) {
|
||||||
|
Ok(state) => {
|
||||||
|
info!("Disconnected from GDB. Target state: {:?}", state);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(gdbstub::Error::TargetError(e)) => Err(e),
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Debugger session ended, result={:?}", result);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "gdb"))]
|
||||||
|
{
|
||||||
|
error!("failed. please compile me with 'gdb' feature")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
impl Target for GameBoyAdvance {
|
impl Target for GameBoyAdvance {
|
||||||
type Usize = u32;
|
type Usize = u32;
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
|
@ -3,8 +3,11 @@ use std::cell::RefCell;
|
||||||
#[cfg(not(feature = "no_video_interface"))]
|
#[cfg(not(feature = "no_video_interface"))]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use num::FromPrimitive;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use rustboyadvance_utils::index2d;
|
||||||
|
|
||||||
use super::bus::*;
|
use super::bus::*;
|
||||||
use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
|
use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
|
||||||
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
||||||
|
@ -13,8 +16,6 @@ pub use super::sysbus::consts::*;
|
||||||
#[cfg(not(feature = "no_video_interface"))]
|
#[cfg(not(feature = "no_video_interface"))]
|
||||||
use super::VideoInterface;
|
use super::VideoInterface;
|
||||||
|
|
||||||
use crate::num::FromPrimitive;
|
|
||||||
|
|
||||||
mod render;
|
mod render;
|
||||||
|
|
||||||
use render::Point;
|
use render::Point;
|
||||||
|
|
|
@ -7,6 +7,7 @@ use super::super::Rgb15;
|
||||||
use super::{utils, MODE5_VIEWPORT, SCREEN_VIEWPORT};
|
use super::{utils, MODE5_VIEWPORT, SCREEN_VIEWPORT};
|
||||||
|
|
||||||
use crate::Bus;
|
use crate::Bus;
|
||||||
|
use rustboyadvance_utils::index2d;
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
pub(in super::super) fn render_mode3(&mut self, bg: usize) {
|
pub(in super::super) fn render_mode3(&mut self, bg: usize) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use super::super::regs::*;
|
use super::super::regs::*;
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
|
use rustboyadvance_utils::index2d;
|
||||||
|
|
||||||
const OVRAM: u32 = 0x0601_0000;
|
const OVRAM: u32 = 0x0601_0000;
|
||||||
const PALRAM_OFS_FG: u32 = 0x200;
|
const PALRAM_OFS_FG: u32 = 0x200;
|
||||||
const ATTRS_SIZE: u32 = 2 * 3 + 2;
|
const ATTRS_SIZE: u32 = 2 * 3 + 2;
|
||||||
|
|
|
@ -7,6 +7,8 @@ use super::{utils, ViewPort};
|
||||||
|
|
||||||
use crate::Bus;
|
use crate::Bus;
|
||||||
|
|
||||||
|
use rustboyadvance_utils::index2d;
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
pub(in super::super) fn render_reg_bg(&mut self, bg: usize) {
|
pub(in super::super) fn render_reg_bg(&mut self, bg: usize) {
|
||||||
let (h_ofs, v_ofs) = (self.bg_hofs[bg] as u32, self.bg_vofs[bg] as u32);
|
let (h_ofs, v_ofs) = (self.bg_hofs[bg] as u32, self.bg_vofs[bg] as u32);
|
||||||
|
|
|
@ -9,17 +9,13 @@ extern crate debug_stub_derive;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate enum_primitive_derive;
|
extern crate enum_primitive_derive;
|
||||||
use num;
|
|
||||||
use num_traits;
|
use num_traits;
|
||||||
|
|
||||||
use bit;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitfield;
|
extern crate bitfield;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
|
||||||
use byteorder;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
@ -36,9 +32,7 @@ use zip;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[macro_use]
|
pub use arm7tdmi;
|
||||||
pub mod util;
|
|
||||||
pub mod arm7tdmi;
|
|
||||||
pub use arm7tdmi::disass;
|
pub use arm7tdmi::disass;
|
||||||
mod bios;
|
mod bios;
|
||||||
pub mod cartridge;
|
pub mod cartridge;
|
||||||
|
@ -140,10 +134,10 @@ pub mod prelude {
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
pub use super::debugger::Debugger;
|
pub use super::debugger::Debugger;
|
||||||
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
|
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
|
||||||
pub use super::util::{read_bin_file, write_bin_file};
|
|
||||||
pub use super::Bus;
|
pub use super::Bus;
|
||||||
#[cfg(not(feature = "no_video_interface"))]
|
#[cfg(not(feature = "no_video_interface"))]
|
||||||
pub use super::VideoInterface;
|
pub use super::VideoInterface;
|
||||||
pub use super::{AudioInterface, InputInterface, StereoSample};
|
pub use super::{AudioInterface, InputInterface, StereoSample};
|
||||||
pub use super::{GBAError, GBAResult, GameBoyAdvance};
|
pub use super::{GBAError, GBAResult, GameBoyAdvance};
|
||||||
|
pub use rustboyadvance_utils::{read_bin_file, write_bin_file};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
|
|
||||||
use super::util::Shared;
|
use rustboyadvance_utils::Shared;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -271,17 +271,19 @@ mod test {
|
||||||
let mut sched = holder.sched.clone();
|
let mut sched = holder.sched.clone();
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Gpu(GpuEvent::VBlankHDraw), 240);
|
.schedule((EventType::Gpu(GpuEvent::VBlankHDraw), 240));
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg1Generate), 60);
|
.schedule((EventType::Apu(ApuEvent::Psg1Generate), 60));
|
||||||
holder.sched.push(EventType::Apu(ApuEvent::Sample), 512);
|
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg2Generate), 13);
|
.schedule((EventType::Apu(ApuEvent::Sample), 512));
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg4Generate), 72);
|
.schedule((EventType::Apu(ApuEvent::Psg2Generate), 13));
|
||||||
|
holder
|
||||||
|
.sched
|
||||||
|
.schedule((EventType::Apu(ApuEvent::Psg4Generate), 72));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sched.events.pop(),
|
sched.events.pop(),
|
||||||
|
@ -300,17 +302,19 @@ mod test {
|
||||||
let mut sched = holder.sched.clone();
|
let mut sched = holder.sched.clone();
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Gpu(GpuEvent::VBlankHDraw), 240);
|
.schedule((EventType::Gpu(GpuEvent::VBlankHDraw), 240));
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg1Generate), 60);
|
.schedule((EventType::Apu(ApuEvent::Psg1Generate), 60));
|
||||||
holder.sched.push(EventType::Apu(ApuEvent::Sample), 512);
|
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg2Generate), 13);
|
.schedule((EventType::Apu(ApuEvent::Sample), 512));
|
||||||
holder
|
holder
|
||||||
.sched
|
.sched
|
||||||
.push(EventType::Apu(ApuEvent::Psg4Generate), 72);
|
.schedule((EventType::Apu(ApuEvent::Psg2Generate), 13));
|
||||||
|
holder
|
||||||
|
.sched
|
||||||
|
.schedule((EventType::Apu(ApuEvent::Psg4Generate), 72));
|
||||||
|
|
||||||
println!("all events");
|
println!("all events");
|
||||||
for e in sched.events.iter() {
|
for e in sched.events.iter() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::arm7tdmi;
|
|
||||||
use super::arm7tdmi::memory::*;
|
use super::arm7tdmi::memory::*;
|
||||||
use super::bios::Bios;
|
use super::bios::Bios;
|
||||||
use super::bus::*;
|
use super::bus::*;
|
||||||
|
@ -8,7 +7,8 @@ use super::cartridge::Cartridge;
|
||||||
use super::dma::DmaNotifer;
|
use super::dma::DmaNotifer;
|
||||||
use super::iodev::{IoDevices, WaitControl};
|
use super::iodev::{IoDevices, WaitControl};
|
||||||
use super::sched::*;
|
use super::sched::*;
|
||||||
use super::util::{Shared, WeakPointer};
|
use arm7tdmi::{self, Arm7tdmiCore};
|
||||||
|
use rustboyadvance_utils::{Shared, WeakPointer};
|
||||||
|
|
||||||
pub mod consts {
|
pub mod consts {
|
||||||
pub const WORK_RAM_SIZE: usize = 256 * 1024;
|
pub const WORK_RAM_SIZE: usize = 256 * 1024;
|
||||||
|
@ -145,7 +145,7 @@ impl CycleLookupTables {
|
||||||
pub struct SysBus {
|
pub struct SysBus {
|
||||||
pub io: Shared<IoDevices>,
|
pub io: Shared<IoDevices>,
|
||||||
scheduler: Shared<Scheduler>,
|
scheduler: Shared<Scheduler>,
|
||||||
arm_core: WeakPointer<arm7tdmi::Core<SysBus>>,
|
arm_core: WeakPointer<Arm7tdmiCore<SysBus>>,
|
||||||
|
|
||||||
bios: Bios,
|
bios: Bios,
|
||||||
ewram: Box<[u8]>,
|
ewram: Box<[u8]>,
|
||||||
|
@ -225,7 +225,7 @@ impl SysBus {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// must be called whenever this object is instanciated
|
/// must be called whenever this object is instanciated
|
||||||
pub fn init(&mut self, arm_core: WeakPointer<arm7tdmi::Core<SysBus>>) {
|
pub fn init(&mut self, arm_core: WeakPointer<Arm7tdmiCore<SysBus>>) {
|
||||||
self.arm_core = arm_core.clone();
|
self.arm_core = arm_core.clone();
|
||||||
self.bios.connect_arm_core(arm_core.clone());
|
self.bios.connect_arm_core(arm_core.clone());
|
||||||
let ptr = SysBusPtr::new(self as *mut SysBus);
|
let ptr = SysBusPtr::new(self as *mut SysBus);
|
||||||
|
@ -268,10 +268,9 @@ impl SysBus {
|
||||||
/// `addr` is considered to be an address of
|
/// `addr` is considered to be an address of
|
||||||
fn read_invalid(&mut self, addr: Addr) -> u32 {
|
fn read_invalid(&mut self, addr: Addr) -> u32 {
|
||||||
warn!("invalid read @{:08x}", addr);
|
warn!("invalid read @{:08x}", addr);
|
||||||
use super::arm7tdmi::CpuState;
|
|
||||||
let value = match self.arm_core.cpsr.state() {
|
let value = match self.arm_core.cpsr.state() {
|
||||||
CpuState::ARM => self.arm_core.get_prefetched_opcode(),
|
arm7tdmi::CpuState::ARM => self.arm_core.get_prefetched_opcode(),
|
||||||
CpuState::THUMB => {
|
arm7tdmi::CpuState::THUMB => {
|
||||||
// For THUMB code the result consists of two 16bit fragments and depends on the address area
|
// For THUMB code the result consists of two 16bit fragments and depends on the address area
|
||||||
// and alignment where the opcode was stored.
|
// and alignment where the opcode was stored.
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustboyadvance-core = { path = "../../core/", features = ["elf_support"] }
|
rustboyadvance-core = { path = "../../core/", features = ["elf_support"] }
|
||||||
|
rustboyadvance-utils = { path = "../../utils/" }
|
||||||
sdl2 = { version = "0.33.0", features = ["image"] }
|
sdl2 = { version = "0.33.0", features = ["image"] }
|
||||||
ringbuf = "0.2.2"
|
ringbuf = "0.2.2"
|
||||||
bytesize = "1.0.0"
|
bytesize = "1.0.0"
|
||||||
|
|
|
@ -41,9 +41,11 @@ use input::create_input;
|
||||||
use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH};
|
use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH};
|
||||||
|
|
||||||
use rustboyadvance_core::cartridge::BackupType;
|
use rustboyadvance_core::cartridge::BackupType;
|
||||||
|
#[cfg(feature = "gdb")]
|
||||||
|
use rustboyadvance_core::gdb::spawn_and_run_gdb_server;
|
||||||
use rustboyadvance_core::prelude::*;
|
use rustboyadvance_core::prelude::*;
|
||||||
use rustboyadvance_core::util::spawn_and_run_gdb_server;
|
|
||||||
use rustboyadvance_core::util::FpsCounter;
|
use rustboyadvance_utils::FpsCounter;
|
||||||
|
|
||||||
const LOG_DIR: &str = ".logs";
|
const LOG_DIR: &str = ".logs";
|
||||||
const DEFAULT_GDB_SERVER_ADDR: &'static str = "localhost:1337";
|
const DEFAULT_GDB_SERVER_ADDR: &'static str = "localhost:1337";
|
||||||
|
@ -237,6 +239,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gdb")]
|
||||||
if with_gdbserver {
|
if with_gdbserver {
|
||||||
spawn_and_run_gdb_server(&mut gba, DEFAULT_GDB_SERVER_ADDR)?;
|
spawn_and_run_gdb_server(&mut gba, DEFAULT_GDB_SERVER_ADDR)?;
|
||||||
}
|
}
|
||||||
|
|
12
utils/Cargo.toml
Normal file
12
utils/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "rustboyadvance-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ringbuf = "0.2.2"
|
||||||
|
|
||||||
|
[target.'cfg(target_arch="wasm32")'.dependencies]
|
||||||
|
instant = { version = "0.1.2", features = ["wasm-bindgen"] }
|
|
@ -22,49 +22,6 @@ fn now() -> Instant {
|
||||||
instant::Instant::now()
|
instant::Instant::now()
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::GameBoyAdvance;
|
|
||||||
#[cfg(feature = "gdb")]
|
|
||||||
use gdbstub;
|
|
||||||
#[cfg(feature = "gdb")]
|
|
||||||
use gdbstub::GdbStub;
|
|
||||||
use std::fmt;
|
|
||||||
#[cfg(feature = "gdb")]
|
|
||||||
use std::net::TcpListener;
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
|
|
||||||
pub fn spawn_and_run_gdb_server<A: ToSocketAddrs + fmt::Display>(
|
|
||||||
#[allow(unused)] target: &mut GameBoyAdvance,
|
|
||||||
#[allow(unused)] addr: A,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
#[cfg(feature = "gdb")]
|
|
||||||
{
|
|
||||||
info!("spawning gdbserver, listening on {}", addr);
|
|
||||||
|
|
||||||
let sock = TcpListener::bind(addr)?;
|
|
||||||
let (stream, addr) = sock.accept()?;
|
|
||||||
|
|
||||||
info!("got connection from {}", addr);
|
|
||||||
|
|
||||||
let mut gdb = GdbStub::new(stream);
|
|
||||||
let result = match gdb.run(target) {
|
|
||||||
Ok(state) => {
|
|
||||||
info!("Disconnected from GDB. Target state: {:?}", state);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Err(gdbstub::Error::TargetError(e)) => Err(e),
|
|
||||||
Err(e) => return Err(e.into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
info!("Debugger session ended, result={:?}", result);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "gdb"))]
|
|
||||||
{
|
|
||||||
error!("failed. please compile me with 'gdb' feature")
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_bin_file(filename: &Path) -> io::Result<Vec<u8>> {
|
pub fn read_bin_file(filename: &Path) -> io::Result<Vec<u8>> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let mut file = File::open(filename)?;
|
let mut file = File::open(filename)?;
|
Reference in a new issue