Expand description
Typed handles to the Game Boy’s High RAM (HRAM, 0xFF80..=0xFFFE).
HRAM is a 127-byte region the CPU can still reach while an OAM DMA holds the
bus, and the ldh instructions address it in a single byte. Cells declared
with the hram! macro are read and written with the immediate ldh (n)
form (2 bytes / 3 cycles): the linker assigns each cell a fixed HRAM address
and the low byte is baked into the instruction. That is faster and smaller
than the 3-byte / 4-cycle absolute ld (nn) used for WRAM.
§Which kind to declare
An access one byte wide is a single instruction, and the CPU takes interrupts only between instructions, so it cannot be observed half done. A wider access is several instructions and an interrupt landing in the middle leaves the reader with a value that never existed. The three kinds differ in what they do about that.
| Kind | Width | Access |
|---|---|---|
HramAtomicCell<T> | one byte | get() / set() |
HramCell<T> | up to MAX_BYTES | get(cs) / set(cs, v) |
HramArea<N> | any | raw pointers |
HramCell takes a CriticalSection because nothing else can make a
multi-instruction access indivisible on this CPU. Obtaining the token is the
caller’s business; a cell reached only from the main loop, never from an
interrupt handler, still needs one.
Both cells hold a CellValue, which under the bank-safe feature also has to
survive a bank switch.
§Examples
#![feature(asm_experimental_arch)]
use gb_hram::hram;
hram! {
/// Frames elapsed, bumped by the VBlank handler.
pub static FRAME: HramAtomicCell<u8>;
static SCROLL: HramCell<ScrollState>;
static OAM_DMA: HramArea<13>;
}
fn tick() {
FRAME.set(FRAME.get().wrapping_add(1)); // ldh a,(n) / ldh (n),a
}Write static NAME as "symbol": ...; to export the storage under a fixed
symbol, to share a cell with C or assembly. The symbol is emitted with the
target’s usual prefix.
The accessors emit ldh inline asm in the calling crate, so that crate needs
#![feature(asm_experimental_arch)].
§Zero initialisation
HRAM is NOLOAD, so nothing is loaded from ROM, and a conforming runtime is
required to clear 0xFF80..=0xFFFE before main. A cell whose type has a
valid all-zero bit pattern therefore starts at 0 and may be read before it
is first written; any other type must be written first.
§Feature flags
bank-safe— Require every cell value to beBankSafe, so a pointer to banked code cannot be parked in HRAM and outlive its bank.
Modules§
- prelude
- Common imports for HRAM access (
use gb_hram::prelude::*).
Macros§
- hram
- Declare static HRAM cells and areas, each at a linker-assigned High RAM address.
Structs§
- Critical
Section - Critical section token.
- Hram
Area - A raw, fixed-size region of High RAM, addressed through pointers.
- Hram
Atomic Cell - Storage for a one-byte cell, accessed without a
CriticalSection. - Hram
Cell - Storage for a cell read and written under a
CriticalSection.
Constants§
- MAX_
BYTES - The widest
HramCellvalue an access unrolls into straight-lineldhs. HRAM is only 127 bytes, so cells are small; a wider type is a compile error.
Traits§
- Cell
Value bank-safe - What an HRAM cell may hold.
- Hram
Access - Read and write an HRAM cell under a
CriticalSection. - Hram
Atomic Access - Read and write a one-byte HRAM cell without a
CriticalSection.