Skip to main content

Module sram

Module sram 

Source
Available on crate feature pak only.
Expand description

The cartridge’s own RAM, usually kept alive by a battery.

SRAM is only readable and writable while the controller has it switched on, so every access happens inside Sram::open, which switches it on for the closure and off again after. Leaving it off otherwise protects the contents while the console powers down or the cartridge is pulled.

§Declaring

use core::cell::Cell;
use gb_pak::{CriticalSection, sram};
use zerocopy::FromBytes;

#[repr(C)]
#[derive(FromBytes)]
struct Save {
    magic:   Cell<[u8; 4]>,
    version: Cell<u8>,
    hp:      Cell<u8>,
    gold:    Cell<u16>,
}

/// The save file.
#[sram(0)]
static FILE: Save;

fn hurt(cs: CriticalSection<'_>) {
    FILE.open(cs, |f| f.hp.set(f.hp.get().saturating_sub(1)));
}

A static has no initializer: the bytes are the cartridge’s already. A bank holds one of them, at its start (0xA000), and the attribute says which bank.

Turned down at compile time: a missing bank number, a bank the cartridge does not have, any bank when it has no SRAM, a value larger than one 8 KiB bank, and an initializer.

§Editing in place

The closure is handed a shared reference, so every field is written as a Cell, the way a peripheral crate writes a register block. A field that is not one can never be written.

unsafe { gb::interrupt::free(|cs| FILE.open(cs, |f| f.gold.set(f.gold.get() + 10))) };

§Trusting the contents

A cartridge that has never been written holds noise, so the value is bounded on [FromBytes]: no byte pattern may be invalid for it, which rules out bool, char, enums, and references.

repr(C) is recommended: a repr(Rust) layout is unspecified and may differ between toolchain versions, so a save an earlier build wrote could be read back wrong.

That bounds the type, not the contents. The bytes are still whatever survived: noise on a new cartridge, decay on a failing battery, another build’s layout after an update. Check a magic number, a schema version, and a checksum before believing a save.

Structs§

Sram
A value at the base of SRAM bank BANK.

Constants§

BANKS
SRAM banks this cartridge has, from ram_size in header.toml.
BANK_LEN
Bytes one bank holds.