Skip to main content

Gtrom111

Struct Gtrom111 

Source
pub struct Gtrom111 { /* private fields */ }
Expand description

Mapper 111 (GTROM / Cheapocabra), written from nesdev_wiki/output/GTROM.md (v2.9.6 “Roster”: the register window, bonus RAM and self-flashing were added and the board promoted to Curated).

  • Register (GRNC PPPP): 32 KiB PRG bank, 8 KiB CHR-RAM bank, 8 KiB nametable page, and two LEDs. The latch clocks when /ROMSEL, A14 and A12 are all high, which is $5000-$5FFF and $7000-$7FFF and nowhere else; $6000-$6FFF is not decoded. A read there latches too, with the value floating on the bus (“reading from the register effectively writes the value of open bus”), which is what Mapper::notify_floating_read exists for.
  • PPU RAM is one 32 KiB chip. The pattern tables use one of its first two 8 KiB pages, and PPU $2000-$3EFF one of its last two, unmirrored. Each nametable page therefore holds the four nametables plus almost 4 KiB of bonus RAM at $3000-$3EFF. The console’s CIRAM is disabled.
  • PRG is an SST39SF040 (sst39sf040.rs). Writes to $8000-$FFFF are its commands; command addresses are A14-A0, so 5555h is CPU $D555 and 2AAAh is $AAAA in any bank. The flashed image is the board’s battery save (Mapper::save_data; sram() stays empty, since no RAM sits at $6000), and a save state carries only the sectors that differ from the ROM.

The LEDs have no emulated effect. Their bits are kept in the register so a debugger shows them.

Implementations§

Source§

impl Gtrom111

Source

pub fn new(prg_rom: Box<[u8]>, _chr_rom: &[u8]) -> Result<Self, MapperError>

Construct a new mapper 111 board.

§Errors

Returns MapperError::Invalid when PRG is not a non-zero multiple of 32 KiB.

Trait Implementations§

Source§

impl Mapper for Gtrom111

Source§

fn save_data(&self) -> &[u8] ⓘ

The flash image: what a self-flashing GTROM game saves to. There is no RAM at $6000, so sram() stays empty.

Source§

fn cpu_read_unmapped(&self, addr: u16) -> bool

The register is write-only and nothing else lives below $8000.

Source§

fn caps(&self) -> MapperCaps

v2.8.0 Phase 4 — the mapper’s per-CPU-cycle capability flags. Read more
Source§

fn save_data_mut(&mut self) -> &mut [u8] ⓘ

Mutable Self::save_data, for loading a save.
Source§

fn clear_save_data(&mut self)

Return the save data to the state of a cartridge that has never been saved to. That is zeroed RAM by default. On a flash board it is the PRG image as loaded, since a zero-filled flash would be a ROM with no program in it. A power-on movie calls this (power_on_for_movie).
Source§

fn notify_floating_read(&mut self, addr: u16, value: u8)

A CPU read the mapper declined (Self::cpu_read_unmapped) has just completed, and value is what floated on the bus. Read more
Source§

fn cpu_read(&mut self, addr: u16) -> u8

Read a byte from the CPU address space $4020-$FFFF.
Source§

fn cpu_write(&mut self, addr: u16, value: u8)

Write a byte to the CPU address space $4020-$FFFF.
Source§

fn ppu_read(&mut self, addr: u16) -> u8

