ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rar5_tables.c
Go to the documentation of this file.
1
27#include <string.h>
28
29#include "ra8_attributes.h"
30#include "ra8_rar5.h"
31#include "ra8_rar5_internal.h"
32
33/* ---- streaming MSB-first bit reader ------------------------------------- */
34
51{
52 if (st->refill_pos >= st->refill_len) {
53 if (st->fetched >= st->packlen) {
54 st->overrun = true;
55 return 0U;
56 }
57 const uint64_t remain = st->packlen - st->fetched;
58 const size_t want = (remain < (uint64_t)k_ra8_rar5_refill_bytes)
59 ? (size_t)remain
61 const size_t r = st->rar->read(st->rar->ctx, st->base + st->fetched, st->refill, want);
62 if (r == 0U) {
63 st->overrun = true;
64 return 0U;
65 }
66 st->refill_len = (uint32_t)r;
67 st->refill_pos = 0U;
68 st->fetched += (uint64_t)r;
69 }
70 const uint8_t b = st->refill[st->refill_pos];
71 st->refill_pos += 1U;
72 return b;
73}
74
89RA8_INTERNAL static void internal_ensure(ra8_rar5_state_t* st, uint32_t n)
90{
91 while (st->nbits < n) { /* bound: n<=32, +8 bits per pass -> <=4 passes */
92 const uint8_t b = internal_fetch_byte(st);
93 st->acc = (st->acc << k_r5_byte_bits) | (uint64_t)b;
94 st->nbits += (uint32_t)k_r5_byte_bits;
95 }
96}
97
113RA8_INTERNAL static uint32_t internal_peek(ra8_rar5_state_t* st, uint32_t n)
114{
115 internal_ensure(st, n);
116 const uint64_t mask = ((uint64_t)1U << n) - (uint64_t)1U;
117 return (uint32_t)((st->acc >> (st->nbits - n)) & mask);
118}
119
134RA8_INTERNAL static void internal_drop(ra8_rar5_state_t* st, uint32_t n)
135{
136 st->nbits -= n;
137 st->consumed += (uint64_t)n;
138 const uint64_t mask = (st->nbits >= (uint32_t)k_r5_acc_bits)
139 ? ~(uint64_t)0U
140 : (((uint64_t)1U << st->nbits) - (uint64_t)1U);
141 st->acc &= mask;
142}
143
145RA8_PRIV uint32_t priv_rar5_get(ra8_rar5_state_t* st, uint32_t n)
146{
147 const uint32_t v = internal_peek(st, n);
148 internal_drop(st, n);
149 return v;
150}
151
166{
167 internal_drop(st, st->nbits & (uint32_t)k_r5_low3_mask);
168}
169
170/* ---- canonical Huffman decode tables ------------------------------------ */
171
187RA8_INTERNAL static void internal_tab_limits(ra8_rar5_dtab_t* d, const uint32_t* count)
188{
189 d->len[0] = 0U;
190 d->pos[0] = 0U;
191 uint32_t upper = 0U;
192 for (uint32_t i = 1U; i < (uint32_t)(k_r5_maxbits + 1U); ++i) { /* bound: 15 lengths */
193 upper += count[i];
194 d->len[i] = upper << ((uint32_t)k_r5_bf_bits - i);
195 upper <<= 1U;
196 d->pos[i] = d->pos[i - 1U] + count[i - 1U];
197 }
198}
199
216RA8_INTERNAL static void
217internal_make_tables(ra8_rar5_dtab_t* d, const uint8_t* lengths, uint16_t size)
218{
219 uint32_t count[k_r5_maxbits + 1U] = {};
220 for (uint16_t i = 0U; i < size; ++i) { /* bound: size <= k_ra8_rar5_nc */
221 count[lengths[i] & (uint8_t)k_r5_nibble_mask] += 1U;
222 }
223 count[0] = 0U;
224 internal_tab_limits(d, count);
225 (void)memset(d->num, 0, (size_t)size * sizeof(d->num[0]));
226 uint32_t copypos[k_r5_maxbits + 1U];
227 for (uint32_t i = 0U; i < (uint32_t)(k_r5_maxbits + 1U); ++i) { /* bound: 16 */
228 copypos[i] = d->pos[i];
229 }
230 for (uint16_t i = 0U; i < size; ++i) { /* bound: size */
231 const uint8_t bl = lengths[i] & (uint8_t)k_r5_nibble_mask;
232 if (bl != 0U) {
233 d->num[copypos[bl]] = i;
234 copypos[bl] += 1U;
235 }
236 }
237 d->max = size;
238}
239
242{
243 const uint32_t bf = internal_peek(st, (uint32_t)k_r5_bf_bits) & (uint32_t)k_r5_bf_mask;
244 uint32_t bits = (uint32_t)k_r5_maxbits;
245 for (uint32_t i = 1U; i < (uint32_t)k_r5_maxbits; ++i) { /* bound: 14 lengths */
246 if (bf < d->len[i]) {
247 bits = i;
248 break;
249 }
250 }
251 internal_drop(st, bits);
252 const uint32_t dist = (bf - d->len[bits - 1U]) >> ((uint32_t)k_r5_bf_bits - bits);
253 uint32_t pos = d->pos[bits] + dist;
254 if (pos >= (uint32_t)d->max) {
255 pos = 0U;
256 }
257 return d->num[pos];
258}
259
260/* ---- block header + Huffman tables -------------------------------------- */
261
277RA8_INTERNAL static uint8_t internal_checksum(uint32_t flags, uint64_t blocksize)
278{
279 uint32_t x = (uint32_t)k_r5_hdr_chk_seed ^ flags;
280 x ^= (uint32_t)(blocksize & (uint64_t)k_r5_byte_mask);
281 x ^= (uint32_t)((blocksize >> k_r5_byte_bits) & (uint64_t)k_r5_byte_mask);
282 x ^= (uint32_t)((blocksize >> (k_r5_byte_bits * 2U)) & (uint64_t)k_r5_byte_mask);
283 return (uint8_t)(x & (uint32_t)k_r5_byte_mask);
284}
285
288{
289 internal_align(st);
290 const uint32_t flags = priv_rar5_get(st, (uint32_t)k_r5_byte_bits);
291 const uint32_t bytecount =
292 ((flags >> (uint32_t)k_r5_bf_bcount_shift) & (uint32_t)k_r5_bf_bcount_mask) + 1U;
293 uint64_t bsz = 0U;
294 for (uint32_t i = 0U; i < bytecount; ++i) { /* bound: bytecount <= 4 */
295 bsz |= (uint64_t)priv_rar5_get(st, (uint32_t)k_r5_byte_bits)
296 << ((uint32_t)i * (uint32_t)k_r5_byte_bits);
297 }
298 const uint32_t saved = priv_rar5_get(st, (uint32_t)k_r5_byte_bits);
299 if ((uint32_t)internal_checksum(flags, bsz) != saved) {
301 }
302 b->size = bsz;
303 b->last_bits = (flags & (uint32_t)k_r5_bf_bitsize_mask) + 1U;
304 b->tables = (flags & (uint32_t)k_r5_bf_tables) != 0U;
305 b->last = (flags & (uint32_t)k_r5_bf_last) != 0U;
306 return k_ra8_ok;
307}
308
310RA8_PRIV uint32_t priv_rar5_fill_zeros(uint8_t* out, uint32_t start, uint32_t count, uint32_t max)
311{
312 uint32_t i = start;
313 for (uint32_t c = 0U; (c < count) && (i < max); ++c) { /* bound: count, i<max */
314 out[i] = 0U;
315 i += 1U;
316 }
317 return i;
318}
319
336{
337 uint32_t i = 0U;
338 while (i < (uint32_t)k_ra8_rar5_bc) { /* bound: i advances toward k_ra8_rar5_bc */
339 const uint32_t len = priv_rar5_get(st, 4U);
340 if (len != (uint32_t)k_r5_len_escape) {
341 out[i] = (uint8_t)len;
342 i += 1U;
343 continue;
344 }
345 const uint32_t zc = priv_rar5_get(st, 4U);
346 if (zc == 0U) {
347 out[i] = (uint8_t)k_r5_len_escape;
348 i += 1U;
349 } else {
350 i = priv_rar5_fill_zeros(out, i, zc + (uint32_t)k_r5_zeros_extra, (uint32_t)k_ra8_rar5_bc);
351 }
352 }
353 return k_ra8_ok;
354}
355
358 uint8_t* tbl,
359 uint32_t* idx,
360 uint32_t num)
361{
362 const bool is_long =
363 (num == (uint32_t)k_r5_tbl_copy_long) || (num == (uint32_t)k_r5_tbl_zero_long);
364 const bool is_zero =
365 (num == (uint32_t)k_r5_tbl_zero_short) || (num == (uint32_t)k_r5_tbl_zero_long);
366 const uint32_t count =
367 is_long ? (priv_rar5_get(st, (uint32_t)k_r5_run_long_bits) + (uint32_t)k_r5_run_long_add)
368 : (priv_rar5_get(st, 3U) + 3U);
369 if ((!is_zero) && (*idx == 0U)) {
371 }
372 const uint8_t prev = (*idx > 0U) ? tbl[*idx - 1U] : 0U;
373 const uint8_t fill = is_zero ? 0U : prev;
374 uint32_t i = *idx;
375 for (uint32_t c = 0U; (c < count) && (i < (uint32_t)k_ra8_rar5_huff_total);
376 ++c) { /* bound: count */
377 tbl[i] = fill;
378 i += 1U;
379 }
380 *idx = i;
381 return k_ra8_ok;
382}
383
401{
402 uint32_t i = 0U;
403 while (i < (uint32_t)k_ra8_rar5_huff_total) { /* bound: i advances each pass */
404 const uint32_t num = priv_rar5_decode_num(st, &st->bd);
405 if (num < 16U) {
406 tbl[i] = (uint8_t)num;
407 i += 1U;
408 continue;
409 }
410 const ra8_err_t e = priv_rar5_apply_run(st, tbl, &i, num);
411 if (e != k_ra8_ok) {
412 return e;
413 }
414 }
415 return k_ra8_ok;
416}
417
420{
421 uint8_t bdlen[k_ra8_rar5_bc] = {};
422 ra8_err_t e = internal_read_bd_lengths(st, bdlen);
423 if (e != k_ra8_ok) {
424 return e;
425 }
426 internal_make_tables(&st->bd, bdlen, (uint16_t)k_ra8_rar5_bc);
427 uint8_t tbl[k_ra8_rar5_huff_total] = {};
428 e = internal_read_full_table(st, tbl);
429 if (e != k_ra8_ok) {
430 return e;
431 }
432 internal_make_tables(&st->ld, &tbl[0], (uint16_t)k_ra8_rar5_nc);
433 internal_make_tables(&st->dd, &tbl[k_ra8_rar5_nc], (uint16_t)k_ra8_rar5_dc);
435 internal_make_tables(&st->rd,
437 (uint16_t)k_ra8_rar5_rc);
438 st->tables_ready = true;
439 return k_ra8_ok;
440}
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
Clean-room RAR 5.0 ("method 50") decompressor – LZ + Huffman + filters.
@ k_ra8_rar5_ldc
Low-distance alphabet size.
Definition ra8_rar5.h:79
@ k_ra8_rar5_huff_total
NC+DC+LDC+RC combined length-table size.
Definition ra8_rar5.h:82
@ k_ra8_rar5_bc
Bit-length pre-table alphabet size.
Definition ra8_rar5.h:81
@ k_ra8_rar5_rc
Repeat-length alphabet size.
Definition ra8_rar5.h:80
@ k_ra8_rar5_refill_bytes
Streaming bit-reader packed-byte window.
Definition ra8_rar5.h:84
@ k_ra8_rar5_dc
Distance-slot alphabet size.
Definition ra8_rar5.h:78
@ k_ra8_rar5_nc
Main alphabet size (literals+len+rep+filter).
Definition ra8_rar5.h:77
Cross-TU seam between the RAR5 entropy front-end and the LZ decoder.
@ k_r5_nibble_mask
Low nibble of a bit-length byte.
@ k_r5_byte_mask
Single-byte mask.
@ k_r5_bf_mask
DecodeNumber bit-field, low bit cleared.
@ k_r5_bf_last
Last block in the file.
@ k_r5_bf_bcount_shift
Shift to the block-size byte count.
@ k_r5_bf_bcount_mask
Mask of the block-size byte count.
@ k_r5_hdr_chk_seed
Header-checksum seed constant.
@ k_r5_bf_tables
Block carries new Huffman tables.
@ k_r5_bf_bitsize_mask
Last-byte valid-bit count minus one.
@ k_r5_maxbits
Longest Huffman code length.
@ k_r5_byte_bits
Bits per packed byte.
@ k_r5_low3_mask
Low three bits (byte-alignment residue).
@ k_r5_acc_bits
Bit-accumulator width (mask guard).
@ k_r5_bf_bits
DecodeNumber look-ahead window width.
@ k_r5_len_escape
4-bit escape in the BD length list.
@ k_r5_tbl_copy_long
Copy previous length, 7-bit run.
@ k_r5_zeros_extra
BD zero-run length bias.
@ k_r5_tbl_zero_short
Zero length, 3-bit run.
@ k_r5_run_long_bits
Long-run extra-bit width.
@ k_r5_run_long_add
Long-run length bias.
@ k_r5_tbl_zero_long
Zero length, 7-bit run.
static void internal_ensure(ra8_rar5_state_t *st, uint32_t n)
Ensure at least n bits are buffered in the accumulator.
ra8_err_t priv_rar5_read_tables(ra8_rar5_state_t *st)
Implementation of priv_rar5_read_tables() – BD pre-table then the four LZ tables.
static void internal_make_tables(ra8_rar5_dtab_t *d, const uint8_t *lengths, uint16_t size)
Build a canonical Huffman decode table from a bit-length vector.
static ra8_err_t internal_read_bd_lengths(ra8_rar5_state_t *st, uint8_t *out)
Read the 20-entry bit-length pre-table (BD) length list.
static void internal_align(ra8_rar5_state_t *st)
Discard bits up to the next byte boundary.
uint32_t priv_rar5_get(ra8_rar5_state_t *st, uint32_t n)
Implementation of priv_rar5_get() – internal_peek then internal_drop of n bits.
uint32_t priv_rar5_decode_num(ra8_rar5_state_t *st, const ra8_rar5_dtab_t *d)
Implementation of priv_rar5_decode_num() – limit-compare canonical decode.
static ra8_err_t internal_read_full_table(ra8_rar5_state_t *st, uint8_t *tbl)
Decode the combined length table for the four LZ alphabets.
static void internal_tab_limits(ra8_rar5_dtab_t *d, const uint32_t *count)
Fill a decode table's per-length upper-limit and start-position arrays.
ra8_err_t priv_rar5_read_block_header(ra8_rar5_state_t *st, r5_block_t *b)
Implementation of priv_rar5_read_block_header() – align, flags, size, checksum.
uint32_t priv_rar5_fill_zeros(uint8_t *out, uint32_t start, uint32_t count, uint32_t max)
Implementation of priv_rar5_fill_zeros() – bounded zero-length append.
static uint8_t internal_fetch_byte(ra8_rar5_state_t *st)
Pull the next packed byte, refilling the window from the backing reader.
static uint8_t internal_checksum(uint32_t flags, uint64_t blocksize)
Compute the RAR5 block-header checksum byte.
static uint32_t internal_peek(ra8_rar5_state_t *st, uint32_t n)
Peek the next n bits without consuming them.
static void internal_drop(ra8_rar5_state_t *st, uint32_t n)
Consume n previously-peeked bits.
ra8_err_t priv_rar5_apply_run(ra8_rar5_state_t *st, uint8_t *tbl, uint32_t *idx, uint32_t num)
Implementation of priv_rar5_apply_run() – copy-previous / zero run append.
Decoded fields of one RAR5 compressed-block header.
One canonical Huffman decode table (shared by all five RAR5 alphabets).
Definition ra8_rar5.h:105
uint32_t pos[16]
First num index per bit length.
Definition ra8_rar5.h:107
uint32_t len[16]
Left-aligned upper-limit code per bit length.
Definition ra8_rar5.h:106
uint16_t max
Alphabet size (populated slot count).
Definition ra8_rar5.h:109
uint16_t num[k_ra8_rar5_nc]
Symbol per canonical code slot.
Definition ra8_rar5.h:108
Caller-owned zero-heap scratch for one ra8_rar5_decompress call.