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.