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",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
|
@ -1351,6 +1367,7 @@ name = "rustboyadvance-core"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"arm7tdmi",
|
||||
"arrayvec 0.5.2",
|
||||
"bincode",
|
||||
"bit",
|
||||
|
@ -1371,14 +1388,13 @@ dependencies = [
|
|||
"goblin",
|
||||
"hex-literal",
|
||||
"hexdump",
|
||||
"instant",
|
||||
"lazy_static 1.4.0",
|
||||
"log 0.4.11",
|
||||
"memmem",
|
||||
"nom",
|
||||
"num 0.2.1",
|
||||
"num-traits 0.2.12",
|
||||
"ringbuf",
|
||||
"rustboyadvance-utils",
|
||||
"rustyline",
|
||||
"serde",
|
||||
"sha2",
|
||||
|
@ -1433,11 +1449,20 @@ dependencies = [
|
|||
"log 0.4.11",
|
||||
"ringbuf",
|
||||
"rustboyadvance-core",
|
||||
"rustboyadvance-utils",
|
||||
"sdl2 0.33.0",
|
||||
"spin_sleep",
|
||||
"winres",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustboyadvance-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"ringbuf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustboyadvance-wasm"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"core",
|
||||
"arm7tdmi",
|
||||
"utils",
|
||||
"platform/rustboyadvance-sdl2",
|
||||
"platform/rustboyadvance-libretro",
|
||||
"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::fs;
|
||||
use std::io::Write;
|
||||
|
@ -6,7 +7,7 @@ use std::path::Path;
|
|||
extern crate bit;
|
||||
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) {
|
||||
let offset5 = i.bit_range(6..11) as u8;
|
||||
let load = i.bit(11);
|
||||
|
@ -180,7 +181,7 @@ trait BitAsInt<T: From<bool>>: BitIndex {
|
|||
|
||||
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
|
||||
/// * `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> {
|
||||
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
||||
writeln!(file, "impl<I: MemoryInterface> Arm7tdmiCore<I> {{")?;
|
||||
writeln!(
|
||||
file,
|
||||
" pub const THUMB_LUT: [ThumbInstructionInfo<I>; 1024] = ["
|
||||
|
@ -380,7 +381,7 @@ fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
|||
file,
|
||||
" /* {:#x} */
|
||||
ThumbInstructionInfo {{
|
||||
handler_fn: Core::{},
|
||||
handler_fn: Arm7tdmiCore::{},
|
||||
#[cfg(feature = \"debugger\")]
|
||||
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> {
|
||||
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
||||
writeln!(file, "impl<I: MemoryInterface> Arm7tdmiCore<I> {{")?;
|
||||
writeln!(
|
||||
file,
|
||||
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
|
||||
|
@ -406,7 +407,7 @@ fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
|||
file,
|
||||
" /* {:#x} */
|
||||
ArmInstructionInfo {{
|
||||
handler_fn: Core::{},
|
||||
handler_fn: Arm7tdmiCore::{},
|
||||
#[cfg(feature = \"debugger\")]
|
||||
fmt: ArmFormat::{},
|
||||
}} ,",
|
|
@ -1,7 +1,6 @@
|
|||
use bit::BitIndex;
|
||||
|
||||
use super::memory::MemoryInterface;
|
||||
use super::{Core, REG_PC};
|
||||
use crate::{memory::MemoryInterface, registers_consts::REG_PC, Arm7tdmiCore};
|
||||
|
||||
#[derive(Debug, Primitive, Eq, PartialEq)]
|
||||
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 {
|
||||
match amount {
|
||||
0 => val,
|
|
@ -1,17 +1,19 @@
|
|||
use crate::bit::BitIndex;
|
||||
|
||||
use super::super::alu::*;
|
||||
use crate::arm7tdmi::psr::RegPSR;
|
||||
use crate::arm7tdmi::CpuAction;
|
||||
use crate::arm7tdmi::{Addr, Core, CpuMode, CpuState, REG_LR, REG_PC};
|
||||
use crate::{
|
||||
alu::*,
|
||||
memory::{MemoryAccess, MemoryInterface},
|
||||
psr::RegPSR,
|
||||
registers_consts::{REG_LR, REG_PC},
|
||||
Arm7tdmiCore, CpuAction, CpuMode, CpuState,
|
||||
};
|
||||
|
||||
use super::super::memory::{MemoryAccess, MemoryInterface};
|
||||
use MemoryAccess::*;
|
||||
|
||||
use super::ArmDecodeHelper;
|
||||
use super::*;
|
||||
|
||||
impl<I: MemoryInterface> Core<I> {
|
||||
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||
pub fn arm_undefined(&mut self, insn: u32) -> CpuAction {
|
||||
panic!(
|
||||
"executing undefined arm instruction {:08x} at @{:08x}",
|
|
@ -5,11 +5,12 @@ pub mod exec;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::alu::*;
|
||||
use crate::arm7tdmi::{Addr, InstructionDecoder};
|
||||
use super::memory::Addr;
|
||||
use super::InstructionDecoder;
|
||||
|
||||
use crate::bit::BitIndex;
|
||||
use crate::byteorder::{LittleEndian, ReadBytesExt};
|
||||
use crate::num::FromPrimitive;
|
||||
use bit::BitIndex;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use num::FromPrimitive;
|
||||
|
||||
use std::io;
|
||||
|
|
@ -4,7 +4,7 @@ pub use super::exception::Exception;
|
|||
|
||||
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 MemoryAccess::*;
|
||||
|
@ -19,14 +19,14 @@ use super::arm::ArmFormat;
|
|||
|
||||
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
||||
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")]
|
||||
pub fmt: ThumbFormat,
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "debugger"), repr(transparent))]
|
||||
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")]
|
||||
pub fmt: ArmFormat,
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl Default for DebuggerState {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Core<I: MemoryInterface> {
|
||||
pub struct Arm7tdmiCore<I: MemoryInterface> {
|
||||
pub pc: u32,
|
||||
pub(super) bus: Shared<I>,
|
||||
|
||||
|
@ -121,10 +121,10 @@ pub struct Core<I: MemoryInterface> {
|
|||
pub dbg: DebuggerState,
|
||||
}
|
||||
|
||||
impl<I: MemoryInterface> Core<I> {
|
||||
pub fn new(bus: Shared<I>) -> Core<I> {
|
||||
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||
pub fn new(bus: Shared<I>) -> Arm7tdmiCore<I> {
|
||||
let cpsr = RegPSR::new(0x0000_00D3);
|
||||
Core {
|
||||
Arm7tdmiCore {
|
||||
bus,
|
||||
pc: 0,
|
||||
gpr: [0; 15],
|
||||
|
@ -139,12 +139,12 @@ impl<I: MemoryInterface> Core<I> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn weak_ptr(&mut self) -> WeakPointer<Core<I>> {
|
||||
WeakPointer::new(self as *mut Core<I>)
|
||||
pub fn weak_ptr(&mut self) -> WeakPointer<Arm7tdmiCore<I>> {
|
||||
WeakPointer::new(self as *mut Arm7tdmiCore<I>)
|
||||
}
|
||||
|
||||
pub fn from_saved_state(bus: Shared<I>, state: SavedCpuState) -> Core<I> {
|
||||
Core {
|
||||
pub fn from_saved_state(bus: Shared<I>, state: SavedCpuState) -> Arm7tdmiCore<I> {
|
||||
Arm7tdmiCore {
|
||||
bus,
|
||||
|
||||
pc: state.pc,
|
|
@ -1,5 +1,5 @@
|
|||
use super::cpu::Core;
|
||||
use super::memory::MemoryInterface;
|
||||
use super::Arm7tdmiCore;
|
||||
use super::{CpuMode, CpuState};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -16,7 +16,7 @@ pub enum Exception {
|
|||
Fiq = 0x1c,
|
||||
}
|
||||
|
||||
impl<I: MemoryInterface> Core<I> {
|
||||
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||
pub fn exception(&mut self, e: Exception, lr: u32) {
|
||||
use Exception::*;
|
||||
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 num::Num;
|
||||
|
@ -14,16 +23,17 @@ pub use cpu::*;
|
|||
pub mod alu;
|
||||
pub mod memory;
|
||||
pub use alu::*;
|
||||
use memory::Addr;
|
||||
pub mod exception;
|
||||
pub mod psr;
|
||||
pub use psr::*;
|
||||
pub mod disass;
|
||||
|
||||
pub mod registers_consts {
|
||||
pub const REG_PC: usize = 15;
|
||||
pub const REG_LR: usize = 14;
|
||||
pub const REG_SP: usize = 13;
|
||||
|
||||
pub(self) use crate::Addr;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||
pub enum DecodedInstruction {
|
|
@ -1,7 +1,8 @@
|
|||
use super::cpu::Core;
|
||||
use super::Addr;
|
||||
use super::Arm7tdmiCore;
|
||||
use std::fmt;
|
||||
|
||||
pub type Addr = u32;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
|
||||
pub enum MemoryAccess {
|
||||
NonSeq = 0,
|
||||
|
@ -35,7 +36,7 @@ pub enum MemoryAccessWidth {
|
|||
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 {
|
||||
/// data: [u8; 0x4000]
|
||||
|
@ -60,7 +61,7 @@ pub enum MemoryAccessWidth {
|
|||
/// }
|
||||
///
|
||||
/// let mem = Shared::new(Memory { ... });
|
||||
/// let cpu = arm7tdmi::Core::new(mem.clone())
|
||||
/// let cpu = arm7tdmi::Arm7tdmiCore::new(mem.clone())
|
||||
///
|
||||
pub trait MemoryInterface {
|
||||
/// Read a byte
|
||||
|
@ -80,7 +81,7 @@ pub trait MemoryInterface {
|
|||
fn idle_cycle(&mut self);
|
||||
}
|
||||
|
||||
impl<I: MemoryInterface> MemoryInterface for Core<I> {
|
||||
impl<I: MemoryInterface> MemoryInterface for Arm7tdmiCore<I> {
|
||||
#[inline]
|
||||
fn load_8(&mut self, addr: u32, access: MemoryAccess) -> u8 {
|
||||
self.bus.load_8(addr, access)
|
||||
|
@ -117,7 +118,7 @@ impl<I: MemoryInterface> MemoryInterface for Core<I> {
|
|||
}
|
||||
|
||||
/// Implementation of memory access helpers
|
||||
impl<I: MemoryInterface> Core<I> {
|
||||
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||
#[inline]
|
||||
pub(super) fn store_aligned_32(&mut self, addr: Addr, value: u32, access: MemoryAccess) {
|
||||
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::*;
|
||||
use MemoryAccess::*;
|
||||
|
||||
impl<I: MemoryInterface> Core<I> {
|
||||
impl<I: MemoryInterface> Arm7tdmiCore<I> {
|
||||
/// Format 1
|
||||
/// Execution Time: 1S
|
||||
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::arm::*;
|
||||
use super::{Addr, InstructionDecoder};
|
||||
use crate::bit::BitIndex;
|
||||
use crate::byteorder::{LittleEndian, ReadBytesExt};
|
||||
use crate::num::FromPrimitive;
|
||||
use super::memory::Addr;
|
||||
use super::InstructionDecoder;
|
||||
use bit::BitIndex;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use num::FromPrimitive;
|
||||
|
||||
#[cfg(feature = "debugger")]
|
||||
pub mod disass;
|
|
@ -5,6 +5,8 @@ authors = ["Michel Heily <michelheily@gmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
arm7tdmi = { "path" = "../arm7tdmi" }
|
||||
rustboyadvance-utils = { "path" = "../utils" }
|
||||
cfg-if = "1.0.0"
|
||||
serde = { version = "1.0.104", features = ["derive", "rc"] }
|
||||
bincode = "1.2.1"
|
||||
|
@ -35,7 +37,6 @@ hex-literal = "0.2.1"
|
|||
rustyline = { version = "6.0.0", optional = true }
|
||||
nom = { version = "5.0.0", optional = true }
|
||||
gdbstub = { version = "0.1.2", optional = true, features = ["std"] }
|
||||
ringbuf = "0.2.2"
|
||||
goblin = { version = "0.2", optional = true }
|
||||
fuzzy-matcher = { version = "0.3.4", optional = true }
|
||||
bit_reverse = "0.1.8"
|
||||
|
@ -43,12 +44,6 @@ yaml-rust = "0.4"
|
|||
lazy_static = "1.4.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]
|
||||
criterion = "0.3"
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use super::arm7tdmi;
|
||||
use super::bus::{Addr, Bus, DebugRead};
|
||||
use super::util::WeakPointer;
|
||||
use super::bus::{Bus, DebugRead};
|
||||
use super::SysBus;
|
||||
use arm7tdmi::{memory::Addr, Arm7tdmiCore};
|
||||
|
||||
use rustboyadvance_utils::WeakPointer;
|
||||
|
||||
/// Struct representing the sytem ROM
|
||||
#[derive(Clone)]
|
||||
|
@ -11,7 +12,7 @@ pub struct Bios {
|
|||
/// Last read value
|
||||
last_opcode: u32,
|
||||
/// Arm pointer - used only to read the PC register
|
||||
arm_core: WeakPointer<arm7tdmi::Core<SysBus>>,
|
||||
arm_core: WeakPointer<Arm7tdmiCore<SysBus>>,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub type Addr = u32;
|
||||
pub use arm7tdmi::memory::Addr; // re-export
|
||||
|
||||
pub trait Bus {
|
||||
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 super::BackupMemoryInterface;
|
||||
use crate::util::write_bin_file;
|
||||
use rustboyadvance_utils::write_bin_file;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BackupFile {
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::io::prelude::*;
|
|||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::util::read_bin_file;
|
||||
use rustboyadvance_utils::read_bin_file;
|
||||
use zip::ZipArchive;
|
||||
|
||||
#[cfg(feature = "elf_support")]
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::arm7tdmi::thumb::ThumbInstruction;
|
|||
use crate::arm7tdmi::CpuState;
|
||||
use crate::bus::{Addr, Bus, DebugRead};
|
||||
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::tile_view::create_tile_view;
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::rc::Rc;
|
|||
use bincode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::arm7tdmi;
|
||||
use super::cartridge::Cartridge;
|
||||
use super::dma::DmaController;
|
||||
use super::gpu::*;
|
||||
|
@ -15,14 +14,16 @@ use super::sched::{EventType, Scheduler, SchedulerConnect, SharedScheduler};
|
|||
use super::sound::SoundController;
|
||||
use super::sysbus::SysBus;
|
||||
use super::timer::Timers;
|
||||
use super::util::Shared;
|
||||
|
||||
#[cfg(not(feature = "no_video_interface"))]
|
||||
use super::VideoInterface;
|
||||
use super::{AudioInterface, InputInterface};
|
||||
|
||||
use arm7tdmi::{self, Arm7tdmiCore};
|
||||
use rustboyadvance_utils::Shared;
|
||||
|
||||
pub struct GameBoyAdvance {
|
||||
pub cpu: Box<arm7tdmi::Core<SysBus>>,
|
||||
pub cpu: Box<Arm7tdmiCore<SysBus>>,
|
||||
pub sysbus: Shared<SysBus>,
|
||||
pub io_devs: Shared<IoDevices>,
|
||||
pub scheduler: SharedScheduler,
|
||||
|
@ -103,7 +104,7 @@ impl GameBoyAdvance {
|
|||
gamepak,
|
||||
));
|
||||
|
||||
let cpu = Box::new(arm7tdmi::Core::new(sysbus.clone()));
|
||||
let cpu = Box::new(Arm7tdmiCore::new(sysbus.clone()));
|
||||
|
||||
let mut gba = GameBoyAdvance {
|
||||
cpu,
|
||||
|
@ -150,7 +151,7 @@ impl GameBoyAdvance {
|
|||
decoded.ewram,
|
||||
decoded.iwram,
|
||||
));
|
||||
let mut arm7tdmi = Box::new(arm7tdmi::Core::from_saved_state(
|
||||
let mut arm7tdmi = Box::new(Arm7tdmiCore::from_saved_state(
|
||||
sysbus.clone(),
|
||||
decoded.cpu_state,
|
||||
));
|
||||
|
|
|
@ -10,6 +10,44 @@ use gdbstub::{Access, Target, TargetState};
|
|||
|
||||
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 {
|
||||
type Usize = u32;
|
||||
type Error = ();
|
||||
|
|
|
@ -3,8 +3,11 @@ use std::cell::RefCell;
|
|||
#[cfg(not(feature = "no_video_interface"))]
|
||||
use std::rc::Rc;
|
||||
|
||||
use num::FromPrimitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use rustboyadvance_utils::index2d;
|
||||
|
||||
use super::bus::*;
|
||||
use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
|
||||
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
|
||||
|
@ -13,8 +16,6 @@ pub use super::sysbus::consts::*;
|
|||
#[cfg(not(feature = "no_video_interface"))]
|
||||
use super::VideoInterface;
|
||||
|
||||
use crate::num::FromPrimitive;
|
||||
|
||||
mod render;
|
||||
|
||||
use render::Point;
|
||||
|
|
|
@ -7,6 +7,7 @@ use super::super::Rgb15;
|
|||
use super::{utils, MODE5_VIEWPORT, SCREEN_VIEWPORT};
|
||||
|
||||
use crate::Bus;
|
||||
use rustboyadvance_utils::index2d;
|
||||
|
||||
impl Gpu {
|
||||
pub(in super::super) fn render_mode3(&mut self, bg: usize) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use super::super::regs::*;
|
||||
use super::super::*;
|
||||
|
||||
use rustboyadvance_utils::index2d;
|
||||
|
||||
const OVRAM: u32 = 0x0601_0000;
|
||||
const PALRAM_OFS_FG: u32 = 0x200;
|
||||
const ATTRS_SIZE: u32 = 2 * 3 + 2;
|
||||
|
|
|
@ -7,6 +7,8 @@ use super::{utils, ViewPort};
|
|||
|
||||
use crate::Bus;
|
||||
|
||||
use rustboyadvance_utils::index2d;
|
||||
|
||||
impl Gpu {
|
||||
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);
|
||||
|
|
|
@ -9,17 +9,13 @@ extern crate debug_stub_derive;
|
|||
|
||||
#[macro_use]
|
||||
extern crate enum_primitive_derive;
|
||||
use num;
|
||||
use num_traits;
|
||||
|
||||
use bit;
|
||||
#[macro_use]
|
||||
extern crate bitfield;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
use byteorder;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
|
@ -36,9 +32,7 @@ use zip;
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[macro_use]
|
||||
pub mod util;
|
||||
pub mod arm7tdmi;
|
||||
pub use arm7tdmi;
|
||||
pub use arm7tdmi::disass;
|
||||
mod bios;
|
||||
pub mod cartridge;
|
||||
|
@ -140,10 +134,10 @@ pub mod prelude {
|
|||
#[cfg(feature = "debugger")]
|
||||
pub use super::debugger::Debugger;
|
||||
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
|
||||
pub use super::util::{read_bin_file, write_bin_file};
|
||||
pub use super::Bus;
|
||||
#[cfg(not(feature = "no_video_interface"))]
|
||||
pub use super::VideoInterface;
|
||||
pub use super::{AudioInterface, InputInterface, StereoSample};
|
||||
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::collections::BinaryHeap;
|
||||
|
||||
use super::util::Shared;
|
||||
use rustboyadvance_utils::Shared;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -271,17 +271,19 @@ mod test {
|
|||
let mut sched = holder.sched.clone();
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Gpu(GpuEvent::VBlankHDraw), 240);
|
||||
.schedule((EventType::Gpu(GpuEvent::VBlankHDraw), 240));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg1Generate), 60);
|
||||
holder.sched.push(EventType::Apu(ApuEvent::Sample), 512);
|
||||
.schedule((EventType::Apu(ApuEvent::Psg1Generate), 60));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg2Generate), 13);
|
||||
.schedule((EventType::Apu(ApuEvent::Sample), 512));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg4Generate), 72);
|
||||
.schedule((EventType::Apu(ApuEvent::Psg2Generate), 13));
|
||||
holder
|
||||
.sched
|
||||
.schedule((EventType::Apu(ApuEvent::Psg4Generate), 72));
|
||||
|
||||
assert_eq!(
|
||||
sched.events.pop(),
|
||||
|
@ -300,17 +302,19 @@ mod test {
|
|||
let mut sched = holder.sched.clone();
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Gpu(GpuEvent::VBlankHDraw), 240);
|
||||
.schedule((EventType::Gpu(GpuEvent::VBlankHDraw), 240));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg1Generate), 60);
|
||||
holder.sched.push(EventType::Apu(ApuEvent::Sample), 512);
|
||||
.schedule((EventType::Apu(ApuEvent::Psg1Generate), 60));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg2Generate), 13);
|
||||
.schedule((EventType::Apu(ApuEvent::Sample), 512));
|
||||
holder
|
||||
.sched
|
||||
.push(EventType::Apu(ApuEvent::Psg4Generate), 72);
|
||||
.schedule((EventType::Apu(ApuEvent::Psg2Generate), 13));
|
||||
holder
|
||||
.sched
|
||||
.schedule((EventType::Apu(ApuEvent::Psg4Generate), 72));
|
||||
|
||||
println!("all events");
|
||||
for e in sched.events.iter() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::arm7tdmi;
|
||||
use super::arm7tdmi::memory::*;
|
||||
use super::bios::Bios;
|
||||
use super::bus::*;
|
||||
|
@ -8,7 +7,8 @@ use super::cartridge::Cartridge;
|
|||
use super::dma::DmaNotifer;
|
||||
use super::iodev::{IoDevices, WaitControl};
|
||||
use super::sched::*;
|
||||
use super::util::{Shared, WeakPointer};
|
||||
use arm7tdmi::{self, Arm7tdmiCore};
|
||||
use rustboyadvance_utils::{Shared, WeakPointer};
|
||||
|
||||
pub mod consts {
|
||||
pub const WORK_RAM_SIZE: usize = 256 * 1024;
|
||||
|
@ -145,7 +145,7 @@ impl CycleLookupTables {
|
|||
pub struct SysBus {
|
||||
pub io: Shared<IoDevices>,
|
||||
scheduler: Shared<Scheduler>,
|
||||
arm_core: WeakPointer<arm7tdmi::Core<SysBus>>,
|
||||
arm_core: WeakPointer<Arm7tdmiCore<SysBus>>,
|
||||
|
||||
bios: Bios,
|
||||
ewram: Box<[u8]>,
|
||||
|
@ -225,7 +225,7 @@ impl SysBus {
|
|||
}
|
||||
|
||||
/// 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.bios.connect_arm_core(arm_core.clone());
|
||||
let ptr = SysBusPtr::new(self as *mut SysBus);
|
||||
|
@ -268,10 +268,9 @@ impl SysBus {
|
|||
/// `addr` is considered to be an address of
|
||||
fn read_invalid(&mut self, addr: Addr) -> u32 {
|
||||
warn!("invalid read @{:08x}", addr);
|
||||
use super::arm7tdmi::CpuState;
|
||||
let value = match self.arm_core.cpsr.state() {
|
||||
CpuState::ARM => self.arm_core.get_prefetched_opcode(),
|
||||
CpuState::THUMB => {
|
||||
arm7tdmi::CpuState::ARM => self.arm_core.get_prefetched_opcode(),
|
||||
arm7tdmi::CpuState::THUMB => {
|
||||
// For THUMB code the result consists of two 16bit fragments and depends on the address area
|
||||
// and alignment where the opcode was stored.
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
rustboyadvance-core = { path = "../../core/", features = ["elf_support"] }
|
||||
rustboyadvance-utils = { path = "../../utils/" }
|
||||
sdl2 = { version = "0.33.0", features = ["image"] }
|
||||
ringbuf = "0.2.2"
|
||||
bytesize = "1.0.0"
|
||||
|
|
|
@ -41,9 +41,11 @@ use input::create_input;
|
|||
use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH};
|
||||
|
||||
use rustboyadvance_core::cartridge::BackupType;
|
||||
#[cfg(feature = "gdb")]
|
||||
use rustboyadvance_core::gdb::spawn_and_run_gdb_server;
|
||||
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 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 {
|
||||
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()
|
||||
}
|
||||
|
||||
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>> {
|
||||
let mut buf = Vec::new();
|
||||
let mut file = File::open(filename)?;
|
Reference in a new issue