/* * 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 "Input.h" #include "Output.h" #include "generic.h" #include "lzss.h" #include "Main.h" int lga = 0; 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 } }; CODE_BEGINS public: Appli() : lzsscompress(1), lzss_o(new lzss) {} virtual ~Appli() { delete lzss_o; } private: char * fn1, * fn2, * pname; int lzsscompress; lzss * lzss_o; 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, lzsscompress ? "" : "de"); } void showscheme(void) { lzss::scheme_t scheme = lzss_o->get_scheme(); 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; lzss::schemes[i].name; i++) { printm(M_BARE, "%2i - %s\n", i, lzss::schemes[i].name); } } virtual int startup() throw (GeneralException) { int length = -1; Handle * f1, * f2; int p, show = 0; int c, s, t; lzss::scheme_t scheme = lzss_o->get_scheme(); pname = strdup(argv[0]); p = strlen(pname) - 5; verbosity = M_STATUS; #ifdef __linux__ if (!strcasecmp(pname + p, "dlzss")) { lzsscompress = 0; } #endif printm(M_BARE, LZSS_NAME + " compressor/decompressor version " + LZSS_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 'lzss' 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); if (s >= lzss_o->END) { printm(M_ERROR, "%s: value too high (no such scheme)\n", s); exit(-1); } scheme = lzss::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': lzsscompress = 0; break; case 'c': lzsscompress = 1; break; case 'b': lzss_o->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++]; f1 = new Input(fn1); f2 = new Output(fn2); if (lzsscompress) { printm(M_STATUS, "Compressing `%s' to `%s'...\n", fn1, fn2); } else { printm(M_STATUS, "Decompressing `%s' to `%s'...\n", fn1, fn2); } lzss_o->change_scheme(scheme); if (lzsscompress) { if (length == -1) { lzss_o->lzss_comp(f1, f2); } else { lzss_o->lzss_comp(f1, f2, &length); } } else { length = lzss_o->lzss_decomp(f1, f2, length); } printm(M_STATUS, "Done, filesize changed from %i to %i.\n", f1->GetSize(), f2->GetSize()); if (!lzss_o->bitmap_count) lzss_o->bitmap_count = 8; if (lzsscompress) printm(M_STATUS, "Compressed %i = 0x%08x blocs, containing %i = 0x%08x chunks.\n", lzss_o->blk + 1, lzss_o->blk + 1, lzss_o->blk * 8 + lzss_o->bitmap_count, lzss_o->blk * 8 + lzss_o->bitmap_count); delete f1; delete f2; return 0; } CODE_ENDS