mirror of
https://github.com/exoticorn/upkr.git
synced 2026-01-20 11:36:42 +01:00
first try of c decompressor, not working yet
This commit is contained in:
5
c_unpacker/.gitignore
vendored
Normal file
5
c_unpacker/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
unpack
|
||||||
|
unpack_bitstream
|
||||||
|
unpack_debug
|
||||||
|
*.upk
|
||||||
|
|
||||||
10
c_unpacker/Makefile
Normal file
10
c_unpacker/Makefile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
all: unpack unpack_bitstream
|
||||||
|
|
||||||
|
unpack: main.c unpack.c
|
||||||
|
cc -O2 -o unpack main.c unpack.c
|
||||||
|
|
||||||
|
unpack_bitstream: main.c unpack.c
|
||||||
|
cc -O2 -D UPKR_BITSTREAM -o unpack_bitstream main.c unpack.c
|
||||||
|
|
||||||
|
unpack_debug: main.c unpack.c
|
||||||
|
cc -g -o unpack_debug main.c unpack.c
|
||||||
25
c_unpacker/main.c
Normal file
25
c_unpacker/main.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int upkr_unpack(void* destination, void* compressed_data);
|
||||||
|
|
||||||
|
int main(int argn, char** argv) {
|
||||||
|
void* input_buffer = malloc(1024*1024);
|
||||||
|
void* output_buffer = malloc(1024*1024);
|
||||||
|
|
||||||
|
FILE* in_file = fopen(argv[1], "rb");
|
||||||
|
int in_size = fread(input_buffer, 1, 1024*1024, in_file);
|
||||||
|
fclose(in_file);
|
||||||
|
|
||||||
|
printf("Compressed size: %d\n", in_size);
|
||||||
|
|
||||||
|
int out_size = upkr_unpack(output_buffer, input_buffer);
|
||||||
|
|
||||||
|
printf("Uncompressed size: %d\n", out_size);
|
||||||
|
|
||||||
|
FILE* out_file = fopen(argv[2], "wb");
|
||||||
|
fwrite(output_buffer, 1, out_size, out_file);
|
||||||
|
fclose(out_file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
97
c_unpacker/unpack.c
Normal file
97
c_unpacker/unpack.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned long u32;
|
||||||
|
|
||||||
|
u8* upkr_data_ptr;
|
||||||
|
u8 upkr_probs[1 + 255 + 1 + 2*32 + 2*32];
|
||||||
|
#ifdef UPKR_BITSTREAM
|
||||||
|
u16 upkr_state;
|
||||||
|
u8 upkr_current_byte;
|
||||||
|
int upkr_bits_left;
|
||||||
|
#else
|
||||||
|
u32 upkr_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int upkr_decode_bit(int context_index) {
|
||||||
|
#ifdef UPKR_BITSTREAM
|
||||||
|
while(upkr_state < 32768) {
|
||||||
|
if(upkr_bits_left == 0) {
|
||||||
|
upkr_current_byte = *upkr_data_ptr++;
|
||||||
|
upkr_bits_left = 8;
|
||||||
|
}
|
||||||
|
upkr_state = (upkr_state << 1) + (upkr_current_byte & 1);
|
||||||
|
upkr_current_byte >>= 1;
|
||||||
|
--upkr_bits_left;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
while(upkr_state < 4096) {
|
||||||
|
upkr_state = (upkr_state << 8) | *upkr_data_ptr++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int prob = upkr_probs[context_index];
|
||||||
|
int bit = (upkr_state & 255) < prob ? 1 : 0;
|
||||||
|
|
||||||
|
if(bit) {
|
||||||
|
upkr_state = prob * (upkr_state >> 8) + (upkr_state & 255);
|
||||||
|
upkr_probs[context_index] = prob + ((255 - prob + 8) >> 4);
|
||||||
|
} else {
|
||||||
|
upkr_state = (255 - prob) * (upkr_state >> 8) + (upkr_state & 255) - prob;
|
||||||
|
upkr_probs[context_index] = prob - ((prob + 8) >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int upkr_decode_length(int context_index) {
|
||||||
|
int length = 0;
|
||||||
|
int bit_pos = 0;
|
||||||
|
while(upkr_decode_bit(context_index)) {
|
||||||
|
length |= upkr_decode_bit(context_index + 1) << bit_pos++;
|
||||||
|
context_index += 2;
|
||||||
|
}
|
||||||
|
return length | (1 << bit_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
int upkr_unpack(void* destination, void* compressed_data) {
|
||||||
|
upkr_data_ptr = (u8*)compressed_data;
|
||||||
|
upkr_state = 0;
|
||||||
|
#ifdef UPKR_BITSTREAM
|
||||||
|
upkr_bits_left = 0;
|
||||||
|
#endif
|
||||||
|
for(int i = 0; i < sizeof(upkr_probs); ++i)
|
||||||
|
upkr_probs[i] = 128;
|
||||||
|
|
||||||
|
u8* write_ptr = (u8*)destination;
|
||||||
|
|
||||||
|
int prev_was_match = 0;
|
||||||
|
int offset = 0;
|
||||||
|
for(;;) {
|
||||||
|
if(upkr_decode_bit(0)) {
|
||||||
|
if(prev_was_match || upkr_decode_bit(256)) {
|
||||||
|
offset = upkr_decode_length(257) - 1;
|
||||||
|
if(offset == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int length = upkr_decode_length(257 + 64);
|
||||||
|
while(length-- > 1) {
|
||||||
|
*write_ptr = write_ptr[-offset];
|
||||||
|
++write_ptr;
|
||||||
|
}
|
||||||
|
prev_was_match = 1;
|
||||||
|
} else {
|
||||||
|
int context_index = 1;
|
||||||
|
int byte = 0;
|
||||||
|
for(int i = 0; i < 8; ++i) {
|
||||||
|
int bit = upkr_decode_bit(context_index);
|
||||||
|
context_index = (context_index << 1) + bit;
|
||||||
|
byte |= bit << i;
|
||||||
|
}
|
||||||
|
*write_ptr++ = byte;
|
||||||
|
prev_was_match = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return write_ptr - (u8*)destination;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user