ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
sh_comic.c File Reference

Full-page image reader for CBZ / CBR comic archives (#236). More...

#include <string.h>
#include "comic.h"
#include "ra8_gfx.h"
#include "ra8_gfx_font.h"
#include "reflow_image.h"
#include "sh_app.h"
#include "sh_comic_fixture.h"
Include dependency graph for sh_comic.c:

Go to the source code of this file.

Data Structures

struct  sh_comic_blob_t
 Resident-buffer backing for the comic reader's seek+read seam. More...

Enumerations

enum  sh_comic_const_t : uint32_t {
  k_shc_page_cap = 1024U ,
  k_shc_names_cap = 128U * 1024U ,
  k_shc_pagebuf_cap = 4U * 1024U * 1024U ,
  k_shc_arena_cap = 8U * 1024U * 1024U ,
  k_shc_probe_w = 160U ,
  k_shc_probe_h = 120U ,
  k_shc_probe_bg = 0x202028U ,
  k_shc_live_bg = 0x101010U ,
  k_shc_fnv_offset = 2166136261U ,
  k_shc_fnv_prime = 16777619U ,
  k_shc_hex_digits = 8U ,
  k_shc_nib_bits = 4U ,
  k_shc_nib_mask = 0xFU ,
  k_shc_thirds = 3U
}
 Comic reader buffer + layout constants. More...

Functions

static size_t sh_comic_blob_read (void *ctx, uint64_t off, void *buf, size_t len)
 comic_read_fn over a resident archive buffer (bounds-clamped).
static uint32_t sh_comic_fnv (const void *p, size_t n)
 FNV-1a-32 over n bytes of p.
static bool sh_comic_bind (comic_read_fn rd, void *ctx, uint64_t size)
 Bind ::comic over rd + set g_sh.comic_count / page; ok on success.
static ra8_err_t sh_comic_blit_page (uint32_t page, int32_t x, int32_t y, int32_t w, int32_t h, int32_t *out_w, int32_t *out_h)
 Extract page page's encoded bytes and decode+blit into the box.
bool sh_comic_open (uint16_t idx)
 Open shelf entry idx as a comic archive (CBZ / CBR) for page reading.
void sh_comic_close (void)
 Close any open comic and release its backing (idempotent).
static int32_t sh_comic_center_x (const char *s)
 Centre-align s horizontally for the 8px bitmap font.
void sh_comic_render (void)
 Render the current comic page full-screen (title bar + fitted image).
int32_t sh_comic_edge_dir (int32_t x)
 Map a comic-screen edge tap to a reading-order page delta (RTL-aware).
bool sh_comic_turn (int32_t dir)
 Turn the comic page by dir in reading order, clamped to the ends.
bool sh_comic_tap (int32_t x, bool header)
 Handle a comic-screen tap: header returns to the shelf, else page-turn.
void sh_comic_toggle_rtl (void)
 Flip the comic reading direction (LTR <-> RTL); page index unchanged.
static sh_comic_probe_t sh_comic_probe_blob (const uint8_t *blob, uint32_t len)
 Open blob, decode its page 0 into the scratch, hash it; then close.
void sh_comic_selfcheck (sh_comic_probe_t *cbz, sh_comic_probe_t *cbr, bool *rtl_ok)
 Headless boot self-check: decode the baked CBZ + CBR page 0, verify RTL.
void sh_comic_append_banner (char *b, size_t *pos, const sh_comic_probe_t *cbz, const sh_comic_probe_t *cbr, bool rtl_ok)
 Append " cbz=P:WxH:CRC cbr=P:WxH:CRC rtl=OK" to the boot banner buffer.

Variables

static comic_t s_comic
 The open comic (large: page-index storage + backend scratch).
static comic_page_t s_pages [k_shc_page_cap]
 Caller-owned sorted page index.
static char s_names [k_shc_names_cap]
 Caller-owned page-name arena.
static uint8_t s_pagebuf [k_shc_pagebuf_cap]
 One page's extracted encoded image (the decoder input).
static uint8_t s_arena [k_shc_arena_cap]
 stb_image decode bump arena (zero-heap).
static uint16_t s_probe_rgb [(size_t) k_shc_probe_h *(size_t) k_shc_probe_w]
 Off-screen RGB565 scratch for the deterministic self-check decode.
static sh_comic_blob_t s_blob
 Resident-blob backing for baked / self-check comics.
static bool s_from_sd
 true when the open comic's backing is a held SD file (close it too).

Detailed Description

Full-page image reader for CBZ / CBR comic archives (#236).

The shelf's fourth reader surface. A comic archive is a container of page images (JPEG / PNG / ...) in reading order; ::comic opens either a .cbz (ZIP of images) or a .cbr (RAR of images) behind one interface and streams one page's encoded bytes on demand (bounded RAM, no whole-archive residency – see comic.h). This module pages through those images:

  • Opens the archive over a baked MRAM blob or the held-open SD file (sh_sd_book_open + sh_sd_comic_read), building ::comic's sorted page index into caller-owned arenas (no heap; NASA P10 Rule 3).
  • Renders the current page full-screen: extract the page's encoded image, then aspect-fit decode + blit it into the content box below the header via the integer ra8_img_decode_blit pipeline – the same decoder the EPUB cover path uses, so "page-0-as-cover" and page N share one code path.
  • Pages by re-decoding on each turn (one page + one decode arena resident at a time). A future large-manga path can stream through the #231/#232 tile cache instead of a whole-page decode; the encoded-page buffer bounds the openable page size for now (TODO(#231): tile huge pages rather than cap).
Right-to-left (manga) reading
Raw CBZ/CBR carry no reading-direction metadata, so direction is an app-level toggle (g_sh.comic_rtl, flipped by SW1 on the comic screen). sh_comic_edge_dir mirrors the edge-tap zones for RTL: the left edge advances in manga order.
Deterministic self-check
sh_comic_selfcheck decodes the baked CBZ + CBR fixtures' page 0 into an off-screen scratch and FNV-hashes them (an integer pipeline -> a toolchain-independent digest identical on host / ra8_emulator / silicon), which the boot banner pins as the comic golden without disturbing the shelf render.

[Ring 6 / App] {World: NS}

Since
0.1.0

Definition in file sh_comic.c.

Enumeration Type Documentation

◆ sh_comic_const_t

enum sh_comic_const_t : uint32_t

Comic reader buffer + layout constants.

Enumerator
k_shc_page_cap 

Max pages in the sorted index.

k_shc_names_cap 

Page-name arena bytes.

k_shc_pagebuf_cap 

One encoded page image, bytes.

k_shc_arena_cap 

stb_image decode bump arena bytes.

k_shc_probe_w 

Self-check scratch width, pixels.

k_shc_probe_h 

Self-check scratch height, pixels.

k_shc_probe_bg 

Self-check clear colour (matches.

ereader_comic -> same page digest).

k_shc_live_bg 

Live comic backdrop (near-black).

k_shc_fnv_offset 

FNV-1a-32 offset basis.

k_shc_fnv_prime 

FNV-1a-32 prime.

k_shc_hex_digits 

Hex digits in a 32-bit CRC.

k_shc_nib_bits 

Bits per hex nibble.

k_shc_nib_mask 

Low-nibble mask.

k_shc_thirds 

Edge-tap split (left/centre/right).

Definition at line 52 of file sh_comic.c.

Function Documentation

◆ sh_comic_append_banner()

void sh_comic_append_banner ( char * b,
size_t * pos,
const sh_comic_probe_t * cbz,
const sh_comic_probe_t * cbr,
bool rtl_ok )

Append " cbz=P:WxH:CRC cbr=P:WxH:CRC rtl=OK" to the boot banner buffer.

Formats the two sh_comic_selfcheck digests + the RTL verdict onto b at *pos, advancing *pos past what it wrote. The comic golden the shelf hil.conf pins lives entirely in these fields, so the shelf's own fb= hash stays byte-identical (this appends after).

Parameters
[in,out]bBanner buffer with room for the appended fields.
[in,out]posCurrent write offset into b; advanced on return.
[in]cbzCBZ page-0 self-check result (non-NULL).
[in]cbrCBR page-0 self-check result (non-NULL).
[in]rtl_okRTL edge-mapping verdict from sh_comic_selfcheck.
Precondition
b holds at least *pos + 64 writable bytes.
pos, cbz, cbr are non-NULL.
Postcondition
*pos advanced past the appended text; b is not NUL-terminated here.
Note
Not thread-safe.
Since
0.1.0

Definition at line 359 of file sh_comic.c.

References sh_comic_probe_t::crc, k_sh_dec_base, k_shc_hex_digits, k_shc_nib_bits, k_shc_nib_mask, and sh_fmt_uint().

Referenced by sh_print_banner().

◆ sh_comic_bind()

bool sh_comic_bind ( comic_read_fn rd,
void * ctx,
uint64_t size )
static

Bind ::comic over rd + set g_sh.comic_count / page; ok on success.

Definition at line 126 of file sh_comic.c.

References comic_open(), comic_page_count(), g_sh, k_ra8_ok, k_shc_names_cap, k_shc_page_cap, s_comic, s_names, and s_pages.

Referenced by sh_comic_open(), and sh_comic_probe_blob().

◆ sh_comic_blit_page()

ra8_err_t sh_comic_blit_page ( uint32_t page,
int32_t x,
int32_t y,
int32_t w,
int32_t h,
int32_t * out_w,
int32_t * out_h )
static

Extract page page's encoded bytes and decode+blit into the box.

Definition at line 145 of file sh_comic.c.

References comic_page_read(), g_sh, k_ra8_err_out_of_range, k_ra8_ok, ra8_img_decode_blit(), s_arena, s_comic, and s_pagebuf.

Referenced by sh_comic_probe_blob(), and sh_comic_render().

◆ sh_comic_blob_read()

size_t sh_comic_blob_read ( void * ctx,
uint64_t off,
void * buf,
size_t len )
static

comic_read_fn over a resident archive buffer (bounds-clamped).

Definition at line 102 of file sh_comic.c.

References sh_comic_blob_t::d, memcpy(), and sh_comic_blob_t::n.

Referenced by sh_comic_open(), and sh_comic_probe_blob().

◆ sh_comic_center_x()

int32_t sh_comic_center_x ( const char * s)
static

Centre-align s horizontally for the 8px bitmap font.

Definition at line 217 of file sh_comic.c.

References k_sh_fb_w, k_sh_glyph_w, and strlen().

Referenced by sh_comic_render().

◆ sh_comic_close()

void sh_comic_close ( void )

Close any open comic and release its backing (idempotent).

Definition at line 205 of file sh_comic.c.

References comic_close(), g_sh, s_comic, s_from_sd, and sh_sd_book_close().

Referenced by sh_book_open(), sh_comic_open(), and sh_comic_probe_blob().

◆ sh_comic_edge_dir()

int32_t sh_comic_edge_dir ( int32_t x)

Map a comic-screen edge tap to a reading-order page delta (RTL-aware).

The left third yields one edge and the right third the other; the centre third is neutral. In left-to-right order the right edge is "next" (+1); in right-to-left (manga) order the mapping is mirrored, so the LEFT edge advances. The centre band returns 0.

Parameters
[in]xTouch X in framebuffer pixels (0 .. k_sh_fb_w - 1).
Returns
+1 to advance a page, -1 to go back, 0 for a neutral centre tap.
Return values
+1Tap maps to the next page in reading order.
-1Tap maps to the previous page in reading order.
0Tap fell in the neutral centre band.
Precondition
g_sh.comic_rtl reflects the active reading direction.
Postcondition
No state is modified (pure mapping).
Note
Thread-safe: pure function of x and the RTL flag.
Since
0.1.0

Definition at line 255 of file sh_comic.c.

References g_sh, k_sh_fb_w, and k_shc_thirds.

Referenced by sh_comic_selfcheck(), and sh_comic_tap().

◆ sh_comic_fnv()

uint32_t sh_comic_fnv ( const void * p,
size_t n )
static

FNV-1a-32 over n bytes of p.

Definition at line 115 of file sh_comic.c.

References k_shc_fnv_offset, and k_shc_fnv_prime.

Referenced by sh_comic_probe_blob().

◆ sh_comic_open()

bool sh_comic_open ( uint16_t idx)

Open shelf entry idx as a comic archive (CBZ / CBR) for page reading.

Binds ::comic over the entry's backing – a baked MRAM blob, or the held-open SD file (sh_sd_book_open + sh_sd_comic_read) – and builds the sorted page index. On success g_sh.comic_count is the page count and g_sh.comic_page is reset to 0. The reading direction (g_sh.comic_rtl) is preserved across opens (an app-level toggle, since raw CBZ/CBR carry no direction metadata).

Parameters
[in]idxShelf entry index (< g_sh.book_count) whose fmt is a comic.
Returns
true if the comic opened with >= 1 page; false leaves none open.
Return values
trueComic bound; g_sh.comic_count >= 1, g_sh.comic_page == 0.
falseBad index/format, backing open failed, or no decodable pages.
Precondition
The entry at idx has sh_fmt_is_comic() true.
Any previously open book/comic was torn down by the caller (sh_book_open).
Postcondition
On true a comic is bound and page 0 is the current page.
On false no comic is bound (g_sh.comic_count == 0).
Note
Not thread-safe; single-threaded UI loop only.
Since
0.1.0

Definition at line 174 of file sh_comic.c.

References sh_entry_t::blob, sh_entry_t::blob_len, sh_entry_t::fmt, sh_entry_t::from_sd, g_sh, s_blob, s_from_sd, sh_entry_t::sd_name, sh_comic_bind(), sh_comic_blob_read(), sh_comic_close(), sh_fmt_is_comic(), sh_sd_book_close(), sh_sd_book_open(), and sh_sd_comic_read().

Referenced by sh_book_open().

◆ sh_comic_probe_blob()

◆ sh_comic_render()

void sh_comic_render ( void )

Render the current comic page full-screen (title bar + fitted image).

Definition at line 222 of file sh_comic.c.

References g_sh, k_ra8_ok, k_sh_bar_h, k_sh_col_sub, k_sh_fb_h, k_sh_fb_w, k_sh_linebuf, k_shc_live_bg, ra8_gfx_clear(), ra8_gfx_font_8x16, ra8_gfx_text_out(), sh_comic_blit_page(), sh_comic_center_x(), sh_fmt_uint(), and sh_titlebar().

Referenced by sh_present().

◆ sh_comic_selfcheck()

void sh_comic_selfcheck ( sh_comic_probe_t * cbz,
sh_comic_probe_t * cbr,
bool * rtl_ok )

Headless boot self-check: decode the baked CBZ + CBR page 0, verify RTL.

Opens each baked fixture through the SAME ::comic path the live screen uses, decodes page 0 into an off-screen RGB565 scratch via the integer ra8_img_decode_blit pipeline, and FNV-hashes the scratch – a deterministic digest identical on host, ra8_emulator, and silicon. It also exercises sh_comic_edge_dir in both reading directions. The live display framebuffer binding is restored on return, so the shelf render (and its pinned fb= hash) is untouched.

Parameters
[out]cbzReceives the CBZ page-0 decode result (non-NULL).
[out]cbrReceives the CBR page-0 decode result (non-NULL).
[out]rtl_okReceives true if the RTL edge mapping mirrors LTR (non-NULL).
Precondition
ra8_gfx is bound to the live framebuffer on entry.
cbz, cbr, and rtl_ok are non-NULL.
Postcondition
ra8_gfx is rebound to the live framebuffer (sh_fb_pixels) on return.
No comic is left open.
Note
Not thread-safe; single-threaded boot only.
Since
0.1.0

Definition at line 335 of file sh_comic.c.

References g_sh, k_comic_cbr, k_comic_cbr_len, k_comic_cbz, k_comic_cbz_len, k_ra8_gfx_format_rgb565, k_sh_fb_h, k_sh_fb_w, ra8_gfx_init(), sh_comic_edge_dir(), sh_comic_probe_blob(), and sh_fb_pixels().

Referenced by main().

◆ sh_comic_tap()

bool sh_comic_tap ( int32_t x,
bool header )

Handle a comic-screen tap: header returns to the shelf, else page-turn.

Parameters
[in]xTouch X in framebuffer pixels.
[in]headertrue if the tap landed in the header bar (y < k_sh_bar_h).
Returns
true if the screen must be repainted.
Return values
trueNavigated to the shelf, or a page turned.
falseNeutral tap with no state change.
Precondition
The comic screen is active.
Postcondition
On a header tap g_sh.screen == k_sh_screen_shelf.
Note
Not thread-safe.
Since
0.1.0

Definition at line 285 of file sh_comic.c.

References g_sh, k_sh_fb_w, k_sh_screen_shelf, sh_comic_edge_dir(), sh_comic_toggle_rtl(), and sh_comic_turn().

Referenced by sh_handle_tap().

◆ sh_comic_toggle_rtl()

void sh_comic_toggle_rtl ( void )

Flip the comic reading direction (LTR <-> RTL); page index unchanged.

Definition at line 301 of file sh_comic.c.

References g_sh.

Referenced by sh_comic_tap().

◆ sh_comic_turn()

bool sh_comic_turn ( int32_t dir)

Turn the comic page by dir in reading order, clamped to the ends.

Parameters
[in]dir+1 for the next page, -1 for the previous; 0 is a no-op.
Returns
true if the page index changed (a repaint is needed).
Return values
trueg_sh.comic_page advanced/retreated by one.
falseAt an end, no comic open, or dir == 0.
Precondition
A comic is open (or the call is a no-op).
Postcondition
g_sh.comic_page stays within [0, g_sh.comic_count).
On false no state changed.
Note
Not thread-safe.
Since
0.1.0

Definition at line 268 of file sh_comic.c.

References g_sh.

Referenced by sh_comic_tap(), and sh_handle_button().

Variable Documentation

◆ s_arena

uint8_t s_arena[k_shc_arena_cap]
static

stb_image decode bump arena (zero-heap).

Definition at line 90 of file sh_comic.c.

◆ s_blob

sh_comic_blob_t s_blob
static

Resident-blob backing for baked / self-check comics.

Definition at line 96 of file sh_comic.c.

◆ s_comic

comic_t s_comic
static

The open comic (large: page-index storage + backend scratch).

Definition at line 82 of file sh_comic.c.

Referenced by cm_draw_page(), cm_open_comic(), sh_comic_bind(), sh_comic_blit_page(), and sh_comic_close().

◆ s_from_sd

bool s_from_sd
static

true when the open comic's backing is a held SD file (close it too).

Definition at line 98 of file sh_comic.c.

Referenced by sh_comic_close(), sh_comic_open(), and sh_comic_probe_blob().

◆ s_names

char s_names[k_shc_names_cap]
static

Caller-owned page-name arena.

Definition at line 86 of file sh_comic.c.

Referenced by cm_open_comic(), and sh_comic_bind().

◆ s_pagebuf

uint8_t s_pagebuf[k_shc_pagebuf_cap]
static

One page's extracted encoded image (the decoder input).

Definition at line 88 of file sh_comic.c.

Referenced by cm_draw_page(), and sh_comic_blit_page().

◆ s_pages

comic_page_t s_pages[k_shc_page_cap]
static

Caller-owned sorted page index.

Definition at line 84 of file sh_comic.c.

Referenced by cm_open_comic(), and sh_comic_bind().

◆ s_probe_rgb

uint16_t s_probe_rgb[(size_t) k_shc_probe_h *(size_t) k_shc_probe_w]
static

Off-screen RGB565 scratch for the deterministic self-check decode.

Definition at line 93 of file sh_comic.c.

Referenced by sh_comic_probe_blob().