diff options
Diffstat (limited to 'lzss.cpp')
-rw-r--r-- | lzss.cpp | 438 |
1 files changed, 0 insertions, 438 deletions
diff --git a/lzss.cpp b/lzss.cpp deleted file mode 100644 index 4f9e424..0000000 --- a/lzss.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <getopt.h> -#include <iostream> -#include "fileutils.h" -#include "generic.h" -#include "lzss.h" - -int lzss_maxsize = 18; -int lzss_maxptr = 0x0fff; -int tolerate = 1; -int blockb = 0; - -scheme_t schemes[] = { -/* Nom 1 I J O N 16 P F W Lm1 Ls1 Lm2 Ls2 Jm1 Js1 Jm2 Js2 Fm1 Fs1 Fm2 Fs2 Vm1 Vs1 Vm2 Vs2 */ - {"Xenogears", 1, 0, 0, 1, 0, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"DBZ RPG", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"FF7", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Leen Mean", 1, 1, 1, 1, 0, 0, 0, 0, 0, 0x0f, 0, 0x00, 0, 0xf0, 4, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Metal Max", 0, 0, 0, 1, 0, 0, 2, 0, 0x12, 0x00, 0, 0x0f, 0, 0xff, 0, 0xf0, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Ogre Battle", 0, 0, 0, 1, 0, 0, 1, 0, 0, 0xf8, -3, 0x00, 0, 0x07, 8, 0xff, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Lodoss Wars", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x7f, 0, 0xff, 0, 0x80, 1, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"FF6 PSX", 0, 0, 0, 1, 1, 1, 0, 0, 0, 0x1f, 1, 0x00, 0, 0xe0, -4, 0xff, 4, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Valkyrie-1", 0, 0, 0, 1, 1, 0, 0, 0, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0}, - {"Valkyrie-2", 0, 0, 0, 1, 1, 0, 0, 2, 0, 0x00, 0, 0xf0, -4, 0xff, 0, 0x0f, 8, 0x00, 0, 0x0f, 0, 0xff, 0, 0x00, 0}, - {0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0, 0x00, 0, 0x00, 0, 0x00, 0} -}; - -scheme_t scheme = schemes[0]; - -char swap_bits(char i) { - i = ((i >> 1) & 0x55) | ((i << 1) & 0xaa); - i = ((i >> 2) & 0x33) | ((i << 2) & 0xcc); - i = ((i >> 4) & 0x0f) | ((i << 4) & 0xf0); - return i; -} - -unsigned int shift(unsigned int c, int s) { - return s > 0 ? (c << s) : c >> (-s); -} - -void compute_limits(void) { - unsigned char val1, val2; - - val1 = val2 = 0xff; - - lzss_maxsize = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | - shift(val2 & scheme.l_mask_2, scheme.l_shft_2); - lzss_maxptr = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | - shift(val2 & scheme.j_mask_2, scheme.j_shft_2); - - lzss_maxsize = lzss_maxsize + 3 + scheme.sixteen_bits; - lzss_maxptr += scheme.one_jump; - - if (scheme.l_mask_1 & scheme.j_mask_1) { - printm(M_ERROR, "Masks are overlapping for value 1\n"); - exit(-1); - } - - if (scheme.l_mask_2 & scheme.j_mask_2) { - printm(M_ERROR, "Masks are overlapping for value 2\n"); - exit(-1); - } - - if (shift(scheme.l_mask_1, scheme.l_shft_1) & shift(scheme.l_mask_2, scheme.l_shft_2)) { - printm(M_ERROR, "Shifts build an overlap for lenght\n"); - exit(-1); - } - - if (shift(scheme.j_mask_1, scheme.j_shft_1) & shift(scheme.j_mask_2, scheme.j_shft_2)) { - printm(M_ERROR, "Shifts build an overlap for jump\n"); - exit(-1); - } - - printm(M_INFO, "Computed values: maxsize = %i, maxptr = 0x%06x\n", lzss_maxsize, lzss_maxptr); -} - -unsigned long lzss_decomp(FILE * f_source, FILE * f_cible, long true_length) -{ - unsigned char bitmap, fbitmap; - unsigned char valeur; - unsigned char * text_buf; - unsigned char val1, val2, val3; - int negative_error = scheme.negative_trick, overlap_error = scheme.overlap_trick; - int r = 0; - int decomp_count; - int decomp_length; - int decomp_fill; - int decomp_jump; - int decomp_offset = 0; - int loop_length; - int whole_count; - int i, j; - long length, reads; - - compute_limits(); - - fread(&length, 1, 4, f_source); - if (true_length >= 0) { - length = true_length; - } - whole_count = 0; - - printm(M_INFO, "Decompressing %i bytes\n", length); - - text_buf = (unsigned char *) malloc(length + 8); - - do { - fread(&bitmap, 1, 1, f_source); - if (scheme.sixteen_bits) { - fread(&fbitmap, 1, 1, f_source); - printm(M_INFO, "16bits behavior, false bitmap = %02x\n", fbitmap); - } - if (scheme.bitmap_inversed) { - bitmap = swap_bits(bitmap); - } - printm(M_INFO, "Begin of block, bitmap = %02x\n", bitmap); - for (i = 0; i < 8; i++) { - printm(M_INFO, " - Chunk %i (offset cible = %li = 0x%04x, offset source = %li = 0x%04x)\n", i, ftell(f_cible), ftell(f_cible), ftell(f_source), ftell(f_source)); - if (whole_count >= length) - break; - if ((bitmap & 1) ^ scheme.one_is_compressed) { - for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { - reads = fread(&valeur, 1, 1, f_source); - if (!reads) { - printm(M_WARNING, " WARNING! PADDING!\n"); - free(text_buf); - return length; - } - printm(M_INFO, " Copying 0x%02x\n", valeur); - fwrite(&valeur, 1, 1, f_cible); - text_buf[r++] = valeur; - whole_count++; - } - } else { - fread(&val1, 1, 1, f_source); - fread(&val2, 1, 1, f_source); - decomp_length = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | - shift(val2 & scheme.l_mask_2, scheme.l_shft_2); - decomp_fill = shift(val1 & scheme.f_mask_1, scheme.f_shft_1) | - shift(val2 & scheme.f_mask_2, scheme.f_shft_2); - decomp_jump = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | - shift(val2 & scheme.j_mask_2, scheme.j_shft_2); - valeur = shift(val1 & scheme.v_mask_1, scheme.v_shft_1) | - shift(val2 & scheme.v_mask_2, scheme.v_shft_2); - decomp_jump &= lzss_maxptr; - decomp_jump += scheme.one_jump; - decomp_length = decomp_length + 3 + scheme.sixteen_bits; - decomp_fill = decomp_fill + 3 + scheme.sixteen_bits; - if ((decomp_length == lzss_maxsize) && (scheme.filling)) { - if ((decomp_fill == 3) && (scheme.filling == 2)) { - fread(&val3, 1, 1, f_source); - printm(M_INFO, " Found an extended needle (val1 = 0x%02x, val2 = 0x%02x, val3 = 0x%02x)\n", val1, val2, val3); - decomp_fill = val1 + 19; - valeur = val3; - } else { - printm(M_INFO, " Found a 0x%02x-filling needle of %li bytes (val1 = 0x%02x, val2 = 0x%02x)\n", valeur, decomp_fill, val1, val2); - } - for (decomp_count = 0; decomp_count < decomp_fill; decomp_count++) { - fwrite(&valeur, 1, 1, f_cible); - text_buf[r++] = valeur; - if (!blockb) - whole_count++; - } - if (blockb) - whole_count++; - } else { - switch (scheme.ptrb) { - case 0: - decomp_offset = r - decomp_jump; - break; - case 1: - decomp_offset = r - lzss_maxptr - 1 + decomp_jump; - break; - case 2: - decomp_offset = decomp_jump - scheme.window_start; - break; - } - loop_length = decomp_offset + decomp_length; - if ((loop_length >= r) && (!overlap_error)) { - if (!tolerate) { - free(text_buf); - return 0; - } - printm(M_ERROR, "Overlap trick used without it beeing enabled in the scheme.\n"); - overlap_error = 1; - } - printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x, jump of %li = 0x%04x (val1 = 0x%02x, val2 = 0x%02x)\n", decomp_length, decomp_offset, decomp_offset, decomp_jump, decomp_jump, val1, val2); - for (decomp_count = decomp_offset; decomp_count < loop_length; decomp_count++) { - if (!blockb) - whole_count++; - if (decomp_count < 0) { - valeur = 0; - fwrite(&valeur, 1, 1, f_cible); - text_buf[r++] = 0; - if (!negative_error) { - if (!tolerate) { - free(text_buf); - return 0; - } - printm(M_ERROR, "Negative trick used without it beeing enabled in the scheme.\n"); - negative_error = 1; - } - printm(M_INFO, "Filling with 0\n"); - } else { - fwrite(&text_buf[decomp_count], 1, 1, f_cible); - printm(M_INFO, "@0x%04x: 0x%02x\n", decomp_count, text_buf[decomp_count]); - text_buf[r++] = text_buf[decomp_count]; - } - if (whole_count >= length) - break; - } - if (blockb) - whole_count++; - } - } - bitmap >>= 1; - } - } while (whole_count < length); - free(text_buf); - - return length; -} - -unsigned char lzss_rd(unsigned char * t, long p) { - return ((p < 0) ? 0 : (t[p])); -} - -long lzss_comp_strstr(unsigned char * needle, unsigned char * r, long * l, long sp) { - char redo[256]; - long length, i, p, ptr, maxlength; - - i = 1; - redo[0] = p = 0; - while (i < lzss_maxsize) { - if (needle[i] == needle[p]) { - redo[i++] = ++p; - } else if (p > 0) { - p = redo[p - 1]; - } else { - redo[i++] = 0; - } - } - - length = maxlength = 0; - i = sp; - p = 0; - ptr = 0; - - while ((i - sp - (scheme.overlap_trick ? p : 0)) < *l) { - if (needle[p] == lzss_rd(r, i)) { - if (p == (lzss_maxsize - 1)) { - *l = lzss_maxsize; - return i - lzss_maxsize + 1; - } - i++; - p++; - } else if (p > 0) { - if (p > maxlength) { - if (!((i - p) & scheme.sixteen_bits)) { - ptr = i - (maxlength = p); - } - } - p = redo[p - 1]; - } else { - i++; - } - } - - *l = maxlength; - return ptr; -} - -long blk, bitmap_count; - -unsigned char * lzss_memcomp(unsigned char * r, long * l, long * delta) { - unsigned char bitmap, * comp; - long ptr, needle, needle_length, comp_ptr, bitmap_ptr, val1, val2; - long jump, farest, remaining; - int j; - - comp = (unsigned char *) malloc(3 * *l); - - compute_limits(); - - ptr = 0; - blk = 0; - bitmap_count = 0; - comp_ptr = 1 + scheme.sixteen_bits; - bitmap = 0; - bitmap_ptr = 0; - printm(M_INFO, "Begin of block 0.\n"); - while ((remaining = *l - ptr) > 0) { - printm(M_INFO, " Remaining bytes: %li\n", remaining); - bitmap_count++; - bitmap >>= 1; - farest = ptr - lzss_maxptr; - farest = farest > ((-lzss_maxsize) * scheme.negative_trick) ? farest : -lzss_maxsize * scheme.negative_trick; - needle_length = ptr - farest; - if (scheme.ptrb == 2) { - farest = 0; - needle_length = MIN(lzss_maxptr - scheme.window_start, ptr); - } - needle = lzss_comp_strstr(&r[ptr], r, &needle_length, farest); - if ((needle < 0) && ((-needle) > needle_length)) { - needle = -needle_length; - } - printm(M_INFO, " - Chunk %i (offset source = %li = 0x%04x, offset cible = %li = 0x%04x)\n", bitmap_count - 1, ptr, ptr, comp_ptr, comp_ptr); - jump = ptr - needle; - needle_length = needle_length > remaining ? remaining : needle_length; - - if (needle_length & scheme.sixteen_bits) { - needle_length--; - } - - if ((needle < 0) || (!jump)) { - printm(M_INFO, " Nothing found.\n"); - } else { - printm(M_INFO, " Found a needle of %i bytes at offset %i (jump = %i = 0x%04x)\n", needle_length, needle, jump, jump); - } - - if ((needle_length <= (2 + scheme.sixteen_bits)) || (!jump)) { - if (needle_length > 2) { - printm(M_ERROR, " ** REJECTED **\n"); - } - for (j = 0; j < (scheme.sixteen_bits ? 2 : 1); j++) { - printm(M_INFO, " Repeating 0x%02x\n", r[ptr]); - comp[comp_ptr] = r[ptr]; - ptr++; - comp_ptr++; - } - bitmap |= 0x80; - } else { - int j; - printm(M_INFO, " Found a needle of %li bytes at %li = 0x%04x\n", needle_length, needle, needle); - for (j = 0; j < needle_length; j++) { - printm(M_INFO, "@0x%04x: 0x%02x - @0x%04x: 0x%02x\n", needle + j, lzss_rd(r, needle + j - scheme.window_start), ptr + j, lzss_rd(r, ptr + j)); - if (lzss_rd(r, needle + j) != lzss_rd(r, ptr + j)) { - printm(M_ERROR, "ERROR!!\n"); - } - } - jump -= scheme.one_jump; - printm(M_INFO, "ptr = %li, needle = %li, jump = %li = 0x%03x\n", ptr, needle, jump, jump); - ptr += needle_length; - needle_length -= 3; - switch (scheme.ptrb) { - case 0: - break; - case 1: - jump = lzss_maxptr + 1 - jump; - break; - case 2: - jump = needle + scheme.window_start; - break; - } - val1 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_1) & scheme.j_mask_1) | - (shift(needle_length, -scheme.l_shft_1) & scheme.l_mask_1); - val2 = comp[comp_ptr++] = (shift(jump, -scheme.j_shft_2) & scheme.j_mask_2) | - (shift(needle_length, -scheme.l_shft_2) & scheme.l_mask_2); - printm(M_INFO, " writing info1 = 0x%02x, info2 = 0x%02x\n", val1, val2); - } - - bitmap ^= scheme.one_is_compressed << 7; - - if (bitmap_count == 8) { - blk++; - printm(M_INFO, "End of block, writing bitmap = 0x%02x\n", bitmap); - printm(M_INFO, "Begin of block %li.\n", blk); - bitmap_count = 0; - if (scheme.bitmap_inversed) - bitmap = swap_bits(bitmap); - comp[bitmap_ptr] = bitmap; - if (scheme.sixteen_bits) { - comp[bitmap_ptr + 1] = 0; - } - bitmap_ptr = comp_ptr; - comp_ptr += (scheme.sixteen_bits ? 2 : 1); - } - } - - if (bitmap_count) { - bitmap >>= (8 - bitmap_count); - if (scheme.bitmap_inversed) - bitmap = swap_bits(bitmap); - comp[bitmap_ptr] = bitmap; - if (scheme.sixteen_bits) { - comp[bitmap_ptr + 1] = 0; - } - } else { - comp_ptr--; - } - - if (delta) { - *delta = (bitmap_count ? 8 - bitmap_count : 0); - } - - *l = comp_ptr; - return comp; -} - -void lzss_comp(FILE * f_source, FILE * f_cible, long * delta) { - long length = filesize(f_source), l; - unsigned char * r = (unsigned char *) malloc(length), * c; - - fread(r, 1, length, f_source); - l = length; - c = lzss_memcomp(r, &l, delta); - if (delta) { - length += *delta; - } - fwrite(&length, 1, 4, f_cible); - if (delta) { - length -= *delta; - } - fwrite(c, 1, l, f_cible); - free(c); - free(r); -} |