mirror of
https://gitlab.com/zephray/glider.git
synced 2024-11-14 04:57:54 +00:00
143 lines
4.4 KiB
C
143 lines
4.4 KiB
C
|
// Eink waveform flash decompressor
|
||
|
// Copyright 2024 Wenting Zhang
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
// of this software and associated documentation files (the "Software"), to deal
|
||
|
// in the Software without restriction, including without limitation the rights
|
||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
// copies of the Software, and to permit persons to whom the Software is
|
||
|
// furnished to do so, subject to the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be included in
|
||
|
// all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
// SOFTWARE.
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <assert.h>
|
||
|
#include <inttypes.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#define MAX_DECOMP_SIZE (0x100000)
|
||
|
|
||
|
static uint32_t read_uint16_be(uint8_t *ptr) {
|
||
|
uint32_t b0 = (uint32_t)(*ptr++) << 8;
|
||
|
uint32_t b1 = (uint32_t)(*ptr++);
|
||
|
return b0 | b1;
|
||
|
}
|
||
|
|
||
|
static uint32_t read_uint16_le(uint8_t *ptr) {
|
||
|
uint32_t b0 = (uint32_t)(*ptr++);
|
||
|
uint32_t b1 = (uint32_t)(*ptr++) << 8;
|
||
|
return b0 | b1;
|
||
|
}
|
||
|
|
||
|
static uint32_t read_uint32_be(uint8_t *ptr) {
|
||
|
uint32_t b0 = (uint32_t)(*ptr++) << 24;
|
||
|
uint32_t b1 = (uint32_t)(*ptr++) << 16;
|
||
|
uint32_t b2 = (uint32_t)(*ptr++) << 8;
|
||
|
uint32_t b3 = (uint32_t)(*ptr++);
|
||
|
return b0 | b1 | b2 | b3;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
fprintf(stderr, "Eink waveform flash decompressor\n");
|
||
|
|
||
|
if (argc != 3) {
|
||
|
fprintf(stderr, "Usage: wbf_flash_decompress input_file output_file\n");
|
||
|
fprintf(stderr, "input_file: Compressed flash ROM (like a flash dump)\n");
|
||
|
fprintf(stderr, "output_file: WBF file name\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
char *bin = argv[1];
|
||
|
char *wbf = argv[2];
|
||
|
|
||
|
FILE * fp;
|
||
|
size_t file_size;
|
||
|
char * file_buffer;
|
||
|
size_t result;
|
||
|
|
||
|
fp = fopen(bin, "rb");
|
||
|
assert(fp);
|
||
|
|
||
|
// obtain file size:
|
||
|
fseek(fp, 0, SEEK_END);
|
||
|
file_size = ftell(fp);
|
||
|
fseek(fp, 0, SEEK_SET);
|
||
|
|
||
|
// allocate memory to contain the whole file:
|
||
|
file_buffer = (char*)malloc(sizeof(char) * file_size);
|
||
|
assert(file_buffer);
|
||
|
|
||
|
// copy the file into the buffer:
|
||
|
assert(fread(file_buffer, file_size, 1, fp) == 1);
|
||
|
|
||
|
fclose(fp);
|
||
|
|
||
|
printf("File size: %zu bytes\n", file_size);
|
||
|
|
||
|
uint8_t *ptr = (uint8_t *)file_buffer;
|
||
|
uint32_t compressed_len = read_uint32_be(ptr);
|
||
|
ptr += 4;
|
||
|
uint32_t header_version = read_uint32_be(ptr);
|
||
|
|
||
|
printf("Compressed length: %d bytes\n", compressed_len);
|
||
|
|
||
|
if ((compressed_len + 16) > file_size) {
|
||
|
printf("Error: file size smaller than expected.\n");
|
||
|
return -1;
|
||
|
}
|
||
|
else if ((compressed_len + 16) < file_size) {
|
||
|
printf("Warning: file size larger than expected.\n");
|
||
|
}
|
||
|
|
||
|
printf("Header version: %d\n", header_version);
|
||
|
|
||
|
if (header_version != 1) {
|
||
|
printf("Unsupported file version\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Start decompress
|
||
|
ptr = (uint8_t *)file_buffer + 16; // skip header
|
||
|
static uint8_t decomp_buffer[MAX_DECOMP_SIZE];
|
||
|
uint32_t wrptr = 0;
|
||
|
uint8_t *ptr_end = ptr + compressed_len;
|
||
|
while (ptr < ptr_end) {
|
||
|
uint32_t wrptr_snapshot = wrptr;
|
||
|
uint32_t offset = (uint32_t)read_uint16_le(ptr);
|
||
|
ptr += 2;
|
||
|
uint8_t len = *ptr++;
|
||
|
uint8_t byte = *ptr++;
|
||
|
printf("Ptr %d, Offset %d, Len %d, Byte 0x%02x\n", wrptr_snapshot, offset, len, byte);
|
||
|
if (len != 0) {
|
||
|
printf("Src: %d\n", wrptr_snapshot - offset);
|
||
|
}
|
||
|
for (int i = 0; i < len; i++) {
|
||
|
// len could be zero, in this case the loop doesn't execute
|
||
|
uint8_t rd = decomp_buffer[wrptr_snapshot - offset + i];
|
||
|
decomp_buffer[wrptr++] = rd;
|
||
|
}
|
||
|
decomp_buffer[wrptr++] = byte;
|
||
|
}
|
||
|
|
||
|
printf("Decompressed size: %d bytes\n", wrptr);
|
||
|
|
||
|
fp = fopen(wbf, "wb");
|
||
|
fwrite(decomp_buffer, wrptr, 1, fp);
|
||
|
fclose(fp);
|
||
|
printf("Done\n");
|
||
|
|
||
|
return 0;
|
||
|
}
|