|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scroll #289 and codec policy #290). More...
Go to the source code of this file.
Data Structures | |
| struct | jof_info_t |
| Parsed + validated geometry of one JOF atlas. More... | |
| struct | jof_memstore_t |
| Append-only memory store: the simplest atlas backing (RAM/SDRAM). More... | |
Typedefs | |
| typedef ra8_err_t(* | jof_pread_fn) (void *ctx, uint64_t offset, uint8_t *buf, size_t len, size_t *got) |
| Positioned-read seam over an atlas backing store (DIP). | |
Enumerations | |
| enum | jof_layout_t : uint8_t { k_jof_hdr_bytes = 32U , k_jof_footer_bytes = 16U , k_jof_index_entry = 8U , k_jof_magic_len = 4U , k_jof_ofs_magic = 0U , k_jof_ofs_width = 4U , k_jof_ofs_height = 6U , k_jof_ofs_tile_w = 8U , k_jof_ofs_tile_h = 10U , k_jof_ofs_bpp = 12U , k_jof_ofs_codec = 13U , k_jof_ofs_reserved = 14U , k_jof_ofs_tile_count = 16U , k_jof_ofs_reserved2 = 20U , k_jof_ftr_index_off = 0U , k_jof_ftr_tile_count = 4U , k_jof_ftr_total_size = 8U , k_jof_ftr_magic = 12U , k_jof_idx_ofs_offset = 0U , k_jof_idx_ofs_length = 4U } |
| Fixed byte sizes and offsets of the JOF on-disk structures. More... | |
| enum | jof_limits_t : uint32_t { k_jof_max_dim = 32768U , k_jof_max_tiles = 65536U , k_jof_bpp_max = 4U } |
| Hard caps every JOF atlas must satisfy (fail-closed validation). More... | |
| enum | jof_codec_t : uint8_t { k_jof_codec_raw = 0U , k_jof_codec_deflate = 1U } |
| Per-atlas tile codec selector (header byte 13). More... | |
Functions | |
| ra8_err_t | jof_memstore_sink (void *ctx, const uint8_t *buf, size_t len) |
| Append len bytes to a jof_memstore_t (producer sink). | |
| ra8_err_t | jof_memstore_pread (void *ctx, uint64_t offset, uint8_t *buf, size_t len, size_t *got) |
| Positioned read from a jof_memstore_t (reader seam). | |
| ra8_err_t | jof_parse (jof_pread_fn pread, void *pread_ctx, uint64_t total_size, jof_info_t *out_info) |
| Parse + validate a JOF atlas's header, footer and index bounds. | |
| ra8_err_t | jof_tile_dims (const jof_info_t *info, uint16_t tile_x, uint16_t tile_y, uint16_t *out_w, uint16_t *out_h) |
| Report the true (edge-clamped) pixel dimensions of one tile. | |
| uint32_t | jof_stored_bound (uint32_t raw_bytes) |
| Worst-case stored-tile byte bound for scratch/cell sizing. | |
| ra8_err_t | jof_read_tile (jof_pread_fn pread, void *pread_ctx, const jof_info_t *info, uint16_t tile_x, uint16_t tile_y, uint8_t *scratch, uint32_t scratch_cap, uint8_t *out_px, uint32_t out_cap, uint16_t *out_w, uint16_t *out_h) |
| Read + decode one tile into caller pixels, in bounded RAM. | |
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scroll #289 and codec policy #290).
A huge raster (a manga page or longstrip slice whose decoded size exceeds the ~10 MB SDRAM working set) cannot be decoded whole on this device, and JPEG/PNG offer no random access. JOF – the Jump-Offset Format, named for the access pattern below – solves both at import time: the source image is transcoded once (jof_produce()) into a grid of independently decodable tiles plus a per-tile byte index, so any tile pages in later with one bounded read + one bounded inflate. A reader parses the fixed-size footer, jumps to the index, reads the wanted tile's byte offset, and jumps straight there – hence jump-offset: O(1) random access at full resolution, never a downscale.
One format serves three consumers:
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | magic "JOF1" |
| 4 | 2 | u16 image width, pixels (1..32768) |
| 6 | 2 | u16 image height, pixels (1..32768) |
| 8 | 2 | u16 tile width, pixels (1..width cap) |
| 10 | 2 | u16 tile height, pixels (1..height cap) |
| 12 | 1 | u8 bytes per pixel: 1=gray8, 3=RGB888, 4=RGBA8888 |
| 13 | 1 | u8 tile codec: 0=raw, 1=raw DEFLATE (RFC 1951) |
| 14 | 2 | u16 reserved, must be 0 |
| 16 | 4 | u32 tile count, must equal tile_cols * tile_rows |
| 20 | 12 | reserved, must be 0 |
Tile n (n = tile_y * tile_cols + tile_x, row-major) occupies [index[n].offset, index[n].offset + index[n].length). Edge tiles carry their true clamped dimensions; a tile's decoded payload is exactly tw * th * bpp bytes of tightly packed row-major pixels, where tw = min(tile_w, width - tile_x * tile_w) and likewise for th.
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | u32 tile byte offset (absolute, from atlas byte 0) |
| 4 | 4 | u32 tile byte length |
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | u32 index_offset (absolute) |
| 4 | 4 | u32 tile count, must equal the header field |
| 8 | 4 | u32 total atlas size in bytes (self-check) |
| 12 | 4 | magic "JOFE" |
The index trails the tile streams so a producer can emit the whole atlas through an append-only sink (SD file write, ZIP store) in one forward pass; a reader locates the index via the footer. Atlases are capped at 4 GiB (u32 offsets) and 65536 tiles.
Re-encoding tiles as JPEG would stack a second lossy generation on the source image, which the no-quality-loss rule forbids; DEFLATE is lossless, already in-tree (miniz, reused via ra8_compress/ra8_decompress), decodes a 64 KiB tile in bounded RAM with zero heap, and compresses manga/longstrip line art well. Raw (codec 0) remains for zero-decode paging of already-tiny atlases.
Atlases arrive from untrusted EPUB content. jof_parse() and jof_read_tile() are fail-closed: every geometry field, both magics, the reserved bytes, the tile-count cross-checks, the index window and every per-tile offset/length/decoded-size are validated before any pixel is trusted.
Definition in file jof.h.
| typedef ra8_err_t( * jof_pread_fn) (void *ctx, uint64_t offset, uint8_t *buf, size_t len, size_t *got) |
Positioned-read seam over an atlas backing store (DIP).
The reader never assumes what holds the atlas bytes: a stored ZIP entry (epub_entry_pread), an SD file, or a RAM region all plug in behind this signature. A short read (*got < len) at the backing's tail is legal; reads past the end report *got == 0.
| [in] | ctx | Backing-specific context. |
| [in] | offset | Byte offset into the atlas. |
| [out] | buf | Destination buffer (len writable bytes). |
| [in] | len | Bytes requested. |
| [out] | got | Bytes actually read. |
| enum jof_codec_t : uint8_t |
| enum jof_layout_t : uint8_t |
Fixed byte sizes and offsets of the JOF on-disk structures.
Byte offsets are relative to the region they index (header fields from atlas byte 0, footer fields from the footer start). See the file comment for the authoritative layout tables.
| enum jof_limits_t : uint32_t |
Hard caps every JOF atlas must satisfy (fail-closed validation).
The dimension cap bounds every producer/reader loop (NASA Rule 2); the tile-count cap bounds the index (512 KiB at 8 bytes/entry). k_jof_bpp_max is the largest legal bytes-per-pixel.
| Enumerator | |
|---|---|
| k_jof_max_dim | Max image width/height, pixels. |
| k_jof_max_tiles | Max tiles per atlas. |
| k_jof_bpp_max | Max bytes per pixel. |
|
nodiscard |
Positioned read from a jof_memstore_t (reader seam).
Matching jof_pread_fn: bind with ctx = &store. Reads clamp at store->len; a read at/after the end reports *got == 0 without error, mirroring epub_entry_pread.
| [in] | ctx | Store to read from (a jof_memstore_t*). |
| [in] | offset | Byte offset into the stored atlas. |
| [out] | buf | Destination buffer. |
| [in] | len | Bytes requested. |
| [out] | got | Bytes actually copied (possibly short at the tail). |
| k_ra8_ok | Window read (short reads included). |
| k_ra8_err_null_ptr | ctx, store->buf, buf, or got is NULL. |
ctx points at a store previously filled through the sink. buf holds len writable bytes. buf. Definition at line 177 of file jof.c.
References jof_memstore_t::buf, k_ra8_ok, jof_memstore_t::len, memcpy(), RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ls_open_strip(), mg_build_atlas(), and mg_setup_cache().
|
nodiscard |
Append len bytes to a jof_memstore_t (producer sink).
Matching jof_sink_fn shape (see the producer header): bind with ctx = &store. Fails closed when the store is full so a hostile source can never write past cap.
| [in] | ctx | Store to append to (a jof_memstore_t*). |
| [in] | buf | Bytes to append. |
| [in] | len | Byte count (0 is a no-op). |
| k_ra8_ok | Bytes appended; store->len advanced. |
| k_ra8_err_null_ptr | ctx, store->buf, or buf is NULL. |
| k_ra8_err_no_mem | The append would exceed store->cap. |
ctx points at an initialised store (buf/cap set). buf holds len readable bytes. len bytes were copied at the old len. Definition at line 163 of file jof.c.
References jof_memstore_t::buf, jof_memstore_t::cap, k_ra8_err_no_mem, k_ra8_ok, jof_memstore_t::len, memcpy(), RA8_CHECK_NULL_PTR, and s_tag.
Referenced by mg_build_atlas().
|
nodiscard |
Parse + validate a JOF atlas's header, footer and index bounds.
Reads the 32-byte header at offset 0 and the 16-byte footer at total_size - 16, then cross-checks every field fail-closed: both magics, non-zero geometry within jof_limits_t, legal bpp/codec, zeroed reserved bytes, tile_count == cols * rows in both header and footer, the footer's total_size against the caller-supplied backing size, and the index window [index_off, index_off + 8 * tile_count + 16] == total_size. Per-tile offset/length windows are validated later, per read, by jof_read_tile() (the index itself may be larger than any bounded parse buffer).
| [in] | pread | Backing read seam (non-NULL). |
| [in] | pread_ctx | Context for pread. |
| [in] | total_size | Backing size in bytes (entry/file/store length). |
| [out] | out_info | Receives the validated geometry. |
| k_ra8_ok | Atlas structurally valid; info filled. |
| k_ra8_err_null_ptr | pread or out_info is NULL. |
| k_ra8_err_invalid_size | total_size cannot hold header+footer or exceeds the u32 format cap. |
| k_ra8_err_validation_failed | A magic/geometry/cross-check failed. |
| other | Propagated from pread. |
pread serves the atlas bytes for [0, total_size). out_info is writable. Definition at line 379 of file jof.c.
References internal_check_cross(), internal_parse_header_region(), internal_pread_exact(), internal_rd_u32(), k_jof_footer_bytes, k_jof_ftr_magic, k_jof_hdr_bytes, k_jof_magic_len, k_jof_ofs_tile_count, k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, memcmp(), RA8_CHECK_NULL_PTR, and s_tag.
Referenced by internal_accept(), internal_require_jof(), internal_verify_jof(), jof_audit(), jof_audit_requirements(), longstrip_open(), mg_build_atlas(), and priv_viewer_open_jof().
|
nodiscard |
Read + decode one tile into caller pixels, in bounded RAM.
Fetches the tile's index entry (one 8-byte pread), validates its window against the tile-stream region, reads the stored stream, and decodes it: raw tiles are pread directly into out_px; deflate tiles are pread into scratch and inflated with ra8_decompress() (zero heap). The decoded byte count must equal the tile's exact payload size or the read fails closed. Resident cost is scratch_cap + out_cap, independent of the image size – the property #231 needs for decode-on-demand paging.
| [in] | pread | Backing read seam (non-NULL). |
| [in] | pread_ctx | Context for pread. |
| [in] | info | Parsed atlas geometry. |
| [in] | tile_x | Tile column, [0, tile_cols). |
| [in] | tile_y | Tile row, [0, tile_rows). |
| [out] | scratch | Stored-stream staging (deflate codec only; may be NULL for raw atlases). |
| [in] | scratch_cap | Capacity of scratch; must cover jof_stored_bound() of the tile payload for deflate atlases. |
| [out] | out_px | Destination pixel buffer. |
| [in] | out_cap | Capacity of out_px; must cover the payload. |
| [out] | out_w | Receives the tile's clamped width, pixels. |
| [out] | out_h | Receives the tile's clamped height, pixels. |
| k_ra8_ok | Tile decoded into out_px. |
| k_ra8_err_null_ptr | A required pointer is NULL. |
| k_ra8_err_out_of_range | tile_x / tile_y outside the grid. |
| k_ra8_err_invalid_size | out_cap (or scratch_cap) too small for this tile. |
| k_ra8_err_validation_failed | Index/stream window corrupt, short read, or decoded size mismatch. |
| other | Propagated from pread. |
info came from a successful jof_parse() over the same backing. out_px holds out_cap writable bytes. out_px content is unspecified. Definition at line 637 of file jof.c.
References jof_info_t::bpp, internal_fetch_decode(), internal_read_args_ok(), jof_tile_dims(), k_ra8_err_invalid_size, k_ra8_ok, and jof_info_t::tile_cols.
Referenced by internal_audit_tile(), internal_compare(), internal_preflight(), longstrip_tile_decode(), and mg_tile_decode().
|
nodiscard |
Worst-case stored-tile byte bound for scratch/cell sizing.
For raw tiles the stored stream equals the payload; for deflate the stored stream is bounded by the incompressible-input expansion raw + raw/8 + 256 (a safe over-estimate of the miniz raw-DEFLATE worst case). Size jof_read_tile()'s scratch with this over raw = tile_w * tile_h * bpp.
| [in] | raw_bytes | Decoded tile payload size in bytes. |
| >=raw_bytes | Always at least the payload size plus margin. |
raw_bytes is a real tile payload size (fits uint32_t with margin). raw_bytes + 256. Worst-case stored-tile byte bound for scratch/cell sizing.
Definition at line 439 of file jof.c.
References k_jof_bound_add, and k_jof_bound_div.
Referenced by internal_carve_pixel_path(), internal_require_jof(), jof_audit_requirements(), jof_work_bytes(), priv_viewer_open_jof(), and ra8_fmt_jof_verify_requirements().
|
nodiscard |
Report the true (edge-clamped) pixel dimensions of one tile.
| [in] | info | Parsed atlas geometry. |
| [in] | tile_x | Tile column, [0, tile_cols). |
| [in] | tile_y | Tile row, [0, tile_rows). |
| [out] | out_w | Receives the tile's width, pixels. |
| [out] | out_h | Receives the tile's height, pixels. |
| k_ra8_ok | Dimensions reported. |
| k_ra8_err_null_ptr | info, out_w, or out_h is NULL. |
| k_ra8_err_out_of_range | tile_x / tile_y outside the grid. |
info came from a successful jof_parse(). out_w and out_h are writable. Definition at line 414 of file jof.c.
References jof_info_t::height, k_ra8_err_out_of_range, k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, jof_info_t::tile_cols, jof_info_t::tile_h, jof_info_t::tile_rows, jof_info_t::tile_w, and jof_info_t::width.
Referenced by internal_audit_tile(), and jof_read_tile().