/* * 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 #include #include #include #include #include "fileutils.h" #include "generic.h" #include "lz77.h" int lz77_maxsize = 18; int lz77_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; lz77_maxsize = shift(val1 & scheme.l_mask_1, scheme.l_shft_1) | shift(val2 & scheme.l_mask_2, scheme.l_shft_2); lz77_maxptr = shift(val1 & scheme.j_mask_1, scheme.j_shft_1) | shift(val2 & scheme.j_mask_2, scheme.j_shft_2); lz77_maxsize = lz77_maxsize + 3 + scheme.sixteen_bits; lz77_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", lz77_maxsize, lz77_maxptr); } unsigned long lz77_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 &= lz77_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 == lz77_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 - lz77_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 lz77_rd(unsigned char * t, long p) { return ((p < 0) ? 0 : (t[p])); } long lz77_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 < lz77_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] == lz77_rd(r, i)) { if (p == (lz77_maxsize - 1)) { *l = lz77_maxsize; return i - lz77_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 * lz77_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 - lz77_maxptr; farest = farest > ((-lz77_maxsize) * scheme.negative_trick) ? farest : -lz77_maxsize * scheme.negative_trick; needle_length = ptr - farest; if (scheme.ptrb == 2) { farest = 0; needle_length = MIN(lz77_maxptr - scheme.window_start, ptr); } needle = lz77_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, lz77_rd(r, needle + j - scheme.window_start), ptr + j, lz77_rd(r, ptr + j)); if (lz77_rd(r, needle + j) != lz77_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 = lz77_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 lz77_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 = lz77_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); } #ifdef LZ77_MAIN char * fn1, * fn2, * pname; int lga = 0; int compress = 1; struct option long_options[] = { {"1iscomp", 1, &lga, 1 }, {"overlap", 1, &lga, 2 }, {"16bits", 1, &lga, 11 }, {"negative", 1, &lga, 12 }, {"ptrb", 1, &lga, 13 }, {"filling", 1, &lga, 14 }, {"inverse", 1, &lga, 23 }, {"onejump", 1, &lga, 24 }, {"window", 1, &lga, 25 }, {"lmask1", 1, &lga, 3 }, {"lshft1", 1, &lga, 4 }, {"lmask2", 1, &lga, 5 }, {"lshft2", 1, &lga, 6 }, {"jmask1", 1, &lga, 7 }, {"jshft1", 1, &lga, 8 }, {"jmask2", 1, &lga, 9 }, {"jshft2", 1, &lga, 10 }, {"fmask1", 1, &lga, 15 }, {"fshft1", 1, &lga, 16 }, {"fmask2", 1, &lga, 17 }, {"fshft2", 1, &lga, 18 }, {"vmask1", 1, &lga, 19 }, {"vshft1", 1, &lga, 20 }, {"vmask2", 1, &lga, 21 }, {"vshft2", 1, &lga, 22 }, {"help", 0, NULL, 'h'}, {"scheme", 1, NULL, 's'}, {"length", 1, NULL, 'l'}, {"version", 0, NULL, 'V'}, {"verbose", 0, NULL, 'v'}, {"show", 0, NULL, 'S'}, {"dump", 0, NULL, 'D'}, {"compress", 0, NULL, 'c'}, {"decompress", 0, NULL, 'd'}, {"blocks", 0, NULL, 'b'}, {0, 0, NULL, 0 } }; void showhelp(void) { printm(M_BARE, "Usages:\n" " %s <--help|-h|-H|-?> Show this help and exit.\n" " %s <--dump> Show the built-in schemes and exit.\n" " %s <--version|-V> Show the version and copyrights and exit.\n" " %s [-c|-d] [-s ] [-l ] [-S] [-v] \n" "\n" "-c --compress Compress to \n" "-d --decompress Decompress to \n" "-s --scheme= Loads the built-in scheme number \n" "-l --length= Specify the true length for decompression,\n" " or enable the padding behavior for compression.\n" "-S --show Show the actual scheme before processing.\n" "-v --verbose Display a *LOT* of informations.\n" "-b --blocks Switch to blocks decompression behaviour\n" "\n" "Additionnaly you have the scheme manipulation options:\n" "--1iscomp --overlap --negative --16bits --ptrb\n" "--filling --inverse --onejump --window\n" "--lmask1 --lshft1 --lmask2 --lshft2 --jmask1 --jshft1 --jmask2 --jshft2\n" "--vmask1 --vshft1 --vmask2 --vshft2 --fmask1 --fshft1 --fmask2 --fshft2\n" "\n" "If you don't know what they are, forget them.\n" "\n" "Default behavior is to %scompress.\n" "\n", pname, pname, pname, pname, compress ? "" : "de"); } void showscheme(void) { printm(M_BARE, "Actual scheme:\n" "--1iscomp %i\n" "--overlap %i\n" "--negative %i\n" "--16bits %i\n" "--ptrb %i\n" "--filling %i\n" "--inverse %i\n" "--onejump %i\n" "--window %i\n" "--lmask1 0x%02x\n" "--lshft1 %i\n" "--lmask2 0x%02x\n" "--lshft2 %i\n" "--jmask1 0x%02x\n" "--jshft1 %i\n" "--jmask2 0x%02x\n" "--jshft2 %i\n" "--fmask1 0x%02x\n" "--fshft1 %i\n" "--fmask2 0x%02x\n" "--fshft2 %i\n" "--vmask1 0x%02x\n" "--vshft1 %i\n" "--vmask2 0x%02x\n" "--vshft2 %i\n" "\n", scheme.one_is_compressed, scheme.overlap_trick, scheme.negative_trick, scheme.sixteen_bits, scheme.ptrb, scheme.filling, scheme.bitmap_inversed, scheme.one_jump, scheme.window_start, scheme.l_mask_1, scheme.l_shft_1, scheme.l_mask_2, scheme.l_shft_2, scheme.j_mask_1, scheme.j_shft_1, scheme.j_mask_2, scheme.j_shft_2, scheme.f_mask_1, scheme.f_shft_1, scheme.f_mask_2, scheme.f_shft_2, scheme.v_mask_1, scheme.v_shft_1, scheme.v_mask_2, scheme.v_shft_2); } void dump(void) { int i; printm(M_BARE, "Built-in schemes:\n"); for (i = 0; schemes[i].name; i++) { printm(M_BARE, "%2i - %s\n", i, schemes[i].name); } } int main(int argc, char ** argv) { long length = -1; FILE * f1, * f2; int p, show = 0; int c, s, t; pname = strdup(argv[0]); p = strlen(pname) - 5; verbosity = M_STATUS; if (!strcasecmp(pname + p, "dlz77")) { compress = 0; } printm(M_BARE, LZ77_NAME " compressor/decompressor version " LZ77_VERSION ",\n" "Copyright (C) 2002 Nicolas \"Pixel\" Noble\n" "This software comes with ABSOLUTELY NO WARRANTY; see COPYING for details\n" "Thanks to Czar Dragon, for his little 'LZ77' schemes FAQ.\n" "Special thanks to Yazoo, who taught me PSX hacking.\n" "\n"); while ((c = getopt_long(argc, argv, "Hhs:l:vVScdb", long_options, NULL)) != EOF) { switch (c) { case 0: switch (lga) { case 1: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.one_is_compressed = t; } break; case 2: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.overlap_trick = t; } break; case 3: sscanf(optarg, "%i", &scheme.l_mask_1); break; case 4: scheme.l_shft_1 = atoi(optarg); break; case 5: sscanf(optarg, "%i", &scheme.l_mask_2); break; case 6: scheme.l_shft_2 = atoi(optarg); break; case 7: sscanf(optarg, "%i", &scheme.j_mask_1); break; case 8: scheme.j_shft_1 = atoi(optarg); break; case 9: sscanf(optarg, "%i", &scheme.j_mask_2); break; case 10: scheme.j_mask_2 = atoi(optarg); break; case 11: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.sixteen_bits = t; } break; case 12: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.negative_trick = t; } break; case 13: t = atoi(optarg); if ((t != 2) && (t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for ter: %s\n", optarg); } else { scheme.ptrb = t; } break; case 14: t = atoi(optarg); if ((t != 2) && (t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for ter: %s\n", optarg); } else { scheme.filling = t; } break; case 15: sscanf(optarg, "%i", &scheme.f_mask_1); break; case 16: scheme.f_shft_1 = atoi(optarg); break; case 17: sscanf(optarg, "%i", &scheme.f_mask_2); break; case 18: scheme.f_shft_2 = atoi(optarg); break; case 19: sscanf(optarg, "%i", &scheme.v_mask_1); break; case 20: scheme.v_shft_1 = atoi(optarg); break; case 21: sscanf(optarg, "%i", &scheme.v_mask_2); break; case 22: scheme.v_mask_2 = atoi(optarg); break; case 23: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.bitmap_inversed = t; } break; case 24: t = atoi(optarg); if ((t != 1) && (t != 0)) { printm(M_ERROR, "Invalid value for boolean: %s\n", optarg); } else { scheme.one_jump = t; } break; case 25: t = sscanf(optarg, "%i", &scheme.window_start); break; default: showhelp(); printm(M_ERROR, "Unknow option.\n"); exit(-1); } break; case '?': case 'H': case 'h': showhelp(); exit(0); case 's': s = atoi(optarg); scheme = schemes[s]; break; case 'l': length = atoi(optarg); break; case 'v': verbosity = M_INFO; break; case 'V': exit(0); case 'S': show = 1; break; case 'D': dump(); exit(0); break; case 'd': compress = 0; break; case 'c': compress = 1; break; case 'b': blockb = 1; break; default: showhelp(); printm(M_ERROR, "Unknow option.\n"); exit(-1); } } if (show) showscheme(); if (optind != (argc - 2)) { if (optind > (argc - 2)) { printm(M_ERROR, "Not enough filenames\n"); exit(-1); } else { printm(M_ERROR, "Too much arguments\n"); exit(-1); } } fn1 = argv[optind++]; fn2 = argv[optind++]; if (!(f1 = fopen(fn1, "r"))) { printm(M_ERROR, "Error opening file %s for reading.\n", fn1); } if (!(f2 = fopen(fn2, "w"))) { printm(M_ERROR, "Error opening file %s for writing.\n", fn2); } if (compress) { printm(M_STATUS, "Compressing `%s' to `%s'...\n", fn1, fn2); } else { printm(M_STATUS, "Decompressing `%s' to `%s'...\n", fn1, fn2); } if (compress) { if (length == -1) { lz77_comp(f1, f2); } else { lz77_comp(f1, f2, &length); } } else { length = lz77_decomp(f1, f2, length); } printm(M_STATUS, "Done, filesize changed from %i to %i.\n", filesize(f1), filesize(f2)); if (!bitmap_count) bitmap_count = 8; if (compress) printm(M_STATUS, "Compressed %i = 0x%08x blocs, containing %i = 0x%08x chunks.\n", blk + 1, blk + 1, blk * 8 + bitmap_count, blk * 8 + bitmap_count); fclose(f1); fclose(f2); exit(0); } #endif