61 lines
1.3 KiB
C
61 lines
1.3 KiB
C
|
|
#include "fileio.h"
|
|
#include "unpack.h"
|
|
#include "util.h"
|
|
|
|
struct unpack_t {
|
|
uint8_t dict_buf[0x200 * 2];
|
|
uint8_t rd[0x1000];
|
|
int size;
|
|
int dict_len;
|
|
};
|
|
|
|
static struct unpack_t g_unpack;
|
|
|
|
int unpack(const char *filename, uint8_t *dst) {
|
|
const int f = fio_open(filename, 1);
|
|
|
|
fio_read(f, g_unpack.rd, 6);
|
|
g_unpack.size = (READ_LE_UINT16(g_unpack.rd) << 16) + READ_LE_UINT16(g_unpack.rd + 2);
|
|
const int dict_len = READ_LE_UINT16(g_unpack.rd + 4);
|
|
print_debug(DBG_UNPACK, "unpack '%s' size %d dict_len %d", filename, g_unpack.size, dict_len);
|
|
fio_read(f, g_unpack.dict_buf, dict_len);
|
|
|
|
const uint8_t *src = g_unpack.rd;
|
|
int len = 1;
|
|
int bytes_count = 2;
|
|
uint16_t bits = 0;
|
|
uint16_t val = 0;
|
|
while (1) {
|
|
--len;
|
|
if (len == 0) {
|
|
bytes_count -= 2;
|
|
if (bytes_count == 0) {
|
|
bytes_count = fio_read(f, g_unpack.rd, 0x1000);
|
|
if (bytes_count == 0) {
|
|
break;
|
|
}
|
|
bytes_count += (bytes_count & 1);
|
|
src = g_unpack.rd;
|
|
}
|
|
bits = READ_BE_UINT16(src); src += 2;
|
|
len = 17;
|
|
continue;
|
|
}
|
|
const int carry = (bits & 0x8000) != 0;
|
|
bits <<= 1;
|
|
if (carry) {
|
|
val += 2;
|
|
}
|
|
assert(val < 0x400);
|
|
val = READ_LE_UINT16(g_unpack.dict_buf + val);
|
|
if ((val & 0x8000) == 0) {
|
|
continue;
|
|
}
|
|
*dst++ = val & 255;
|
|
val = 0;
|
|
}
|
|
fio_close(f);
|
|
return g_unpack.size;
|
|
}
|