ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rar5.c
Go to the documentation of this file.
1
40#include "ra8_rar5.h"
41
42#include <string.h>
43
44#include "ra8_attributes.h"
45#include "ra8_check.h"
46#include "ra8_rar5_internal.h"
47
49static const char* const s_tag_rar5 = "ra8_rar5";
50
64RA8_INTERNAL static void internal_copy_object(void* dst, const void* src, size_t len)
65{
66 (void)memcpy(dst, src, len);
67}
68
69/* ---- little-endian scalar reads/writes ---------------------------------- */
70
85RA8_INTERNAL static uint32_t internal_rd_le32(const uint8_t* p)
86{
87 uint32_t v = 0U;
88 internal_copy_object(&v, p, sizeof(v));
89 return v;
90}
91
105RA8_INTERNAL static void internal_wr_le32(uint8_t* p, uint32_t v)
106{
107 internal_copy_object(p, &v, sizeof(v));
108}
109
110/* ---- LZ token decode ---------------------------------------------------- */
111
127RA8_INTERNAL static uint32_t internal_slot_to_length(ra8_rar5_state_t* st, uint32_t slot)
128{
129 uint32_t length = 2U;
130 if (slot < 8U) {
131 return length + slot;
132 }
133 const uint32_t lbits = (slot / 4U) - 1U;
134 length += (4U | (slot & 3U)) << lbits;
135 length += priv_rar5_get(st, lbits);
136 return length;
137}
138
155{
156 const uint32_t slot = priv_rar5_decode_num(st, &st->dd);
157 if (slot < 4U) {
158 return (uint64_t)1U + slot;
159 }
160 const uint32_t dbits = (slot / 2U) - 1U;
161 uint64_t dist = UINT64_C(1) + ((UINT64_C(2) | (uint64_t)(slot & 1U)) << dbits);
162 if (dbits < 4U) {
163 return dist + priv_rar5_get(st, dbits);
164 }
165 if (dbits > 4U) {
166 dist += (uint64_t)priv_rar5_get(st, dbits - 4U) << 4U;
167 }
168 dist += priv_rar5_decode_num(st, &st->ldd);
169 return dist;
170}
171
186RA8_INTERNAL static uint32_t internal_adjust_length(uint32_t length, uint64_t dist)
187{
188 uint32_t adjusted = length;
189 if (dist > (uint64_t)k_r5_dist_th1) {
190 adjusted += 1U;
191 if (dist > (uint64_t)k_r5_dist_th2) {
192 adjusted += 1U;
193 if (dist > (uint64_t)k_r5_dist_th3) {
194 adjusted += 1U;
195 }
196 }
197 }
198 return adjusted;
199}
200
215RA8_INTERNAL static void internal_push_dist(ra8_rar5_state_t* st, uint64_t dist)
216{
217 for (uint32_t i = (uint32_t)k_ra8_rar5_old_dist - 1U; i > 0U; --i) { /* bound: ring size */
218 st->old_dist[i] = st->old_dist[i - 1U];
219 }
220 st->old_dist[0] = dist;
221}
222
224RA8_PRIV bool
225priv_rar5_copy_match(uint8_t* out, size_t* out_pos, size_t unp, uint32_t length, uint64_t dist)
226{
227 size_t pos = *out_pos;
228 if ((dist == 0U) || (dist > (uint64_t)pos)) {
229 return false;
230 }
231 const size_t back = (size_t)dist;
232 for (uint32_t k = 0U; (k < length) && (pos < unp); ++k) { /* bound: length, pos<unp */
233 out[pos] = out[pos - back];
234 pos += 1U;
235 }
236 *out_pos = pos;
237 return true;
238}
239
240/* ---- in-stream data filters --------------------------------------------- */
241
256{
257 const uint32_t bc = priv_rar5_get(st, 2U) + 1U;
258 uint32_t data = 0U;
259 for (uint32_t i = 0U; i < bc; ++i) { /* bound: bc <= 4 */
260 data |= priv_rar5_get(st, (uint32_t)k_r5_byte_bits) << (i * (uint32_t)k_r5_byte_bits);
261 }
262 return data;
263}
264
282{
283 if (st->filter_count >= (uint16_t)k_ra8_rar5_max_filters) {
285 }
286 const uint32_t rel = internal_read_filter_data(st);
287 const uint32_t len = internal_read_filter_data(st);
288 const uint32_t type = priv_rar5_get(st, (uint32_t)k_r5_ftype_bits);
289 if (type > (uint32_t)k_ra8_rar5_filter_arm) {
291 }
292 uint32_t channels = 1U;
293 if (type == (uint32_t)k_ra8_rar5_filter_delta) {
294 channels = priv_rar5_get(st, (uint32_t)k_r5_fchan_bits) + 1U;
295 }
296 ra8_rar5_filter_t* f = &st->filters[st->filter_count];
297 f->start = (uint64_t)out_pos + (uint64_t)rel;
298 f->len = len;
299 f->type = (uint8_t)type;
300 f->channels = (uint8_t)channels;
301 st->filter_count += 1U;
302 return k_ra8_ok;
303}
304
306RA8_PRIV void
307priv_rar5_filter_delta(ra8_rar5_state_t* st, uint8_t* d, uint32_t len, uint32_t channels)
308{
309 if ((len > (uint32_t)k_ra8_rar5_delta_scratch) || (channels == 0U)) {
310 return;
311 }
312 (void)memcpy(st->delta, d, (size_t)len);
313 uint32_t dpos = 0U;
314 for (uint32_t ch = 0U; ch < channels; ++ch) { /* bound: channels <= 32 */
315 uint8_t prev = 0U;
316 for (uint32_t i = ch; i < len; i += channels) { /* bound: i < len */
317 prev = (uint8_t)(prev - st->delta[dpos]);
318 dpos += 1U;
319 d[i] = prev;
320 }
321 }
322}
323
339RA8_INTERNAL static bool internal_x86_is_op(uint8_t op, bool e9)
340{
341 if (op == (uint8_t)k_r5_x86_call) {
342 return true;
343 }
344 return e9 && (op == (uint8_t)k_r5_x86_jmp);
345}
346
363RA8_INTERNAL static void internal_filter_x86(uint8_t* d, uint32_t len, uint64_t filepos, bool e9)
364{
365 if (len < (uint32_t)k_r5_x86_ilen) {
366 return;
367 }
368 const uint32_t limit = len - (uint32_t)k_r5_x86_ilen;
369 uint32_t i = 0U;
370 while (i <= limit) { /* bound: i <= limit < len */
371 if (internal_x86_is_op(d[i], e9)) {
372 const uint32_t off = i + 1U;
373 const uint32_t pos = (uint32_t)(filepos + (uint64_t)off);
374 internal_wr_le32(&d[off], internal_rd_le32(&d[off]) - pos);
375 i += (uint32_t)k_r5_x86_ilen;
376 } else {
377 i += 1U;
378 }
379 }
380}
381
397RA8_INTERNAL static void internal_filter_arm(uint8_t* d, uint32_t len, uint64_t filepos)
398{
399 if (len < 4U) {
400 return;
401 }
402 const uint32_t limit = len - 4U;
403 uint32_t i = 0U;
404 while (i <= limit) { /* bound: i steps by 4 to limit */
405 if (d[i + 3U] == (uint8_t)k_r5_arm_bl) {
406 uint32_t v = (uint32_t)d[i] | ((uint32_t)d[i + 1U] << k_r5_byte_bits) |
407 ((uint32_t)d[i + 2U] << (k_r5_byte_bits * 2U));
408 const uint32_t p = (uint32_t)((filepos + (uint64_t)i) >> 2U);
409 v = (v - p) & (uint32_t)k_r5_arm_off_mask;
410 d[i] = (uint8_t)(v & (uint32_t)k_r5_byte_mask);
411 d[i + 1U] = (uint8_t)((v >> k_r5_byte_bits) & (uint32_t)k_r5_byte_mask);
412 d[i + 2U] = (uint8_t)((v >> (k_r5_byte_bits * 2U)) & (uint32_t)k_r5_byte_mask);
413 }
414 i += 4U;
415 }
416}
417
436 uint8_t* out,
437 size_t unp,
438 const ra8_rar5_filter_t* f)
439{
440 if (f->start >= (uint64_t)unp) {
441 return;
442 }
443 const uint64_t avail = (uint64_t)unp - f->start;
444 const uint32_t len = ((uint64_t)f->len > avail) ? (uint32_t)avail : f->len;
445 if (len == 0U) {
446 return;
447 }
448 uint8_t* d = &out[(size_t)f->start];
449 if (f->type == (uint8_t)k_ra8_rar5_filter_delta) {
450 priv_rar5_filter_delta(st, d, len, f->channels);
451 } else if (f->type == (uint8_t)k_ra8_rar5_filter_e8) {
452 internal_filter_x86(d, len, f->start, false);
453 } else if (f->type == (uint8_t)k_ra8_rar5_filter_e8e9) {
454 internal_filter_x86(d, len, f->start, true);
455 } else {
456 internal_filter_arm(d, len, f->start);
457 }
458}
459
475RA8_INTERNAL static void internal_apply_filters(ra8_rar5_state_t* st, uint8_t* out, size_t unp)
476{
477 for (uint16_t f = 0U; f < st->filter_count; ++f) { /* bound: filter_count */
478 internal_apply_one_filter(st, out, unp, &st->filters[f]);
479 }
480}
481
482/* ---- token dispatch + block/stream loops -------------------------------- */
483
505static ra8_err_t
506internal_do_match(ra8_rar5_state_t* st, uint32_t slot, uint8_t* out, size_t* out_pos, size_t unp)
507{
508 uint32_t length = internal_slot_to_length(st, slot - (uint32_t)k_r5_sym_lenbase);
509 const uint64_t dist = internal_decode_distance(st);
510 length = internal_adjust_length(length, dist);
511 internal_push_dist(st, dist);
512 st->last_length = length;
513 if (!priv_rar5_copy_match(out, out_pos, unp, length, dist)) {
515 }
516 return k_ra8_ok;
517}
518
539static ra8_err_t
540internal_do_repdist(ra8_rar5_state_t* st, uint32_t slot, uint8_t* out, size_t* out_pos, size_t unp)
541{
542 const uint32_t idx = slot - (uint32_t)k_r5_sym_repdist0;
543 const uint64_t dist = st->old_dist[idx];
544 for (uint32_t i = idx; i > 0U; --i) { /* bound: idx <= 3 */
545 st->old_dist[i] = st->old_dist[i - 1U];
546 }
547 st->old_dist[0] = dist;
548 const uint32_t lenslot = priv_rar5_decode_num(st, &st->rd);
549 const uint32_t length = internal_slot_to_length(st, lenslot);
550 st->last_length = length;
551 if (!priv_rar5_copy_match(out, out_pos, unp, length, dist)) {
553 }
554 return k_ra8_ok;
555}
556
576static ra8_err_t
577internal_do_replast(ra8_rar5_state_t* st, uint8_t* out, size_t* out_pos, size_t unp)
578{
579 if (st->last_length == 0U) {
580 return k_ra8_ok;
581 }
582 if (!priv_rar5_copy_match(out, out_pos, unp, st->last_length, st->old_dist[0])) {
584 }
585 return k_ra8_ok;
586}
587
608static ra8_err_t
609internal_decode_token(ra8_rar5_state_t* st, uint8_t* out, size_t* out_pos, size_t unp)
610{
611 const uint32_t slot = priv_rar5_decode_num(st, &st->ld);
612 if (slot < (uint32_t)k_r5_sym_filter) {
613 out[*out_pos] = (uint8_t)slot;
614 *out_pos += 1U;
615 return k_ra8_ok;
616 }
617 if (slot == (uint32_t)k_r5_sym_filter) {
618 return internal_read_filter(st, *out_pos);
619 }
620 if (slot == (uint32_t)k_r5_sym_replast) {
621 return internal_do_replast(st, out, out_pos, unp);
622 }
623 if (slot < (uint32_t)k_r5_sym_lenbase) {
624 return internal_do_repdist(st, slot, out, out_pos, unp);
625 }
626 return internal_do_match(st, slot, out, out_pos, unp);
627}
628
648internal_open_block(ra8_rar5_state_t* st, uint64_t* end_bit, bool* last)
649{
650 r5_block_t blk = {};
651 const ra8_err_t e = priv_rar5_read_block_header(st, &blk);
652 if (e != k_ra8_ok) {
653 return e;
654 }
655 if (blk.size == 0U) {
657 }
658 const uint64_t start = st->consumed;
659 *end_bit = start + ((blk.size - 1U) * (uint64_t)k_r5_byte_bits) + (uint64_t)blk.last_bits;
660 *last = blk.last;
661 if (blk.tables) {
662 return priv_rar5_read_tables(st);
663 }
664 if (!st->tables_ready) {
666 }
667 return k_ra8_ok;
668}
669
695static ra8_err_t
696internal_decode_stream(ra8_rar5_state_t* st, uint8_t* out, size_t out_cap, size_t unp)
697{
698 (void)out_cap;
699 size_t out_pos = 0U;
700 bool last = false;
701 uint64_t block_end = 0U;
702 const uint64_t cap_bits = (st->packlen * (uint64_t)k_r5_byte_bits) + (uint64_t)k_r5_max_pad_bits;
703 ra8_err_t e = internal_open_block(st, &block_end, &last);
704 if (e != k_ra8_ok) {
705 return e;
706 }
707 while ((out_pos < unp) && (st->consumed <= cap_bits)) { /* bound: consumed strictly rises */
708 if (st->consumed >= block_end) {
709 if (last) {
710 break;
711 }
712 e = internal_open_block(st, &block_end, &last);
713 if (e != k_ra8_ok) {
714 return e;
715 }
716 continue;
717 }
718 e = internal_decode_token(st, out, &out_pos, unp);
719 if (e != k_ra8_ok) {
720 return e;
721 }
722 }
723 if (out_pos != unp) {
725 }
726 return k_ra8_ok;
727}
728
755 const uint8_t* out,
756 const ra8_rar5_state_t* st,
757 size_t out_cap,
758 uint64_t unp_size,
759 uint64_t pack_size)
760{
761 RA8_CHECK_NULL_PTR(rar, s_tag_rar5, "decompress: null rar");
762 RA8_CHECK_NULL_PTR(out, s_tag_rar5, "decompress: null out");
763 RA8_CHECK_NULL_PTR(st, s_tag_rar5, "decompress: null st");
764 if (rar->version != k_ra8_rar_ver_5) {
766 }
767 if (unp_size > (uint64_t)out_cap) {
768 return k_ra8_err_no_mem;
769 }
770 if (pack_size == 0U) {
772 }
773 return k_ra8_ok;
774}
775
777 uint64_t data_off,
778 uint64_t pack_size,
779 uint8_t* out,
780 size_t out_cap,
781 uint64_t unp_size,
783 size_t* got)
784{
785 RA8_CHECK_NULL_PTR(got, s_tag_rar5, "decompress: null got");
786 *got = 0U;
787 const ra8_err_t vcheck = internal_decompress_check(rar, out, st, out_cap, unp_size, pack_size);
788 if (vcheck != k_ra8_ok) {
789 return vcheck;
790 }
791 *st = (ra8_rar5_state_t){};
792 st->rar = rar;
793 st->base = data_off;
794 st->packlen = pack_size;
795 if (unp_size == 0U) {
796 return k_ra8_ok;
797 }
798 const ra8_err_t e = internal_decode_stream(st, out, out_cap, (size_t)unp_size);
799 if (e != k_ra8_ok) {
800 return e;
801 }
802 internal_apply_filters(st, out, (size_t)unp_size);
803 *got = (size_t)unp_size;
804 return k_ra8_ok;
805}
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).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ 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 * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
static uint32_t internal_rd_le32(const uint8_t *p)
Read a little-endian uint32 from four unaligned bytes.
Definition ra8_rar5.c:85
static uint32_t internal_slot_to_length(ra8_rar5_state_t *st, uint32_t slot)
Convert an LZ length slot into a match length, reading any extra bits.
Definition ra8_rar5.c:127
static void internal_wr_le32(uint8_t *p, uint32_t v)
Write a uint32 as four little-endian bytes.
Definition ra8_rar5.c:105
static void internal_apply_one_filter(ra8_rar5_state_t *st, uint8_t *out, size_t unp, const ra8_rar5_filter_t *f)
Replay one queued filter over its (clamped) output range.
Definition ra8_rar5.c:435
static ra8_err_t internal_decompress_check(const ra8_rar_t *rar, const uint8_t *out, const ra8_rar5_state_t *st, size_t out_cap, uint64_t unp_size, uint64_t pack_size)
Validate the non-output arguments of ra8_rar5_decompress.
Definition ra8_rar5.c:754
static uint64_t internal_decode_distance(ra8_rar5_state_t *st)
Decode an LZ match distance from the distance / low-distance tables.
Definition ra8_rar5.c:154
ra8_err_t ra8_rar5_decompress(const ra8_rar_t *rar, uint64_t data_off, uint64_t pack_size, uint8_t *out, size_t out_cap, uint64_t unp_size, ra8_rar5_state_t *st, size_t *got)
Decompress one RAR5-packed member into the caller's output buffer.
Definition ra8_rar5.c:776
static void internal_push_dist(ra8_rar5_state_t *st, uint64_t dist)
Push a fresh match distance onto the recent-distance ring.
Definition ra8_rar5.c:215
static ra8_err_t internal_open_block(ra8_rar5_state_t *st, uint64_t *end_bit, bool *last)
Open the next compressed block: header, tables, and its bit-end.
Definition ra8_rar5.c:648
static void internal_apply_filters(ra8_rar5_state_t *st, uint8_t *out, size_t unp)
Replay every queued filter in stream order.
Definition ra8_rar5.c:475
static ra8_err_t internal_do_match(ra8_rar5_state_t *st, uint32_t slot, uint8_t *out, size_t *out_pos, size_t unp)
Decode a length-slot LZ match (main symbol >= 262) into out.
Definition ra8_rar5.c:506
static void internal_filter_arm(uint8_t *d, uint32_t len, uint64_t filepos)
Apply the ARM BL branch-offset filter over d.
Definition ra8_rar5.c:397
static ra8_err_t internal_decode_token(ra8_rar5_state_t *st, uint8_t *out, size_t *out_pos, size_t unp)
Decode one LZ token: literal, match, repeat-match, or filter.
Definition ra8_rar5.c:609
static void internal_filter_x86(uint8_t *d, uint32_t len, uint64_t filepos, bool e9)
Apply the x86 CALL/JMP relative-address filter over d.
Definition ra8_rar5.c:363
static ra8_err_t internal_decode_stream(ra8_rar5_state_t *st, uint8_t *out, size_t out_cap, size_t unp)
Drive the block + token loops until unp bytes are produced.
Definition ra8_rar5.c:696
static ra8_err_t internal_do_repdist(ra8_rar5_state_t *st, uint32_t slot, uint8_t *out, size_t *out_pos, size_t unp)
Decode a remembered-distance LZ match (main symbols 258..261) into out.
Definition ra8_rar5.c:540
static ra8_err_t internal_read_filter(ra8_rar5_state_t *st, size_t out_pos)
Read one filter descriptor and queue it for post-decode replay.
Definition ra8_rar5.c:281
static uint32_t internal_adjust_length(uint32_t length, uint64_t dist)
Add the RAR5 distance-dependent bias to a match length.
Definition ra8_rar5.c:186
static uint32_t internal_read_filter_data(ra8_rar5_state_t *st)
Read one length/offset field of a RAR5 filter descriptor.
Definition ra8_rar5.c:255
bool priv_rar5_copy_match(uint8_t *out, size_t *out_pos, size_t unp, uint32_t length, uint64_t dist)
Implementation of priv_rar5_copy_match() – self-overlapping back-copy.
Definition ra8_rar5.c:225
static bool internal_x86_is_op(uint8_t op, bool e9)
Test whether op is an x86 branch opcode this filter transforms.
Definition ra8_rar5.c:339
static void internal_copy_object(void *dst, const void *src, size_t len)
Copy an object representation through compatible byte-pointer types.
Definition ra8_rar5.c:64
void priv_rar5_filter_delta(ra8_rar5_state_t *st, uint8_t *d, uint32_t len, uint32_t channels)
Implementation of priv_rar5_filter_delta() – per-channel running byte-sum.
Definition ra8_rar5.c:307
static const char *const s_tag_rar5
Log tag for RAR5 decoder diagnostics.
Definition ra8_rar5.c:49
static ra8_err_t internal_do_replast(ra8_rar5_state_t *st, uint8_t *out, size_t *out_pos, size_t unp)
Replay the last match (main symbol 257) into out.
Definition ra8_rar5.c:577
Clean-room RAR 5.0 ("method 50") decompressor – LZ + Huffman + filters.
@ k_ra8_rar5_max_filters
Pending data-filter records per member.
Definition ra8_rar5.h:83
@ k_ra8_rar5_delta_scratch
Delta-filter reorder buffer (in-place bound).
Definition ra8_rar5.h:85
@ k_ra8_rar5_old_dist
Remembered recent match distances.
Definition ra8_rar5.h:86
@ k_ra8_rar5_filter_delta
Per-channel byte-delta de-interleave.
Definition ra8_rar5.h:138
@ k_ra8_rar5_filter_arm
32-bit ARM BL branch-target transform.
Definition ra8_rar5.h:141
@ k_ra8_rar5_filter_e8e9
x86 E8+E9 call/jmp-target transform.
Definition ra8_rar5.h:140
@ k_ra8_rar5_filter_e8
x86 E8 call-target absolute->relative.
Definition ra8_rar5.h:139
Cross-TU seam between the RAR5 entropy front-end and the LZ decoder.
ra8_err_t priv_rar5_read_tables(ra8_rar5_state_t *st)
Parse a table block: build the BD pre-table then the four LZ tables.
uint32_t priv_rar5_get(ra8_rar5_state_t *st, uint32_t n)
Peek and consume n bits from the streaming reader in one step.
@ k_r5_x86_ilen
CALL/JMP instruction width.
@ k_r5_arm_bl
ARM BL opcode byte.
@ k_r5_x86_jmp
x86 near JMP opcode.
@ k_r5_x86_call
x86 near CALL opcode.
@ k_r5_byte_mask
Single-byte mask.
uint32_t priv_rar5_decode_num(ra8_rar5_state_t *st, const ra8_rar5_dtab_t *d)
Decode one Huffman symbol from d, consuming its code bits.
@ k_r5_byte_bits
Bits per packed byte.
ra8_err_t priv_rar5_read_block_header(ra8_rar5_state_t *st, r5_block_t *b)
Read and validate one RAR5 block header at the current bit position.
@ k_r5_sym_filter
Read one data filter.
@ k_r5_sym_lenbase
First LZ length slot.
@ k_r5_sym_replast
Repeat the last match.
@ k_r5_sym_repdist0
First remembered distance.
@ k_r5_arm_off_mask
ARM BL 24-bit word offset.
@ k_r5_ftype_bits
Filter-type field width.
@ k_r5_fchan_bits
Delta channel-count field width.
@ k_r5_max_pad_bits
Bit slack past the packed member end.
@ k_r5_dist_th2
+1 more above this distance.
@ k_r5_dist_th3
+1 more above this distance.
@ k_r5_dist_th1
+1 length above this distance.
@ k_ra8_rar_ver_5
RAR 5.0 block format ("RAR5").
Definition ra8_rar.h:100
Decoded fields of one RAR5 compressed-block header.
uint32_t last_bits
Valid bits in the block's last byte.
bool last
Block is the last in the file.
bool tables
Block carries fresh Huffman tables.
uint64_t size
Block size in bytes from BlockStart.
One pending RAR5 data filter recorded during decode, applied after.
Definition ra8_rar5.h:123
uint8_t channels
Delta channel count (1..32); unused otherwise.
Definition ra8_rar5.h:127
uint32_t len
Length of the transformed range in bytes.
Definition ra8_rar5.h:125
uint8_t type
Filter kind (ra8_rar5_filter_kind_t).
Definition ra8_rar5.h:126
uint64_t start
Absolute output offset the filter transforms from.
Definition ra8_rar5.h:124
Caller-owned zero-heap scratch for one ra8_rar5_decompress call.
One open RAR archive: the backing plus the detected generation.
Definition ra8_rar.h:144
ra8_rar_version_t version
Detected container generation.
Definition ra8_rar.h:149