uz.c
来自「CC386 is a general-purpose 32-bit C comp」· C语言 代码 · 共 502 行
C
502 行
/*
Copyright 2001-2003 Free Software Foundation, Inc.
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.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
**********************************************************************
UZ.C unzips a zip-compressed database. In this case we are uncompressing
the splash screen
**********************************************************************
*/
#include <setjmp.h>
#include <string.h>
unsigned CRCtab[256];
unsigned currentcrc;
unsigned char masktab[9] =
{
0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
};
unsigned char tab7_rearrange[0x13] =
{
0x10, 0x11, 0x12, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
};
unsigned accum, accum_count;
int inflatepos = 0;
jmp_buf inflate_sync, inflate_badtab;
char inflate_tab_1[0x140];
unsigned char inflate_tab_2[32];
short inflate_tab_3[256];
short inflate_tab_4[256];
unsigned short inflate_tab_5[0x240];
unsigned short inflate_tab_6[64];
unsigned char inflate_tab_7[0x13];
unsigned short inflate_tab_8[0x116];
unsigned short intermed_tab[16];
unsigned short intermed_tab_2[16];
unsigned short intermed_tab_3[0x140];
int if1_count, if2_count;
int outputPos = 0;
unsigned char *inflatebuf, *outputQueue;
void CreateCRCTab(void)
{
int i;
for (i = 0; i < 256; i++)
{
unsigned k = i, j;
for (j = 0; j < 8; j++)
{
if (k &1)
{
k >>= 1;
k ^= 0xEdB88320;
}
else
k >>= 1;
}
CRCtab[i] = k;
}
}
//-------------------------------------------------------------------------
void increment_crc(unsigned char *data, int len)
{
int i;
for (i = 0; i < len; i++)
currentcrc = (currentcrc >> 8) ^ CRCtab[ *data++ ^ (unsigned char)
currentcrc];
}
//-------------------------------------------------------------------------
void fetchbyte(void)
{
accum |= (inflatebuf[inflatepos++]) << 8;
accum_count = 8;
}
//-------------------------------------------------------------------------
void shr_n_bits(int count)
{
if (count >= accum_count)
{
accum >>= accum_count;
count = count - accum_count;
fetchbyte();
}
accum >>= count;
accum_count -= count;
}
//-------------------------------------------------------------------------
unsigned get_n_bits_b(int count)
{
int rv = accum &masktab[count];
shr_n_bits(count);
return rv;
}
//-------------------------------------------------------------------------
unsigned get_n_bits_w(int count)
{
int rv = get_n_bits_b(8);
rv += (get_n_bits_b(count - 8) << 8);
return rv;
}
//-------------------------------------------------------------------------
unsigned get_n_bits(int count)
{
if (count > 8)
return get_n_bits_w(count);
else
return get_n_bits_b(count);
}
//-------------------------------------------------------------------------
void BadTable(void)
{
longjmp(inflate_badtab, 1);
}
//-------------------------------------------------------------------------
void ExpandTables(unsigned short *dest2, unsigned short *dest, unsigned char
*source, int len)
{
int i;
short sum = 0, xlen = 0;
unsigned short *idest;
if (!len)
return ;
memset(intermed_tab, 0, sizeof(intermed_tab) *2);
for (i = 0; i < len; i++)
intermed_tab[source[i]]++;
intermed_tab_2[1] = 0;
for (i = 1; i < 16; i++)
{
sum += intermed_tab[i];
sum <<= 1;
intermed_tab_2[i + 1] = sum;
}
if (sum)
{
sum = 0;
for (i = 1; i < 16; i++)
sum += intermed_tab[i];
if (sum > 1)
{
BadTable();
}
}
for (i = 0; i < len; i++)
if (source[i] == 0)
intermed_tab_3[i] = 0;
else
intermed_tab_3[i] = intermed_tab_2[source[i]]++;
idest = intermed_tab_3;
for (i = 0; i < len; i++)
{
sum = source[i] - 1;
if (sum <= 0)
idest++;
else
{
short shift = *idest;
short shift1 = 0;
do
{
shift1 <<= 1;
if (shift &1)
shift1 |= 1;
shift >>= 1;
}
while (--sum && shift != 0);
shift1 <<= 1;
if (shift &1)
shift1 |= 1;
shift1 <<= sum;
*(idest)++ = shift1;
}
}
memset(dest, 0, 256 *2);
idest = intermed_tab_3;
source += len - 1;
idest += len - 1;
for (i = len - 1; i >= 0; i--)
{
if (sum = *source--)
{
if (sum > 8)
{
short *xdest = dest + (*idest &0xff);
int j, shift = 1, mask = *idest >> 8;
sum -= 8;
for (j = 0; j < sum; j++)
{
unsigned val;
if (*xdest == 0)
{
*xdest = ~xlen;
dest2[xlen] = dest2[xlen + 1] = 0;
xlen += 2;
}
xdest = ~ * xdest + dest2;
if (mask &shift)
xdest++;
shift <<= 1;
}
*xdest = i;
}
else
{
int pos = *idest;
sum = 1 << sum;
do
{
dest[pos] = i;
pos += sum;
}
while (pos < 0x100);
}
}
idest--;
}
}
//-------------------------------------------------------------------------
void GetInflateTables(void)
{
int v = get_n_bits(2);
int count, scount, i, len, val, shift;
unsigned char *xdest;
switch (v)
{
case 0:
/* copy data in the clear */
if (accum_count != 8)
shr_n_bits(accum_count);
count = accum;
scount = inflatebuf[inflatepos++];
scount |= inflatebuf[inflatepos++] << 8;
if (((count ^ scount) + 1) == 0)
{
do
{
outputQueue[outputPos++] = inflatebuf[inflatepos++];
}
while (--count);
longjmp(inflate_sync, 1);
}
else
{
BadTable();
}
break;
case 1:
/* default tabs */
memset(inflate_tab_1, 8, 0x90);
memset(inflate_tab_1 + 0x90, 9, 0x70);
memset(inflate_tab_1 + 0x100, 7, 0x18);
memset(inflate_tab_1 + 0x118, 8, 0x8);
if2_count = 32;
memset(inflate_tab_2, 5, 32);
if1_count = 0x120;
break;
case 2:
/* compressed tabs */
if1_count = get_n_bits(5) + 0x101;
if2_count = get_n_bits(5) + 1;
memset(inflate_tab_7, 0, 0x13);
len = get_n_bits(4) + 4;
for (i = 0; i < len; i++)
inflate_tab_7[tab7_rearrange[i]] = get_n_bits(3);
ExpandTables(tab7_rearrange + len, inflate_tab_8, inflate_tab_7,
0x13);
xdest = inflate_tab_1;
for (i = if1_count + if2_count; i > 0;)
{
val = inflate_tab_8[accum &0xff];
shr_n_bits(inflate_tab_7[val]);
if (val < 0x10)
{
*xdest++ = val;
i--;
}
else
{
switch (val)
{
case 0x10:
val = get_n_bits(2) + 3;
shift = *(xdest - 1);
break;
case 0x11:
val = get_n_bits(3) + 3;
shift = 0;
break;
default:
val = get_n_bits(7) + 11;
shift = 0;
break;
}
if ((i -= val) < 0)
{
BadTable();
}
memset(xdest, shift, val);
xdest += val;
}
}
memcpy(inflate_tab_2, inflate_tab_1 + if1_count, if2_count);
break;
case 3:
BadTable();
break;
}
ExpandTables(inflate_tab_5, inflate_tab_3, inflate_tab_1, if1_count);
ExpandTables(inflate_tab_6, inflate_tab_4, inflate_tab_2, if2_count);
}
//-------------------------------------------------------------------------
unsigned fancymove(short b, short *tab, int *count)
{
short c;
*count = 0;
shr_n_bits(8);
c = accum &0xff;
do
{
b = ~b;
(*count)++;
b &= ~1;
if (c &1)
b |= 1;
c >>= 1;
}
while ((b = tab[b]) < 0);
return b;
}
//-------------------------------------------------------------------------
unsigned consulttabs1(void)
{
short b = (accum &0xff);
int count, shift;
if ((b = inflate_tab_3[b]) >= 0)
shr_n_bits(count = inflate_tab_1[b]);
else
{
b = fancymove(b, inflate_tab_5, &count);
shr_n_bits(count);
}
if (b < 0x109)
return b;
if (b == 0x11d)
{
return 0x200;
}
b -= 0x101;
shift = (b >> 2) - 1;
b = (((b &3) + 4) << shift) + 0x101;
b += get_n_bits(shift);
return b;
}
//-------------------------------------------------------------------------
unsigned consulttabs2(void)
{
short b = (accum &0xff);
int count, shift;
if ((b = inflate_tab_4[b]) >= 0)
shr_n_bits(count = inflate_tab_2[b]);
else
{
b = fancymove(b, inflate_tab_6, &count);
shr_n_bits(count);
}
if ((b &0xff) >= 4)
{
shift = (b &0xff) / 2-1;
b = ((b &1) + 2) << shift;
b += get_n_bits(shift);
}
return b;
}
//-------------------------------------------------------------------------
int Inflate(unsigned char *idata, unsigned char *odata)
{
int i;
unsigned matchword = 0;
inflatebuf = idata;
outputQueue = odata;
inflatepos = outputPos = 0;
CreateCRCTab();
if (setjmp(inflate_badtab))
{
printf("Bad Table");
return 0;
}
setjmp(inflate_sync);
accum = inflatebuf[inflatepos++];
accum |= inflatebuf[inflatepos++] << 8;
accum_count = 8;
while (matchword == 0)
{
matchword <<= 1;
matchword |= accum &1;
shr_n_bits(1);
GetInflateTables();
while (1)
{
int val = consulttabs1(), b;
if (!(val &0xff00))
{
outputQueue[outputPos++] = val &0xff;
}
else
{
char *src;
if (val == 0x100)
break;
val -= 0xfe;
b = consulttabs2();
src = outputQueue + outputPos - 1-b;
for (i = 0; i < val; i++)
{
outputQueue[outputPos++] = *src++;
}
}
}
}
return 1;
}
//-------------------------------------------------------------------------
unsigned char *InflateWrap(unsigned char *data)
{
int outsize = *(int*)(data + 22);
unsigned char *buf = calloc(outsize, 1);
if (!buf)
return 0;
if (Inflate(data + 30+*(int*)(data + 26), buf))
return buf;
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?