Skip to content

Commit

Permalink
Improve HiROM space masking, add DSPx coprocessor skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
twvd committed Dec 30, 2023
1 parent 341e15d commit 38b07e6
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 4 deletions.
66 changes: 62 additions & 4 deletions src/snes/cartridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};
use strum::Display;

use crate::snes::bus::{Address, BusMember};
use super::bus::{Address, BusMember};
use super::coprocessor::dspx::DSPx;

const HDR_TITLE_OFFSET: usize = 0x00;
const HDR_TITLE_SIZE: usize = 21;
Expand Down Expand Up @@ -36,6 +37,16 @@ pub enum Chipset {
RomCoBat = 6,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, FromPrimitive)]
pub enum CoProcessor {
DSPx = 0,
SuperFX = 1,
OBC1 = 2,
SA1 = 3,
SDD1 = 4,
SRTC = 5,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, FromPrimitive)]
pub enum MapMode {
LoROM = 0,
Expand All @@ -55,6 +66,12 @@ pub struct Cartridge {

/// RAM address mask, to properly emulate mirroring
ram_mask: usize,

/// ROM address mask
rom_mask: usize,

/// DSP-x co-processor
co_dspx: Option<DSPx>,
}

impl Cartridge {
Expand Down Expand Up @@ -93,6 +110,16 @@ impl Cartridge {
(1 << self.rom[self.header_offset + HDR_RAMSIZE_OFFSET]) * 1024
}

fn get_coprocessor(&self) -> Option<CoProcessor> {
match self.get_chipset() {
Chipset::RomCo | Chipset::RomRamCo | Chipset::RomRamCoBat | Chipset::RomCoBat => Some(
CoProcessor::from_u8(self.rom[self.header_offset + HDR_CHIPSET_OFFSET] & 0xF0)
.unwrap(),
),
_ => None,
}
}

pub fn get_video_format(&self) -> VideoFormat {
match self.rom[self.header_offset + HDR_DESTINATION_OFFSET] {
0x00 // Japan
Expand Down Expand Up @@ -149,8 +176,20 @@ impl Cartridge {
hirom: false,
header_offset: header_offset.expect("Could not locate header"),
ram_mask: 0,
rom_mask: (rom.len() - load_offset - 1),
co_dspx: None,
};

// Detect / initialize co-processor
match c.get_coprocessor() {
Some(CoProcessor::DSPx) => {
println!("DSP-x co-processor detected");
c.co_dspx = Some(DSPx::new());
}
Some(c) => println!("Warning: unimplemented co-processor: {:?}", c),
None => (),
}

// TODO refactor header to its own struct
c.hirom = match c.get_map() {
MapMode::HiROM => true,
Expand All @@ -168,6 +207,8 @@ impl Cartridge {
hirom,
header_offset: 0,
ram_mask: RAM_SIZE - 1,
rom_mask: rom.len() - 1,
co_dspx: None,
}
}

Expand All @@ -180,6 +221,8 @@ impl Cartridge {
hirom: false,
header_offset: 0,
ram_mask: RAM_SIZE - 1,
rom_mask: usize::MAX,
co_dspx: None,
}
}
}
Expand All @@ -206,8 +249,9 @@ impl BusMember<Address> for Cartridge {
match (bank, addr) {
// HiROM (mirrors in LoROM banks)
(0x00..=0x3F | 0x80..=0xBF, 0x8000..=0xFFFF) if self.hirom => {
Some(self.rom[addr - 0x0000 + (bank & !0x80) * 0x10000])
Some(self.rom[(addr - 0x0000 + (bank & !0x80) * 0x10000) & self.rom_mask])
}

// LoROM
(0x00..=0x3F | 0x80..=0xFF, 0x8000..=0xFFFF) if !self.hirom => {
Some(self.rom[addr - 0x8000 + (bank & !0x80) * 0x8000])
Expand All @@ -220,7 +264,7 @@ impl BusMember<Address> for Cartridge {

// HiROM
(0x40..=0x6F, _) if self.hirom => {
Some(self.rom[(addr + ((bank - 0x40) * 0x10000)) % self.rom.len()])
Some(self.rom[(addr + ((bank - 0x40) * 0x10000)) & self.rom_mask])
}

// LoROM SRAM
Expand All @@ -229,7 +273,15 @@ impl BusMember<Address> for Cartridge {
}

// HiROM
(0xC0..=0xFF, _) if self.hirom => Some(self.rom[addr + ((bank - 0xC0) * 0x10000)]),
(0xC0..=0xFF, _) if self.hirom => {
Some(self.rom[(addr + ((bank - 0xC0) * 0x10000)) & self.rom_mask])
}

// DSP-x co-processor
(0x00..=0xDF, 0x6000..=0x7FFF) if self.co_dspx.is_some() => {
let dspx = self.co_dspx.as_ref().unwrap();
dspx.read(fulladdr)
}

_ => None,
}
Expand All @@ -249,6 +301,12 @@ impl BusMember<Address> for Cartridge {
Some(self.ram[(bank - 0x70) * 0x8000 + addr & self.ram_mask] = val)
}

// DSP-x co-processor
(0x00..=0xDF, 0x6000..=0x7FFF) if self.co_dspx.is_some() => {
let dspx = self.co_dspx.as_mut().unwrap();
dspx.write(fulladdr, val)
}

_ => None,
}
}
Expand Down
39 changes: 39 additions & 0 deletions src/snes/coprocessor/dspx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use serde::{Deserialize, Serialize};

use crate::snes::bus::{Address, BusMember};

/// DSP-x co-processor
#[derive(Serialize, Deserialize)]
pub struct DSPx {}

impl DSPx {
pub fn new() -> Self {
Self {}
}
}

impl BusMember<Address> for DSPx {
fn read(&self, fulladdr: Address) -> Option<u8> {
let (bank, addr) = ((fulladdr >> 16) as usize, (fulladdr & 0xFFFF) as usize);

match addr {
0x7000 => {
// SR (LSB)
Some(0)
}
0x7001 => {
// SR (MSB)
Some(0x80)
}
_ => None,
}
}

fn write(&mut self, fulladdr: Address, val: u8) -> Option<()> {
let (bank, addr) = ((fulladdr >> 16) as usize, (fulladdr & 0xFFFF) as usize);

match addr {
_ => None,
}
}
}
1 change: 1 addition & 0 deletions src/snes/coprocessor/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod dspx;
1 change: 1 addition & 0 deletions src/snes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod apu;
pub mod bus;
pub mod cartridge;
pub mod coprocessor;
pub mod cpu_65816;
pub mod cpu_spc700;
pub mod joypad;
Expand Down

0 comments on commit 38b07e6

Please sign in to comment.