Skip to content

Commit

Permalink
wip: refactor rom module
Browse files Browse the repository at this point in the history
  • Loading branch information
luckasRanarison committed Dec 27, 2024
1 parent 7368726 commit c0c5239
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 90 deletions.
2 changes: 1 addition & 1 deletion crates/mes-core/src/bus/ppu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
bus::Bus,
cartridge::Mirroring,
mappers::{Mapper, MapperChip},
rom::Mirroring,
utils::{Clock, Reset},
};

Expand Down
2 changes: 1 addition & 1 deletion crates/mes-core/src/features/json.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{cartridge::Header, error::Error};
use crate::{error::Error, rom::ines::Header};

pub fn serialize_rom_header(bytes: &[u8]) -> Result<String, Error> {
let header = Header::try_from_bytes(bytes)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/mes-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pub mod apu;
pub mod bus;
pub mod cartridge;
pub mod controller;
pub mod cpu;
pub mod error;
pub mod mappers;
pub mod ppu;
pub mod rom;
pub mod utils;

mod features;
Expand Down
5 changes: 4 additions & 1 deletion crates/mes-core/src/mappers/mapper_000.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

use super::Mapper;
use crate::{
cartridge::{Cartridge, ChrPage, Mirroring, PrgPage},
rom::{
cartridge::{Cartridge, ChrPage, PrgPage},
Mirroring,
},
utils::Reset,
};

Expand Down
7 changes: 5 additions & 2 deletions crates/mes-core/src/mappers/mapper_001.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

use super::Mapper;
use crate::{
cartridge::{Cartridge, ChrPage, Mirroring, PrgPage},
rom::{
cartridge::{Cartridge, ChrPage, PrgPage},
Mirroring,
},
utils::{BitFlag, Reset},
};

Expand Down Expand Up @@ -102,7 +105,7 @@ impl Mapper for SxRom {
}
}

