56 lines
1.7 KiB
C
56 lines
1.7 KiB
C
/**
|
|
* DreamStack Delta Codec — C port for ESP32-P4
|
|
*
|
|
* Ported from engine/ds-stream/src/codec.rs (lines 109-179)
|
|
* Exact same encoding: 0x00 + 2-byte LE count = zero run.
|
|
*/
|
|
|
|
#include "ds_codec.h"
|
|
#include <string.h>
|
|
|
|
size_t ds_rle_decode(const uint8_t *compressed, size_t comp_len,
|
|
uint8_t *output, size_t out_cap) {
|
|
size_t i = 0; // input position
|
|
size_t o = 0; // output position
|
|
|
|
while (i < comp_len) {
|
|
if (compressed[i] == 0x00) {
|
|
// Zero run: 0x00 + count_lo + count_hi
|
|
if (i + 2 >= comp_len) break;
|
|
uint16_t count = (uint16_t)compressed[i + 1]
|
|
| ((uint16_t)compressed[i + 2] << 8);
|
|
if (o + count > out_cap) return 0; // overflow
|
|
memset(output + o, 0, count);
|
|
o += count;
|
|
i += 3;
|
|
} else {
|
|
// Literal byte
|
|
if (o >= out_cap) return 0;
|
|
output[o++] = compressed[i++];
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
void ds_xor_apply(uint8_t *framebuffer, const uint8_t *delta, size_t len) {
|
|
// Process 4 bytes at a time for speed on 32-bit RISC-V
|
|
size_t i = 0;
|
|
size_t aligned = len & ~3u;
|
|
for (; i < aligned; i += 4) {
|
|
*(uint32_t *)(framebuffer + i) ^= *(const uint32_t *)(delta + i);
|
|
}
|
|
for (; i < len; i++) {
|
|
framebuffer[i] ^= delta[i];
|
|
}
|
|
}
|
|
|
|
int ds_apply_delta_rle(uint8_t *framebuffer, size_t fb_len,
|
|
const uint8_t *compressed, size_t comp_len,
|
|
uint8_t *scratch) {
|
|
size_t decoded_len = ds_rle_decode(compressed, comp_len, scratch, fb_len);
|
|
if (decoded_len == 0 || decoded_len != fb_len) {
|
|
return -1;
|
|
}
|
|
ds_xor_apply(framebuffer, scratch, fb_len);
|
|
return 0;
|
|
}
|