00001
00019
00020
00021 #ifdef MAIN_DERNC
00022 # include <stdio.h>
00023 # include <stdlib.h>
00024 # include <string.h>
00025 #endif
00026
00027 #define INTERNAL
00028 #include "lbfileio.h"
00029 #include "dernc.h"
00030
00031 #ifdef MAIN_DERNC
00032 int main_unpack (char *pname, char *iname, char *oname);
00033 int copy_file (char *iname, char *oname);
00034
00040 short show_usage(char *fname)
00041 {
00042 printf("usage:\n");
00043 printf(" %s <files>\n", fname);
00044 printf(" or\n");
00045 printf(" %s -o <infile> <outfile>\n", fname);
00046 return 1;
00047 }
00048
00055 int main(int argc, char **argv)
00056 {
00057 int mode=0;
00058 int i;
00059
00060 printf("\nPRO-PACK's alternate RNC files decompressor\n");
00061 printf("-------------------------------\n");
00062
00063 if (argc==1)
00064 {
00065 show_usage(*argv);
00066 return 0;
00067 }
00068 for (i=1; i < argc; i++)
00069 if (!strcmp (argv[i], "-o"))
00070 mode=i;
00071 if (mode && argc != 4)
00072 {
00073 show_usage(*argv);
00074 return 1;
00075 }
00076 switch (mode)
00077 {
00078 case 0 :
00079 for (i=1; i < argc; i++)
00080 {
00081 printf("Extracting %s...\n",argv[i]);
00082 if (main_unpack (*argv, argv[i], argv[i]))
00083 return 1;
00084 }
00085 return 0;
00086 case 1 :
00087 printf("Extracting %s to %s...\n",argv[2],argv[3]);
00088 return main_unpack (*argv, argv[2], argv[3]);
00089 case 2 :
00090 printf("Extracting %s to %s...\n",argv[1],argv[3]);
00091 return main_unpack (*argv, argv[1], argv[3]);
00092 case 3 :
00093 printf("Extracting %s to %s...\n",argv[1],argv[2]);
00094 return main_unpack (*argv, argv[1], argv[2]);
00095 default :
00096 fprintf (stderr, "Internal fault.\n");
00097 }
00098 return 1;
00099 }
00100
00109 int main_unpack (char *pname, char *iname, char *oname)
00110 {
00111 FILE *ifp, *ofp;
00112 long plen, ulen;
00113 void *packed, *unpacked;
00114 char buffer[4];
00115
00116 ifp = fopen(iname, "rb");
00117 if (!ifp)
00118 {
00119 perror(iname);
00120 return 1;
00121 }
00122
00123 fseek (ifp, 0L, SEEK_END);
00124 plen = ftell (ifp);
00125 rewind (ifp);
00126 if (plen < 4)
00127 {
00128 if (strcmp (iname, oname))
00129 return copy_file (iname, oname);
00130 return 0;
00131 }
00132 fread (buffer, 1, 4, ifp);
00133 if (strncmp (buffer, "RNC", 3))
00134 {
00135 fclose (ifp);
00136 if (strcmp (iname, oname))
00137 return copy_file (iname, oname);
00138 return 0;
00139 }
00140 rewind (ifp);
00141
00142 packed = malloc(plen+8);
00143 if (packed==NULL)
00144 {
00145 fclose(ifp);
00146 perror(pname);
00147 return 1;
00148 }
00149 unsigned long rdlen;
00150 rdlen=fread (packed, 1, plen, ifp);
00151 fclose(ifp);
00152
00153 ulen = rnc_ulen (packed);
00154 if (ulen < 0)
00155 {
00156 free(packed);
00157 if (ulen == -1)
00158 return 0;
00159 printf("Error: %s\n", rnc_error (ulen));
00160 return 1;
00161 }
00162
00163
00164 unpacked = malloc(ulen+8);
00165 if (unpacked==NULL)
00166 {
00167 free(packed);
00168 perror(pname);
00169 return 1;
00170 }
00171
00172
00173 ulen = rnc_unpack (packed, unpacked, RNC_IGNORE_NONE);
00174 if (ulen < 0)
00175 {
00176 printf("%s\n", rnc_error (ulen));
00177 return 1;
00178 }
00179
00180
00181 ofp = fopen(oname, "wb");
00182 if (!ofp)
00183 {
00184 perror(oname);
00185 return 1;
00186 }
00187
00188 fwrite (unpacked, 1, ulen, ofp);
00189 fclose (ofp);
00190
00191 free (unpacked);
00192 free (packed);
00193
00194 return 0;
00195 }
00196
00204 int copy_file (char *iname, char *oname)
00205 {
00206 char *sysbuf;
00207
00208 sysbuf = malloc (strlen (iname)+strlen(oname)+6);
00209 if (!sysbuf)
00210 {
00211 fprintf (stderr, "Out of memory.\n");
00212 return 1;
00213 }
00214 strcpy (sysbuf, "cp ");
00215 strcat (sysbuf, iname);
00216 strcat (sysbuf, " ");
00217 strcat (sysbuf, oname);
00218 system (sysbuf);
00219 free (sysbuf);
00220 return 0;
00221 }
00222
00223 #endif
00224
00231 typedef struct {
00232 unsigned long bitbuf;
00233 int bitcount;
00234 } bit_stream;
00235
00236 #define HUFTABLE_ENTRIES 32
00237
00241 typedef struct {
00242 int num;
00243 struct {
00244 unsigned long code;
00245 int codelen;
00246 int value;
00247 } table[HUFTABLE_ENTRIES];
00248 } huf_table;
00249
00250 #include "globals.h"
00251
00252 static void read_huftable (huf_table *h, bit_stream *bs,
00253 const unsigned char **p, const unsigned char *pend);
00254 static unsigned long huf_read (huf_table *h, bit_stream *bs,
00255 const unsigned char **p,const unsigned char *pend);
00256
00257 inline void bitread_init (bit_stream *bs, const unsigned char **p, const unsigned char *pend);
00258 inline void bitread_fix (bit_stream *bs, const unsigned char **p, const unsigned char *pend);
00259 inline unsigned long bit_peek (bit_stream *bs, unsigned long mask);
00260 inline void bit_advance (bit_stream *bs, int n,
00261 const unsigned char **p, const unsigned char *pend);
00262 static unsigned long bit_read (bit_stream *bs, unsigned long mask,
00263 int n, const unsigned char **p, const unsigned char *pend);
00264
00265 static unsigned long mirror (unsigned long x, int n);
00266
00272 char *rnc_error (long errcode)
00273 {
00274 static char *const errors[] = {
00275 "No error",
00276 "File is not RNC-1 format",
00277 "Huffman decode error",
00278 "File size mismatch",
00279 "CRC error in packed data",
00280 "CRC error in unpacked data",
00281 "Compressed file header invalid",
00282 "Huffman decode leads outside buffers",
00283 "Unknown error"
00284 };
00285
00286 errcode = -errcode;
00287 if (errcode < 0)
00288 errcode = 0;
00289 if (errcode > sizeof(errors)/sizeof(*errors) - 1)
00290 errcode = sizeof(errors)/sizeof(*errors) - 1;
00291 return errors[errcode];
00292 }
00293
00301 long rnc_ulen(void *packed)
00302 {
00303 unsigned char *p = packed;
00304 if (read_int32_be_buf(p) != RNC_SIGNATURE_INT)
00305 return RNC_FILE_IS_NOT_RNC;
00306 return read_int32_be_buf(p+4);
00307 }
00308
00316 long rnc_plen(void *packed)
00317 {
00318 unsigned char *p = packed;
00319 if (read_int32_be_buf(p) != RNC_SIGNATURE_INT)
00320 return RNC_FILE_IS_NOT_RNC;
00321 return read_int32_be_buf(p+8);
00322 }
00323
00327 long rnc_nocallback(long done,long total)
00328 {}
00329
00333 long rnc_printcallback(long done,long total)
00334 {
00335 printf("\rProcessing, %2.2f percent done",100.0*done/total);
00336 }
00337
00351 long rnc_unpack (const void *packed, void *unpacked, const unsigned int flags
00352 #ifdef COMPRESSOR
00353 , long *leeway
00354 #endif
00355 )
00356 {
00357 const unsigned char *input = (const unsigned char *)packed;
00358 unsigned char *output = (unsigned char *)unpacked;
00359 const unsigned char *inputend;
00360 unsigned char *outputend;
00361 bit_stream bs;
00362 huf_table raw, dist, len;
00363 unsigned long ch_count;
00364 unsigned long ret_len, inp_len;
00365 unsigned out_crc;
00366 #ifdef COMPRESSOR
00367 long lee = 0;
00368 #endif
00369
00370 if (read_int32_be_buf(input) != RNC_SIGNATURE_INT)
00371 if (!(flags&RNC_IGNORE_HEADER_VAL_ERROR)) return RNC_HEADER_VAL_ERROR;
00372 ret_len = read_int32_be_buf(input+4);
00373 inp_len = read_int32_be_buf(input+8);
00374 if ((ret_len>(RNC_MAX_FILESIZE))||(inp_len>(RNC_MAX_FILESIZE)))
00375 return RNC_HEADER_VAL_ERROR;
00376
00377 outputend = output + ret_len;
00378 inputend = input + SIZEOF_RNC_HEADER + inp_len;
00379 input += SIZEOF_RNC_HEADER;
00380
00381
00382
00383 if (rnc_crc(input, inputend-input) != read_int16_be_buf(input-4))
00384 if (!(flags&RNC_IGNORE_PACKED_CRC_ERROR)) return RNC_PACKED_CRC_ERROR;
00385 out_crc = read_int16_be_buf(input-6);
00386
00387 bitread_init(&bs, &input, inputend);
00388 bit_advance(&bs, 2, &input, inputend);
00389
00390
00391
00392 while (output < outputend)
00393 {
00394
00395 #ifdef COMPRESSOR
00396 long this_lee;
00397 #endif
00398 if (inputend-input<6)
00399 {
00400
00401 if (!(flags&RNC_IGNORE_HUF_EXCEEDS_RANGE))
00402 return RNC_HUF_EXCEEDS_RANGE;
00403 else
00404 {output=outputend;ch_count=0;break;}
00405 }
00406 read_huftable (&raw, &bs, &input, inputend);
00407 read_huftable (&dist, &bs, &input, inputend);
00408 read_huftable (&len, &bs, &input, inputend);
00409 ch_count = bit_read (&bs, 0xFFFF, 16, &input, inputend);
00410
00411 while (1)
00412 {
00413
00414 long length, posn;
00415
00416 length = huf_read(&raw, &bs, &input, inputend);
00417
00418 if (length < 0)
00419 {
00420 if (!(flags&RNC_IGNORE_HUF_DECODE_ERROR))
00421 return RNC_HUF_DECODE_ERROR;
00422 else
00423 {output=outputend;ch_count=0;break;}
00424 }
00425
00426 if (length)
00427 {
00428
00429 while (length--)
00430 {
00431 if ((input>=inputend)||(output>=outputend))
00432 {
00433
00434
00435 if (!(flags&RNC_IGNORE_HUF_EXCEEDS_RANGE))
00436 return RNC_HUF_EXCEEDS_RANGE;
00437 else
00438 {output=outputend;ch_count=0;break;}
00439 }
00440 *output++ = *input++;
00441 }
00442 bitread_fix (&bs, &input, inputend);
00443 }
00444
00445 if (--ch_count <= 0)
00446 break;
00447
00448
00449 posn = huf_read (&dist, &bs, &input, inputend);
00450
00451 if (posn == -1)
00452 {
00453 if (!(flags&RNC_IGNORE_HUF_DECODE_ERROR))
00454 return RNC_HUF_DECODE_ERROR;
00455 else
00456 {output=outputend;ch_count=0;break;}
00457 }
00458
00459 length = huf_read (&len, &bs, &input, inputend);
00460 if (length < 0)
00461 {
00462 if (!(flags&RNC_IGNORE_HUF_DECODE_ERROR))
00463 return RNC_HUF_DECODE_ERROR;
00464 else
00465 {output=outputend;ch_count=0;break;}
00466 }
00467 posn += 1;
00468 length += 2;
00469
00470 while (length--)
00471 {
00472 if ((((void *)output-posn)<unpacked)||((output-posn)>outputend)||
00473 (((void *)output)<unpacked)||((output)>outputend))
00474 {
00475
00476
00477 if (!(flags&RNC_IGNORE_HUF_EXCEEDS_RANGE))
00478 return RNC_HUF_EXCEEDS_RANGE;
00479 else
00480 {output=outputend;ch_count=0;break;}
00481 }
00482 output[0] = output[-posn];
00483 output++;
00484 }
00485 #ifdef COMPRESSOR
00486 this_lee = (inputend - input) - (outputend - output);
00487 if (lee < this_lee)
00488 lee = this_lee;
00489 #endif
00490 }
00491 }
00492
00493
00494
00495 if (outputend != output)
00496 {
00497 if (!(flags&RNC_IGNORE_FILE_SIZE_MISMATCH))
00498 return RNC_FILE_SIZE_MISMATCH;
00499 }
00500
00501 #ifdef COMPRESSOR
00502 if (leeway)
00503 *leeway = lee;
00504 #endif
00505
00506
00507
00508
00509 if (rnc_crc(outputend-ret_len, ret_len) != out_crc)
00510 {
00511
00512 if (!(flags&RNC_IGNORE_UNPACKED_CRC_ERROR))
00513 return RNC_UNPACKED_CRC_ERROR;
00514 }
00515
00516
00517 return ret_len;
00518 }
00519
00523
00524 void read_huftable (huf_table *h, bit_stream *bs,
00525 const unsigned char **p, const unsigned char *pend)
00526 {
00527 int i, j, k, num;
00528 int leaflen[32];
00529 int leafmax;
00530 unsigned long codeb;
00531
00532 num = bit_read (bs, 0x1F, 5, p, pend);
00533 if (!num)
00534 return;
00535
00536 leafmax = 1;
00537 for (i=0; i<num; i++)
00538 {
00539 leaflen[i] = bit_read (bs, 0x0F, 4, p, pend);
00540 if (leafmax < leaflen[i])
00541 leafmax = leaflen[i];
00542 }
00543
00544 codeb = 0L;
00545 k = 0;
00546 for (i=1; i<=leafmax; i++)
00547 {
00548 for (j=0; j<num; j++)
00549 if (leaflen[j] == i)
00550 {
00551 h->table[k].code = mirror (codeb, i);
00552 h->table[k].codelen = i;
00553 h->table[k].value = j;
00554 codeb++;
00555 k++;
00556 }
00557 codeb <<= 1;
00558 }
00559
00560 h->num = k;
00561 }
00562
00566 static unsigned long huf_read (huf_table *h, bit_stream *bs,
00567 const unsigned char **p,const unsigned char *pend)
00568 {
00569 int i;
00570 unsigned long val;
00571
00572 for (i=0; i<h->num; i++)
00573 {
00574 unsigned long mask = (1 << h->table[i].codelen) - 1;
00575 if (bit_peek(bs, mask) == h->table[i].code)
00576 break;
00577 }
00578 if (i == h->num)
00579 return -1;
00580 bit_advance (bs, h->table[i].codelen, p, pend);
00581
00582 val = h->table[i].value;
00583
00584 if (val >= 2)
00585 {
00586 val = 1 << (val-1);
00587 val |= bit_read (bs, val-1, h->table[i].value - 1, p, pend);
00588 }
00589 return val;
00590 }
00591
00598 inline void bitread_init (bit_stream *bs, const unsigned char **p, const unsigned char *pend)
00599 {
00600 if (pend-(*p) >= 1)
00601 {
00602 bs->bitbuf = (unsigned long)read_int16_le_buf(*p);
00603 bs->bitcount = 16;
00604 } else
00605 if (pend-(*p) >= 0)
00606 {
00607 bs->bitbuf = (unsigned long)read_int8_buf(*p);
00608 bs->bitcount = 8;
00609 } else
00610 bs->bitbuf = 0;
00611 }
00612
00619 inline void bitread_fix (bit_stream *bs, const unsigned char **p, const unsigned char *pend)
00620 {
00621 bs->bitcount -= 16;
00622 if (bs->bitcount<0) bs->bitcount=0;
00623 bs->bitbuf &= (1<<bs->bitcount)-1;
00624 int read_val;
00625
00626 if (pend-(*p) >= 1)
00627 {
00628 bs->bitbuf |= (read_int16_le_buf(*p)<<bs->bitcount);
00629 bs->bitcount += 16;
00630 } else
00631 if (pend-(*p) >= 0)
00632 {
00633 bs->bitbuf |= (read_int8_buf(*p)<<bs->bitcount);
00634 bs->bitcount += 8;
00635 }
00636 }
00637
00641 inline unsigned long bit_peek (bit_stream *bs, const unsigned long mask)
00642 {
00643 return bs->bitbuf & mask;
00644 }
00645
00653 inline void bit_advance (bit_stream *bs, int n,
00654 const unsigned char **p, const unsigned char *pend)
00655 {
00656 bs->bitbuf >>= n;
00657 bs->bitcount -= n;
00658 if (bs->bitcount < 16)
00659 {
00660 (*p) += 2;
00661 if (pend-(*p) >= 1)
00662 {
00663 bs->bitbuf |= ((unsigned long)read_int16_le_buf(*p)<<bs->bitcount);
00664 bs->bitcount += 16;
00665 } else
00666 if (pend-(*p) >= 0)
00667 {
00668 bs->bitbuf |= ((unsigned long)read_int8_buf(*p)<<bs->bitcount);
00669 bs->bitcount += 8;
00670 } else
00671 if (bs->bitcount < 0)
00672 bs->bitcount = 0;
00673 }
00674 }
00675
00676
00677
00678
00679
00680 static unsigned long bit_read (bit_stream *bs, unsigned long mask,
00681 int n, const unsigned char **p, const unsigned char *pend)
00682 {
00683 unsigned long result = bit_peek (bs, mask);
00684 bit_advance (bs, n, p, pend);
00685 return result;
00686 }
00687
00694 static unsigned long mirror (unsigned long x, int n)
00695 {
00696 unsigned long top = 1 << (n-1), bottom = 1;
00697 while (top > bottom)
00698 {
00699 unsigned long mask = top | bottom;
00700 unsigned long masked = x & mask;
00701 if (masked != 0 && masked != mask)
00702 x ^= mask;
00703 top >>= 1;
00704 bottom <<= 1;
00705 }
00706 return x;
00707 }
00708
00715 long rnc_crc(const void *data, unsigned long len)
00716 {
00717 static unsigned short crctab[256];
00718 static short crctab_ready=0;
00719 unsigned short val;
00720 int i, j;
00721 const unsigned char *p = data;
00722
00723 if (!crctab_ready)
00724 {
00725 for (i=0; i<256; i++)
00726 {
00727 val = i;
00728
00729 for (j=0; j<8; j++)
00730 {
00731 if (val & 1)
00732 val = (val >> 1) ^ 0xA001;
00733 else
00734 val = (val >> 1);
00735 }
00736 crctab[i] = val;
00737 }
00738 crctab_ready=1;
00739 }
00740
00741 val = 0;
00742 while (len--)
00743 {
00744 val ^= *p++;
00745 val = (val >> 8) ^ crctab[val & 0xFF];
00746 }
00747
00748 return val;
00749 }