fn get_mirroring(&self) -> crate::cartridge::Mirroring {
fn get_mirroring(&self) -> crate::rom::Mirroring {
match self.control & 0b11 {
2 => Mirroring::Vertical,
3 => Mirroring::Horizontal,
Expand Down
5 changes: 4 additions & 1 deletion crates/mes-core/src/mappers/mapper_002.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

use super::Mapper;
use crate::{
cartridge::{Cartridge, ChrPage, Mirroring, PrgPage},
rom::{
cartridge::{Cartridge, ChrPage, PrgPage},
Mirroring,
},
utils::Reset,
};

Expand Down
5 changes: 4 additions & 1 deletion crates/mes-core/src/mappers/mapper_003.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

use super::Mapper;
use crate::{
cartridge::{Cartridge, ChrPage, Mirroring, PrgPage},
rom::{
cartridge::{Cartridge, ChrPage, PrgPage},
Mirroring,
},
utils::Reset,
};

Expand Down
6 changes: 3 additions & 3 deletions crates/mes-core/src/mappers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ mod mapper_003;
use self::{mapper_000::NRom, mapper_001::SxRom, mapper_002::UxRom, mapper_003::CnRom};

use crate::{
cartridge::{Cartridge, Mirroring},
error::Error,
rom::{cartridge::Cartridge, Mirroring},
utils::{MemoryObserver, Reset},
};

Expand All @@ -26,7 +26,7 @@ pub struct MapperBuilder {
impl MapperBuilder {
pub fn new(cartridge: &[u8]) -> Result<Self, Error> {
Ok(Self {
cartridge: Cartridge::try_from_bytes(cartridge)?,
cartridge: Cartridge::try_from_ines(cartridge)?,
})
}

Expand Down Expand Up @@ -58,7 +58,7 @@ impl MapperChip {
}

pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, Error> {
Cartridge::try_from_bytes(bytes).and_then(MapperChip::try_from)
Cartridge::try_from_ines(bytes).and_then(MapperChip::try_from)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,81 +1,14 @@
// https://www.nesdev.org/wiki/INES
use crate::{error::Error, utils::MemoryObserver};

use crate::{
error::Error,
utils::{BitFlag, MemoryObserver},
use super::{
ines::{Header, INES_HEADER_SIZE, TRAINER_SIZE},
Mirroring,
};

#[cfg(feature = "json")]
use serde::Serialize;

const INES_ASCII: [u8; 4] = [0x4E, 0x45, 0x53, 0x1A];
const INES_HEADER_SIZE: usize = 16;
const TRAINER_SIZE: usize = 512;
const PRG_ROM_PAGE_SIZE: usize = 16384;
const PRG_RAM_SIZE: usize = 8192;
const CHR_ROM_PAGE_SIZE: usize = 8192;
const CHR_RAM_PAGE_SIZE: usize = 8192;

pub fn is_ines_file(bytes: &[u8]) -> bool {
bytes[0..4] == INES_ASCII
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub enum Mirroring {
Vertical,
Horizontal,
OneScreen,
FourScreen,
}

#[derive(Debug)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub struct Header {
pub prg_rom_pages: u8,
pub chr_rom_pages: u8,
pub prg_ram_pages: u8,
pub mirroring: Mirroring,
pub battery: bool,
pub trainer: bool,
pub mapper: u8,
}

impl Header {
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, Error> {
if !is_ines_file(bytes) {
return Err(Error::UnsupportedFileFormat);
}

let prg_rom_pages = *bytes.get(4).ok_or(Error::eof("PRG ROM pages", 1))?;
let chr_rom_pages = *bytes.get(5).ok_or(Error::eof("CHR ROM pages", 1))?;
let flags_6 = bytes.get(6).ok_or(Error::eof("Flags 6", 1))?;
let flags_7 = bytes.get(7).ok_or(Error::eof("Flags 7", 1))?;
let prg_ram_pages = *bytes.get(8).ok_or(Error::eof("PRG RAM pages", 1))?;

let battery = flags_6.contains(1);
let trainer = flags_6.contains(2);
let mapper = (flags_7 & 0xF0) | (flags_6 >> 4);
let is_vertical_mirroring = flags_6.contains(0);
let is_four_screen = flags_6.contains(3);

let mirroring = match (is_four_screen, is_vertical_mirroring) {
(true, _) => Mirroring::FourScreen,
(false, true) => Mirroring::Vertical,
(false, false) => Mirroring::Horizontal,
};

Ok(Self {
prg_rom_pages,
prg_ram_pages,
chr_rom_pages,
mirroring,
battery,
trainer,
mapper,
})
}
}
pub const PRG_ROM_PAGE_SIZE: usize = 16384;
pub const PRG_RAM_SIZE: usize = 8192;
pub const CHR_ROM_PAGE_SIZE: usize = 8192;
pub const CHR_RAM_PAGE_SIZE: usize = 8192;

pub enum ChrPage {
Index4(u8),
Expand Down Expand Up @@ -104,7 +37,7 @@ impl std::fmt::Debug for Cartridge {
}

impl Cartridge {
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, Error> {
pub fn try_from_ines(bytes: &[u8]) -> Result<Self, Error> {
let header = Header::try_from_bytes(bytes)?;

let prg_rom_size = header.prg_rom_pages as usize * PRG_ROM_PAGE_SIZE;
Expand All @@ -113,8 +46,7 @@ impl Cartridge {
let chr_rom_start = prg_rom_start + prg_rom_size;
let prg_rom = bytes[prg_rom_start..prg_rom_start + prg_rom_size].to_vec();
let chr_rom = bytes[chr_rom_start..chr_rom_start + chr_rom_size].to_vec();
let prg_ram_size = PRG_RAM_SIZE;
let prg_ram = vec![0_u8; prg_ram_size];
let prg_ram = vec![0_u8; PRG_RAM_SIZE];
let chr_ram_size = (header.chr_rom_pages == 0) as usize * CHR_RAM_PAGE_SIZE;
let chr_ram = vec![0_u8; chr_ram_size];

Expand Down Expand Up @@ -207,7 +139,7 @@ mod tests {

#[test]
fn test_load_rom() {
let rom = Cartridge::try_from_bytes(&NESTEST_ROM);
let rom = Cartridge::try_from_ines(&NESTEST_ROM);

assert!(rom.is_ok());
}
Expand Down
Empty file added crates/mes-core/src/rom/fds.rs
Empty file.
62 changes: 62 additions & 0 deletions crates/mes-core/src/rom/ines.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#[cfg(feature = "json")]
use serde::Serialize;

use crate::{error::Error, utils::BitFlag};

use super::Mirroring;

pub const INES_ASCII: [u8; 4] = [0x4E, 0x45, 0x53, 0x1A];
pub const INES_HEADER_SIZE: usize = 16;
pub const TRAINER_SIZE: usize = 512;

pub fn is_ines_file(bytes: &[u8]) -> bool {
bytes[0..4] == INES_ASCII
}

#[derive(Debug)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub struct Header {
pub prg_rom_pages: u8,
pub chr_rom_pages: u8,
pub prg_ram_pages: u8,
pub mirroring: Mirroring,
pub battery: bool,
pub trainer: bool,
pub mapper: u8,
}

impl Header {
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, Error> {
if !is_ines_file(bytes) {
return Err(Error::UnsupportedFileFormat);
}

let prg_rom_pages = *bytes.get(4).ok_or(Error::eof("PRG ROM pages", 1))?;
let chr_rom_pages = *bytes.get(5).ok_or(Error::eof("CHR ROM pages", 1))?;
let flags_6 = bytes.get(6).ok_or(Error::eof("Flags 6", 1))?;
let flags_7 = bytes.get(7).ok_or(Error::eof("Flags 7", 1))?;
let prg_ram_pages = *bytes.get(8).ok_or(Error::eof("PRG RAM pages", 1))?;

let battery = flags_6.contains(1);
let trainer = flags_6.contains(2);
let mapper = (flags_7 & 0xF0) | (flags_6 >> 4);
let is_vertical_mirroring = flags_6.contains(0);
let is_four_screen = flags_6.contains(3);

let mirroring = match (is_four_screen, is_vertical_mirroring) {
(true, _) => Mirroring::FourScreen,
(false, true) => Mirroring::Vertical,
(false, false) => Mirroring::Horizontal,
};

Ok(Self {
prg_rom_pages,
prg_ram_pages,
chr_rom_pages,
mirroring,
battery,
trainer,
mapper,
})
}
}
17 changes: 17 additions & 0 deletions crates/mes-core/src/rom/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// https://www.nesdev.org/wiki/INES

pub mod cartridge;
pub mod fds;
pub mod ines;

#[cfg(feature = "json")]
use serde::Serialize;

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "json", derive(Serialize))]
pub enum Mirroring {
Vertical,
Horizontal,
OneScreen,
FourScreen,
}

0 comments on commit c0c5239

Please sign in to comment.