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 viaColor555::rgb8(u8RGB → 5-bit truncation), orColor555::rgb5(already 5-bit), or theconstraw constructorColor555::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: checkspixels.len()matchesrect.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-assetwhen it lands. - 4bpp / 8bpp upload helpers. PsyQ packs those as 16-bit
halfwords too (4 / 2 texels per halfword); the same
upload_16bppworks once the caller has pre-packed the indices. A typedupload_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. - Clut
RowAllocator - CLUT-row sub-allocator over a reserved band of
ROWSVRAM rows. - Color555
- A 15-bit BGR pixel as stored in VRAM.
- Texture
Page - A texture page: a 256×256 region at a specific VRAM origin, plus a depth.
- Texture
Window Atlas - Tiny no-alloc atlas for PS1 texture-window-sized subtextures.
- Texture
Window Placement - Placement returned by
TextureWindowAtlas::allocate. - Vram
Allocator - 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 composedTextureWindowAtlassub-allocates room-material windows inside a reserved band; aClutRowAllocatorhands out CLUT rows. - Vram
Rect - An
(x, y, w, h)rectangle in VRAM coordinates.
Enums§
- Texture
Depth - Texture color depth – the last field of GP0(E1h) and bits 7..8 of a primitive’s tpage word.
- Vram
Handle - 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§
- Vram
Region Source - Source of VRAM regions for crates that should not depend on the whole
VramAllocatortype (e.g.psx-font).VramAllocatorimplements it.
Functions§
- dma_
copy_ to_ vram - Upload
wordstorectover block-mode DMA (channel 2) instead of word-at-a-time FIFO writes, and wait for it. This mirrors PsyQ’sLoadImage:BS = words-per-row,BA = rows. - dma_
copy_ to_ vram_ done - True once the transfer
dma_copy_to_vram_startkicked has finished. - dma_
copy_ ⚠to_ vram_ start dma_copy_to_vramwithout the completion wait: send the copy header, kick the block DMA and return, so the CPU keeps working while channel 2 feeds the GPU. Polldma_copy_to_vram_done; abort channel 2 (psx_io::dma::abort) if it never finishes. Returnsfalse, having touched nothing, for a transfer the DMA cannot express (seedma_copy_to_vram).- first_
vram_ overlap - Index of the first pair of rectangles in
rectsthat share a pixel. - upload_
15bpp - Upload typed
Color555pixels – sugar overupload_16bppfor 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_16bppbut accepts a&[u8]– useful when the data comes frominclude_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 atclut. 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
rectsshare a pixel. Seefirst_vram_overlapfor the pattern and why it is worth pinning.
Type Aliases§
- TexDepth
Deprecated - Renamed to
TextureDepth. - Tpage
Deprecated - Renamed to
TexturePage.