Read a byte from the PPU address space $0000-$3FFF (pattern table Read more
Source§

fn ppu_write(&mut self, addr: u16, value: u8)

Write a byte to the PPU address space $0000-$3FFF.
Source§

fn nametable_unfolded(&self) -> bool

Whether PPU $3000-$3EFF is independent RAM on this cartridge rather than a mirror of $2000-$2EFF. Read more
Source§

fn nametable_fetch(&mut self, addr: u16) -> Option<u8>

Optionally synthesize a nametable byte for addr ($2000-$3EFF). Read more
Source§

fn nametable_write(&mut self, addr: u16, value: u8) -> bool

Optionally absorb a nametable write for addr ($2000-$3EFF) directly into mapper-resident storage. Read more
Source§

fn current_mirroring(&self) -> Mirroring

Returns the mapper’s current effective mirroring layout. Read more
Source§

fn debug_info(&self) -> MapperDebugInfo

Surface read-only debug info for the UI. Override per mapper to expose bank registers, IRQ counters, etc. Default returns a minimal entry naming the mapper id.
Source§

fn save_state(&self) -> Vec<u8> ⓘ

Encode the mapper’s mutable state into a tagged save-state blob.
Source§

fn load_state(&mut self, data: &[u8]) -> Result<(), MapperError>

Decode a previously Mapper::save_state blob back into the mapper. Read more
Source§

fn notify_ppu_register_write(&mut self, _addr: u16, _value: u8)

The CPU wrote value to the PPU register window ($2000-$3FFF), at the undecoded address addr. Read more
Source§

fn cpu_read_driven_mask(&self, _addr: u16) -> u8

Which data bits a mapped read in the register window ($4020-$5FFF) actually drives; the rest float and keep the bus’s open-bus value. Read more
Source§

fn ppu_read_sprite(&mut self, addr: u16) -> u8

Read a byte from the PPU pattern-table window ($0000-$1FFF) on behalf of a sprite tile fetch. MMC5 in 8x16 sprite mode uses a separate set of CHR bank registers ($5120-$5127) for sprite fetches; other mappers default to forwarding to Mapper::ppu_read.
Source§

fn chr_phys(&self, _addr: u16) -> Option<u32>

HD-pack tile identity: the ABSOLUTE post-banking offset into CHR-ROM for a pattern-space address $0000-$1FFF (Some(offset)), or None for CHR-RAM (content-hashed instead). tile_index = offset / 16 is the key Mesen uses for CHR-ROM <tile> replacements. Default None so an unported mapper falls back to the content-hash path (no worse than before); the common CHR-ROM mappers override it by exposing their internal CHR mapping.
Source§

fn chr_reads_are_pure(&self) -> bool

v3.1.0 (T-SPRITE-LIMIT) — whether Self::ppu_read and Self::ppu_read_sprite on $0000-$1FFF change nothing but return a byte. true (the default) lets the PPU’s “disable sprite limit” option make extra, display-only pattern reads on this board. Read more
Source§

fn set_mmc3_revision_override( &mut self, _revision: Option<Mmc3Revision>, ) -> bool

v3.1.0 (T-MMC3-NEC-OVERRIDE, ACC-13) — force an MMC3’s IRQ revision (Some), or return to the one its header selected (None). Returns whether this board is an MMC3 that applied it; every other board ignores it (the default). Lets an iNES 1.0 dump, which cannot name its MMC3 revision, run under the alternate (Nec) behaviour.
Source§

fn peek_ex_attribute(&mut self, _v: u16) -> Option<ExAttribute>

Optionally provide per-tile extended attribute + CHR-bank override for the BG tile currently being fetched. Read more
Source§

fn bg_split_state( &mut self, _scanline_y: u16, _coarse_x: u16, ) -> Option<BgSplitState>

Optionally redirect a BG fetch group into a vertical split-screen “alt region”. Read more
Source§

fn nametable_address(&self, addr: u16) -> u16

Resolve a nametable address in $2000-$3EFF to a CIRAM offset in 0..0x800. The PPU owns the 2 KiB CIRAM and uses this hook to apply per-mapper mirroring without giving the mapper direct access to the console-side VRAM. Read more
Source§

fn notify_a12(&mut self, _level: bool)

Notify of a PPU A12 line transition. Default no-op; MMC3 / MMC5 override this for IRQ counter clocking.
Source§

fn notify_a12_at_sub_dot(&mut self, level: bool, _sub_dot: u8)

Notify of a PPU A12 line transition with the current sub-dot of the host CPU cycle (0 / 1 = M2-low half; 2 = M2-high half). Default impl falls through to Self::notify_a12 so existing mappers compile unchanged; MMC3 overrides this for the M2-phase-aware IRQ-output propagation delay required by mmc3_test_2/4-scanline_timing sub-test #3 (C1 step B4 successor).
Source§

fn notify_cpu_cycle(&mut self)

Notify of a CPU cycle. Default no-op; VRC2/4/6, FME-7, Namco 163 override this for IRQ counter clocking.
Source§

fn reset(&mut self)

The console’s RESET button (a soft reset, not a power cycle). Read more
Source§

fn notify_frame_event(&mut self, _events: MapperFrameEvents)

Notify the mapper of the APU frame-counter events fired on the current CPU cycle (quarter-frame envelope clock, half-frame length clock). Only on-cart audio extensions that re-use the 2A03 frame counter cadence need to handle this (MMC5 audio’s two pulse channels). Default no-op.
Source§

fn notify_scanline_start(&mut self)

Notify the mapper that the PPU is starting a new rendered scanline. Read more
Source§

fn notify_vblank(&mut self)

Notify the mapper that the PPU has entered vertical blank. Read more
Source§

fn enable_vs_dual_wram(&mut self)

v2.0.0 beta.5 (Vs. DualSystem): provision the board’s shared 2 KiB work RAM at $6000-$7FFF (mirrored across the 8 KiB window — MAME vsnes.cpp: map(0x6000, 0x67ff).mirror(0x1800).ram()). Only the Vs. System board (mapper 99) implements this — the DualSystem cabinets carry a 2 KiB RAM shared between the two consoles, absent on UniSystem carts (whose $6000 window stays open bus, byte-identically). Called by the VsDualSystem wrapper at construction on both consoles: each console holds its own COPY, and the wrapper converges the copies by draining the write log (below) after every stepped instruction — MAME’s fully-shared .share("nvram") model at soft-lockstep granularity. Default no-op.
Source§

fn set_vs_dual_sub(&mut self)

v2.0.0 beta.5 (Vs. DualSystem): mark this mapper instance as the cabinet’s SUB console — it banks the second 32 KiB PRG half and the upper CHR pages (the two CPUs run DIFFERENT programs; MAME balonfgt loads distinct sub-region ROMs, Mesen2 uses prgOuter = IsVsMainConsole() ? 0 : 4). Applied by the VsDualSystem wrapper at construction, like the bus’s sub identity. Default no-op.
Source§

fn drain_vs_dual_wram_writes(&mut self, dst: &mut Vec<(u16, u8)>)

v2.0.0 beta.5 (Vs. DualSystem): drain this console’s shared-WRAM write log — every (offset, value) the CPU wrote to the window since the last drain, in order — by APPENDING into dst (never clearing it first). The wrapper replays them into the partner’s copy (Self::apply_vs_dual_wram_write), which is what makes the RAM behave as ONE simultaneously-shared memory (MAME’s model; nesdev also documents a $4016-bit-1 access mux, but MAME — where the four DualSystem games verifiably run — shares the RAM unconditionally, and Balloon Fight’s boot handshake requires the partner to see writes made while the mux would deny it access). Read more
Source§

fn take_vs_dual_wram_writes(&mut self) -> Vec<(u16, u8)>

Convenience wrapper around Self::drain_vs_dual_wram_writes for callers that don’t already hold a reusable buffer (diagnostics, tests) — NOT used by the hot pump_comms path, which owns and reuses its own scratch buffer instead.
Source§

fn apply_vs_dual_wram_write(&mut self, offset: u16, value: u8)

v2.0.0 beta.5 (Vs. DualSystem): replay one partner-console write into this console’s copy of the shared WRAM (see Self::take_vs_dual_wram_writes). Does NOT re-log the write (no echo loop). Default no-op.
Source§

fn take_vs_dual_wram(&mut self) -> Option<Box<[u8]>>

v2.0.0 beta.5 (Vs. DualSystem): take the console’s shared-WRAM copy (used by the wrapper’s snapshot-restore normalization — the two copies are re-converged from one buffer after a restore). Returns None on boards without the dual WRAM. Default None.
Source§

fn set_vs_dual_wram(&mut self, wram: Box<[u8]>)

v2.0.0 beta.5 (Vs. DualSystem): install a shared-WRAM copy (the other half of the restore normalization). Default no-op.
Source§

fn irq_pending(&self) -> bool

Returns true if the mapper is currently asserting an IRQ.
Source§

fn irq_acknowledge(&mut self)

Acknowledge a pending IRQ. Default no-op; mappers that latch IRQ state override this.
Source§

fn mix_audio(&mut self) -> i32

Return one signed audio sample for mappers with on-cart audio (VRC6/7, MMC5, Sunsoft 5B, Namco 163, FDS). Default returns silence. Read more
Source§

fn has_hardwired_mirroring(&self) -> bool

Whether this mapper’s nametable mirroring is hardwired by the cartridge (solder pads / the iNES header bit) rather than controlled by the mapper’s own registers at runtime. Read more
Source§

fn disk_side_count(&self) -> usize

Number of disk sides in the inserted image (0 for non-FDS mappers).
Source§

fn inserted_disk_side(&self) -> Option<usize>

The currently inserted disk side index, or None when ejected (or for non-FDS mappers).
Source§

fn set_disk_side(&mut self, _side: Option<usize>)

Insert disk side i (Some) or eject the disk (None). No-op for non-FDS mappers; an out-of-range index is ignored by the FDS device.
Source§

fn sram(&self) -> &[u8] ⓘ

Returns a reference to the mapper’s internal SRAM/PRG-RAM. By default, returns an empty slice if unsupported.
Source§

fn sram_mut(&mut self) -> &mut [u8] ⓘ

Returns a mutable reference to the mapper’s internal SRAM/PRG-RAM. By default, returns an empty mutable slice if unsupported.
Source§

fn enable_fds_trace(&mut self)

Start recording the diagnostic FDS read-stream trace (off by default; observation-only). No-op for non-FDS mappers. See crate::FdsTraceRec.
Source§

fn take_fds_trace(&mut self) -> Vec<FdsTraceRec>

Drain the accumulated FDS read-stream trace records (empty for non-FDS mappers / when tracing was never enabled).
Source§

fn disk_image_bytes(&self) -> Vec<u8> ⓘ

Re-serialize the (possibly-modified) disk image to its byte layout for host persistence. Returns an empty vector for non-FDS mappers.
Source§

fn disk_is_dirty(&self) -> bool

Whether the disk image has unsaved writes. Always false for non-FDS mappers.
Source§

fn clear_disk_dirty(&mut self)

Clear the disk dirty flag (a host calls this after persisting). No-op for non-FDS mappers.
Source§

fn set_disk_write_protected(&mut self, _protected: bool)

Mark the inserted disk read-only (true) or writable (false). No-op for non-FDS mappers.
Source§

fn nsf_song_count(&self) -> u8

Number of selectable songs (0 for a non-NSF mapper).
Source§

fn nsf_current_song(&self) -> u8

The currently-selected 0-based song (0 for a non-NSF mapper).
Source§

fn nsf_set_song(&mut self, _song: u8) -> bool

Select a 0-based song. Returns true if this is an NSF mapper (so the caller knows to re-run the reset that re-vectors into the driver’s init). Default no-op returning false.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.