Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

Crate psx_vram

Crate psx_vram 

Source
Expand description

Typed VRAM primitives.

PS1 VRAM is a 1024×512 halfword frame, and getting a sprite on screen is three interlocking decisions: where the texel bytes live, where the CLUT lives, and what format you’re in. PsyQ leaves those as short variables you pass around by convention. This crate promotes them to types.

§What’s here

  • Color555 – a 15bpp BGR pixel. Constructed via Color555::rgb8 (u8 RGB → 5-bit truncation), or Color555::rgb5 (already 5-bit), or the const raw constructor Color555::raw.
  • VramRect – an (x, y, w, h) in VRAM pixels with const validation of the bounds. Can’t construct one that would overflow VRAM.
  • TexturePage – a texture-page handle. Const constructor enforces the PSX alignment rules (x % 64 == 0, y ∈ {0, 256}), knows its bit-depth, and emits the GP0(E1h) draw-mode word or the 16-bit tpage field embedded in textured-rect UV words.
  • Clut – a CLUT handle. x % 16 == 0, y ∈ 0..512. Emits the 16-bit clut field for UV words. 4bpp and 8bpp CLUTs are the same underlying type – the calling primitive’s tpage picks which entry count it uses.
  • upload_16bpp – safe upload wrapper: checks pixels.len() matches rect.w * rect.h, packs to GP0 0xA0 + word stream.

§What’s NOT here (yet)

  • Compile-time tpage-overlap detection. A later pass can wrap allocations in a const-generic Layout<...> that enforces non-overlap across a fixed set of TexturePage/Clut declarations; kept out for now because the rules around the 16-pixel CLUT stride + tpage-row sharing get messy to express in bare Rust const generics, and a build-time allocator tool is a cleaner path when we’re ready.
  • TIM parsing. Runtime / proc-macro loading lives in psx-asset when it lands.
  • 4bpp / 8bpp upload helpers. PsyQ packs those as 16-bit halfwords too (4 / 2 texels per halfword); the same upload_16bpp works once the caller has pre-packed the indices. A typed upload_4bpp(rect, &[u8], clut) would be nicer; it’s one of the first obvious follow-ups.

§Why these types over PsyQ’s shorts

Every field has rules PsyQ leaves to the programmer. TexturePage X must be a multiple of 64; Y must be 0 or 256. CLUT X must be a multiple of 16. Upload sizes are clamped on hardware but wrap (wrap, not truncate) on the real DMA controller if you oversize them. Getting any of these wrong in PsyQ silently corrupts VRAM. Const-validating them at construction means the bug can’t compile – which is the whole point of writing a Rust SDK instead of a C one.

Structs§

Clut
A CLUT slot – 16 consecutive halfwords at (x, y) for 4bpp, or 256 consecutive halfwords for 8bpp. Const constructor asserts the 16-pixel X alignment hardware requires.
ClutRowAllocator
CLUT-row sub-allocator over a reserved band of ROWS VRAM rows.
Color555
A 15-bit BGR pixel as stored in VRAM.
TexturePage
A texture page: a 256×256 region at a specific VRAM origin, plus a depth.
TextureWindowAtlas
Tiny no-alloc atlas for PS1 texture-window-sized subtextures.
TextureWindowPlacement
Placement returned by TextureWindowAtlas::allocate.
VramAllocator
One owner for all of VRAM: texture pages, room-material windows, model strips and CLUT rows, with free. A coarse 64×16-pixel occupancy grid keeps page/strip/framebuffer reservations from overlapping; a composed TextureWindowAtlas sub-allocates room-material windows inside a reserved band; a ClutRowAllocator hands out CLUT rows.
VramRect
An (x, y, w, h) rectangle in VRAM coordinates.

Enums§

TextureDepth
Texture color depth – the last field of GP0(E1h) and bits 7..8 of a primitive’s tpage word.
VramHandle
A freeable handle to a VRAM reservation handed out by VramAllocator.

Constants§

TEXTURE_PAGE_TEXELS
Texture-page width and height in texels.
TEXTURE_WINDOW_UNIT_TEXELS
Texture-window granularity in texels.
VRAM_ALLOC_COLS
Number of 64-pixel columns across VRAM (16).
VRAM_ALLOC_ROWS
Number of 16-pixel rows down VRAM (32).
VRAM_HEIGHT
VRAM framebuffer height in pixels.
VRAM_WIDTH
VRAM framebuffer width in pixels.

Traits§

VramRegionSource
Source of VRAM regions for crates that should not depend on the whole VramAllocator type (e.g. psx-font). VramAllocator implements it.

Functions§

dma_copy_to_vram
Upload words to rect over block-mode DMA (channel 2) instead of word-at-a-time FIFO writes, and wait for it. This mirrors PsyQ’s LoadImage: BS = words-per-row, BA = rows.
dma_copy_to_vram_done
True once the transfer dma_copy_to_vram_start kicked has finished.
dma_copy_to_vram_start⚠
dma_copy_to_vram without the completion wait: send the copy header, kick the block DMA and return, so the CPU keeps working while channel 2 feeds the GPU. Poll dma_copy_to_vram_done; abort channel 2 (psx_io::dma::abort) if it never finishes. Returns false, having touched nothing, for a transfer the DMA cannot express (see dma_copy_to_vram).
first_vram_overlap
Index of the first pair of rectangles in rects that share a pixel.
upload_15bpp
Upload typed Color555 pixels – sugar over upload_16bpp for direct-color textures.
upload_16bpp
Upload raw 16bpp halfwords into a VRAM rect via GP0 0xA0 + word stream. Checks that pixels.len() * 2 == rect.w * rect.h – one halfword per pixel, and the FIFO ships 32-bit words containing two halfwords each. Odd pixel counts (which round up on hardware) panic because they’re rarely what the caller wanted.
upload_bytes
Upload raw byte-stream pixel data, interpreted as halfwords in little-endian order. Same semantics as upload_16bpp but accepts a &[u8] – useful when the data comes from include_bytes! of a cooked asset blob, where the returned byte array has alignment 1 and a direct &[u16] reinterpret would be undefined behaviour.
upload_bytes_aligned
Upload bytes using aligned word loads when possible. Unaligned and odd halfword counts retain upload_bytes’s zero-padded final-word behavior.
upload_clut
Upload a CLUT – a row of Color555s at clut. The caller picks the width: 16 entries for 4bpp, 256 for 8bpp. Asserts the CLUT fits in VRAM width and the slice length matches.
upload_words
Upload an already packed little-endian stream of two 16-bit VRAM pixels per word.
vram_layout_is_disjoint
True when no two rectangles in rects share a pixel. See first_vram_overlap for the pattern and why it is worth pinning.

Type Aliases§

TexDepthDeprecated
Renamed to TextureDepth.
TpageDeprecated
Renamed to TexturePage.