Skip to content

Instantly share code, notes, and snippets.

@iGlitch
Last active January 7, 2021 23:55
Show Gist options
  • Save iGlitch/74790206e7e9c774d5ae80cc0e5d24fe to your computer and use it in GitHub Desktop.
Save iGlitch/74790206e7e9c774d5ae80cc0e5d24fe to your computer and use it in GitHub Desktop.
// LZSS decompressor
#include <stdio.h>
#include <stdlib.h>
#include <sys\stat.h>
char *decode_lzss_stuff(FILE *fp_i, unsigned int *length_ptr) {
unsigned char *outbuffer = NULL; // decoded data
// should check for size overflow, but I'm going to be stupid and not do so
unsigned int buffersize = 163840; // arbitrary initial size
//unsigned char curbyte, controlbyte;
unsigned char controlbyte;
unsigned int bufferindex = 0;
unsigned int i = 0; // used for looping
unsigned char tempbuffer[10]; // actually only 2-3 bytes should be needed
unsigned int num_bytes_to_copy = 0;
unsigned int backwards_offset = 0;
unsigned int iter_count = 0;
int copy_start_index = 0;
unsigned int copy_counter = 0;
outbuffer = malloc(buffersize);
if(outbuffer == NULL) {
printf("Unable to allocate memory.\n");
return NULL;
}
// copy the first 16 bytes (or 32)
for(i = 0; i < 16; i++) { //i < 32
outbuffer[bufferindex] = fgetc(fp_i);
bufferindex++;
}
//check that the next byte is 0x11
if (fgetc(fp_i) != 0x11) {
printf("Input file does not appear to be LZSS compressed.\n");
exit(-1);
}
//skip the next 3 bytes
for(i = 0; i < 3; i++) {
fgetc(fp_i);
}
while(!feof(fp_i)) {
if(bufferindex > (buffersize-8000)) { // give a big safety margin for fun
buffersize *= 2; // increase buffer size
outbuffer = realloc(outbuffer, buffersize);
if(outbuffer == NULL) {
printf("Unable to allocate memory.\n");
return NULL;
}
}
controlbyte = fgetc(fp_i);
if(feof(fp_i)) {
continue;
}
//printf("Control byte: 0x%02x\n", controlbyte);
//if(bufferindex > 0xC70 && bufferindex < 0xCF0) {
/*if(bufferindex > 0xC70) {
printf("Control byte: 0x%02x\n", controlbyte);
}*/
for(i = 0; i < 8; i++) {
if(controlbyte & (0x80 >> i)) {
//printf("Encoded data...\n");
// decode encoded data
tempbuffer[0] = fgetc(fp_i);
tempbuffer[1] = fgetc(fp_i);
if((tempbuffer[0] & 0xF0) == 0x10) {
tempbuffer[2] = fgetc(fp_i);
tempbuffer[3] = fgetc(fp_i);
num_bytes_to_copy = (((unsigned int) (tempbuffer[0] & 0x0F)) * 0x1000) + (((unsigned int) tempbuffer[1]) * 0x10) + (tempbuffer[2] >> 4) + 0x111;
backwards_offset = (((unsigned int) (tempbuffer[2] & 0x0F)) * 0x100) + tempbuffer[3] + 1;
}
// if the first nibble is 0, get a third byte
else if((tempbuffer[0] & 0xF0) == 0) {
tempbuffer[2] = fgetc(fp_i);
//printf("0x %02x %02x %02x\n", tempbuffer[0], tempbuffer[1], tempbuffer[2]);
//*length_ptr = bufferindex;
//return outbuffer;
//num_bytes_to_copy = (((unsigned int) tempbuffer[0] >> 4) * 0x100) + tempbuffer[2] + 0x2F;
//num_bytes_to_copy = (((unsigned int) tempbuffer[0] >> 4) * 0x100) + tempbuffer[2] + 0x13;
num_bytes_to_copy = (((unsigned int) tempbuffer[0]) * 0x10) + (tempbuffer[1] >> 4) + 0x11;
backwards_offset = (((unsigned int) (tempbuffer[1] & 0x0F)) * 0x100) + tempbuffer[2] + 1;
//backwards_offset = (((unsigned int) (tempbuffer[0] & 0x0F)) * 0x100) + tempbuffer[1];
//printf("0x %02x %02x %02x #B %x\n", tempbuffer[0], tempbuffer[1], tempbuffer[2], num_bytes_to_copy);
}
else {
tempbuffer[2] = 0x00;
//printf("0x %02x %02x\n", tempbuffer[0], tempbuffer[1]);
num_bytes_to_copy = (tempbuffer[0] >> 4) + 0x01;
//num_bytes_to_copy = (tempbuffer[0] >> 4) - 0x00;
backwards_offset = (((unsigned int) (tempbuffer[0] & 0x0F)) * 0x100) + tempbuffer[1] + 1;
//backwards_offset = (((unsigned int) (tempbuffer[0] & 0x0F)) * 0x100) + tempbuffer[1] - 2;
}
if(backwards_offset <= 0) {
printf("Error: Backwards offset is <= 0, this probably is wrong.\n");
}
else {
//printf("0x%03x bytes to copy, from an backwards offset of 0x%03x.\n",
// num_bytes_to_copy, backwards_offset);
copy_start_index = bufferindex - backwards_offset;
if(copy_start_index < 0) {
printf("Error: Copy start index is < 0, this probably is wrong.\n");
}
for(copy_counter = 0; copy_counter < num_bytes_to_copy; copy_counter++) {
if(bufferindex > (buffersize - 16)) {
printf("Buffer overflow ahoy! Trying to save things! bufferindex = %d\n", bufferindex);
break;
}
else if((copy_start_index + copy_counter) >= bufferindex) {
printf("Copying uninitialized data? I think not!\n");
//printf("copy_start_index = %d\n", copy_start_index);
//printf("copy_counter = %d\n", copy_counter);
//printf("Backwards offset coding bytes: 0x %02x %02x %02x\n",
// tempbuffer[0], tempbuffer[1], tempbuffer[2]);
//printf("num_bytes_to_copy = %d\n", num_bytes_to_copy);
//printf("backwards_offset = %d\n", backwards_offset);
//printf("bufferindex = %d\n", bufferindex);
//printf("buffersize = %d\n", buffersize);
break;
}
else {
outbuffer[bufferindex] = outbuffer[copy_start_index + copy_counter];
bufferindex++;
}
} // end copy loop
//if(bufferindex > 0xC70 && bufferindex < 0xCF0) {
/*if(bufferindex > 0xC70) {
printf("(end copy loop)\n");
}*/
} // end valid backwards offset
} // end encoded data
else {
outbuffer[bufferindex] = fgetc(fp_i);
//if(bufferindex > 0xC70 && bufferindex < 0xCF0) {
/*if(bufferindex > 0xC70) {
printf("0x%02x (literal)\n", outbuffer[bufferindex]);
}*/
bufferindex++;
} // end literal data
}
/*if(iter_count > 40) {
break;
}*/
iter_count++;
}
if(length_ptr != NULL) {
*length_ptr = bufferindex;
}
else {
printf("Hey, invalid length pointer supplied!\n");
}
return outbuffer;
}
int main(int argc, char *argv[]) {
FILE *fp_i, *fp_o;
unsigned char curbyte = 0;
unsigned int i = 0;
unsigned int decoded_length = 0;
//int startfound = 0;
char *outbuffer = NULL;
if(argc != 3) {
printf("Usage: delzss input output\n");
exit(-1);
}
fp_i = fopen(argv[1], "rb");
if(fp_i == NULL) {
printf("Error opening input file %s.\n", argv[1]);
exit(-1);
}
fp_o = fopen(argv[2], "wb");
if(fp_o == NULL) {
printf("Error opening output file %s.\n", argv[2]);
fclose(fp_i);
exit(-1);
}
outbuffer = decode_lzss_stuff(fp_i, &decoded_length);
// write the output, dropping the first 3c bytes to get to the start of the JPG data
fwrite(outbuffer, 1, decoded_length, fp_o);
// TODO: drop data past the end of JPG marker?
if(outbuffer != NULL) {
free(outbuffer);
}
fclose(fp_i);
fclose(fp_o);
chmod(argv[2], 0777); // for some reason umask didn't seem to work for this
return 0;
}
// Split stages into header (first 0x10 bytes), data (next 0x4A4 bytes), and JPEG (remainder)
#include <stdio.h>
#include <stdlib.h>
#include <sys\stat.h>
int main(int argc, char *argv[]) {
FILE *fp_i, *fp_o1, *fp_o2, *fp_o3;
unsigned int i = 0;
if(argc != 5) {
printf("Usage: SplitStage input_file output_header output_data output_jpeg\n");
exit(-1);
}
fp_i = fopen(argv[1], "rb");
if(fp_i == NULL) {
printf("Error opening input file %s.\n", argv[1]);
exit(-1);
}
fp_o1 = fopen(argv[2], "wb");
if(fp_o1 == NULL) {
printf("Error opening output file %s.\n", argv[2]);
fclose(fp_i);
exit(-1);
}
fp_o2 = fopen(argv[3], "wb");
if(fp_o2 == NULL) {
printf("Error opening output file %s.\n", argv[3]);
fclose(fp_i);
fclose(fp_o1);
exit(-1);
}
fp_o3 = fopen(argv[4], "wb");
if(fp_o3 == NULL) {
printf("Error opening output file %s.\n", argv[4]);
fclose(fp_i);
fclose(fp_o1);
fclose(fp_o2);
exit(-1);
}
for (i = 0; i < 0x10; i++) {
fputc(fgetc(fp_i), fp_o1);
}
for (i = 0; i < 0x4A4; i++) {
fputc(fgetc(fp_i), fp_o2);
}
while(!feof(fp_i)) {
fputc(fgetc(fp_i), fp_o3);
}
fclose(fp_i);
fclose(fp_o1);
fclose(fp_o2);
fclose(fp_o3);
//chmod(argv[2], 0777); // for some reason umask didn't seem to work for this
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment