mirror of
https://github.com/KranX/Vangers.git
synced 2025-11-30 23:15:27 +07:00
699 lines
12 KiB
C++
699 lines
12 KiB
C++
#include "xzip.h"
|
|
|
|
typedef unsigned char uchar;
|
|
//typedef unsigned short ushort;
|
|
//typedef unsigned long ulong;
|
|
|
|
struct huft;
|
|
|
|
#ifdef _LARGE_MODEL_
|
|
#define WSIZE 0x4000U
|
|
#define OUTBUFSIZ 0x800U
|
|
#else
|
|
#define WSIZE 0x8000U
|
|
#define OUTBUFSIZ 0x1000U
|
|
#endif
|
|
|
|
#define MIN_MATCH 3
|
|
#define MAX_MATCH 258
|
|
|
|
#define DYN_ALLOC
|
|
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
|
#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
|
|
|
|
#define UNKNOWN (-1)
|
|
#define BINARY 0
|
|
#define ASCII 1
|
|
|
|
#define STORE 0
|
|
#define DEFLATE 8
|
|
|
|
// ---------- EXTERN SECTION ----------
|
|
// ---------- PROTOTYPE SECTION ----------
|
|
|
|
int FlushMemory(void);
|
|
int FlushOutput(void);
|
|
void inflate(void);
|
|
int ReadMemoryByte(unsigned short* x);
|
|
|
|
// ---------- DEFINITION SECTION ----------
|
|
|
|
uchar* outbuf;
|
|
uchar* outptr;
|
|
|
|
uchar* slide;
|
|
|
|
int outcnt = 0;
|
|
int outpos = 0;
|
|
unsigned int bitbuf = 0;
|
|
int bits_left = 0;
|
|
char zipeof = 0;
|
|
|
|
unsigned short mask_bits[] = {
|
|
0x0000,
|
|
0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
|
|
0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
|
|
};
|
|
|
|
static uchar* mem_i_buffer;
|
|
static uchar* mem_o_buffer;
|
|
static unsigned int mem_i_size,mem_i_offset;
|
|
static unsigned int mem_o_size,mem_o_offset;
|
|
|
|
unsigned int ZIP_GetExpandedSize(char* p)
|
|
{
|
|
return *(unsigned int*)(p + 2);
|
|
}
|
|
|
|
void ZIP_expand(char* trg,unsigned int trgsize,char* src,unsigned int srcsize)
|
|
{
|
|
unsigned short method;
|
|
|
|
outbuf = new uchar[OUTBUFSIZ + 1];
|
|
slide = new uchar[WSIZE];
|
|
|
|
method = *(short*)(src);
|
|
|
|
mem_i_buffer = (uchar*)src + 2 + 4;
|
|
mem_i_size = srcsize - 2 - 4;
|
|
mem_i_offset = 0;
|
|
|
|
mem_o_buffer = (uchar*)trg;
|
|
mem_o_size = trgsize;
|
|
mem_o_offset = 0;
|
|
|
|
bits_left = 0;
|
|
bitbuf = 0L;
|
|
outpos = 0L;
|
|
outcnt = 0;
|
|
outptr = outbuf;
|
|
zipeof = 0;
|
|
memset(outbuf,0xAA,OUTBUFSIZ);
|
|
|
|
switch (method) {
|
|
case STORE:
|
|
memcpy(trg,src + 2 + 4,(unsigned)(srcsize - 2 - 4));
|
|
break;
|
|
case DEFLATE:
|
|
inflate();
|
|
FlushOutput();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
delete outbuf;
|
|
delete slide;
|
|
}
|
|
|
|
int FlushOutput(void)
|
|
{
|
|
int rc = FlushMemory();
|
|
outpos += outcnt;
|
|
outcnt = 0;
|
|
outptr = outbuf;
|
|
return rc;
|
|
}
|
|
|
|
int ReadMemoryByte(unsigned short* x)
|
|
{
|
|
if (mem_i_offset < mem_i_size) {
|
|
*x = (unsigned short) mem_i_buffer[mem_i_offset++];
|
|
return 8;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
int FlushMemory(void)
|
|
{
|
|
if(outcnt == 0)
|
|
return 0;
|
|
|
|
if(mem_o_offset + outcnt <= mem_o_size){
|
|
memcpy((char*)(mem_o_buffer + mem_o_offset),(char*)outbuf,outcnt);
|
|
mem_o_offset += outcnt;
|
|
return 0;
|
|
} else
|
|
return 50;
|
|
}
|
|
|
|
|
|
#define NEXTBYTE (ReadByte(&bytebuf), bytebuf)
|
|
#define NEEDBITS(n) {while(k<(n)){b|=((unsigned int)NEXTBYTE)<<k;k+=8;}}
|
|
#define DUMPBITS(n) {b>>=(n);k-=(n);}
|
|
|
|
#define BMAX 16
|
|
#define N_MAX 288
|
|
|
|
// ---------- EXTERN SECTION ----------
|
|
|
|
extern uchar* outptr;
|
|
extern int outcnt;
|
|
|
|
// ---------- PROTOTYPE SECTION ----------
|
|
|
|
int FlushOutput(void);
|
|
int ReadMemoryByte(unsigned short* x);
|
|
|
|
int huft_build(unsigned int* b,unsigned int n,unsigned int s,unsigned short* d,unsigned short* e,struct huft** t,int* m);
|
|
int huft_free(struct huft* t);
|
|
void flush(unsigned w);
|
|
int inflate_codes(struct huft* tl,struct huft* td,int bl,int bd);
|
|
int inflate_stored(void);
|
|
int inflate_fixed(void);
|
|
int inflate_dynamic(void);
|
|
int inflate_block(int* e);
|
|
int inflate_entry(void);
|
|
void inflate(void);
|
|
int ReadByte(unsigned short* x);
|
|
|
|
// ---------- DEFINITION SECTION ----------
|
|
|
|
struct huft {
|
|
uchar e;
|
|
uchar b;
|
|
union {
|
|
unsigned short n;
|
|
struct huft *t;
|
|
} v;
|
|
};
|
|
|
|
static unsigned border[] = {
|
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
|
static unsigned short cplens[] = {
|
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
|
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
|
static unsigned short cplext[] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
|
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99};
|
|
static unsigned short cpdist[] = {
|
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
|
8193, 12289, 16385, 24577};
|
|
static unsigned short cpdext[] = {
|
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
|
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
|
12, 12, 13, 13};
|
|
|
|
unsigned wp;
|
|
unsigned int bb;
|
|
unsigned bk;
|
|
unsigned short bytebuf;
|
|
|
|
int lbits = 9;
|
|
int dbits = 6;
|
|
|
|
unsigned hufts;
|
|
|
|
int huft_build(unsigned int* b,unsigned int n,unsigned int s,unsigned short* d,unsigned short* e,struct huft** t,int* m)
|
|
{
|
|
unsigned a;
|
|
unsigned c[BMAX+1];
|
|
unsigned f;
|
|
int g;
|
|
int h;
|
|
unsigned i;
|
|
unsigned j;
|
|
int k;
|
|
int l;
|
|
unsigned *p;
|
|
struct huft *q;
|
|
struct huft r;
|
|
struct huft *u[BMAX];
|
|
unsigned v[N_MAX];
|
|
int w;
|
|
unsigned x[BMAX+1];
|
|
unsigned *xp;
|
|
int y;
|
|
unsigned z;
|
|
|
|
memset(c, 0,sizeof(c));
|
|
p = b; i = n;
|
|
do {
|
|
c[*p++]++;
|
|
} while(--i);
|
|
if(c[0] == n)
|
|
return 2;
|
|
|
|
l = *m;
|
|
for(j = 1; j <= BMAX; j++)
|
|
if(c[j])
|
|
break;
|
|
k = j;
|
|
if((unsigned)l < j)
|
|
l = j;
|
|
for(i = BMAX; i; i--)
|
|
if(c[i])
|
|
break;
|
|
g = i;
|
|
if((unsigned)l > i)
|
|
l = i;
|
|
*m = l;
|
|
|
|
for(y = 1 << j; j < i; j++,y <<= 1)
|
|
if((y -= c[j]) < 0)
|
|
return 2;
|
|
if((y -= c[i]) < 0)
|
|
return 2;
|
|
c[i] += y;
|
|
|
|
x[1] = j = 0;
|
|
p = c + 1; xp = x + 2;
|
|
while(--i){
|
|
*xp++ = (j += *p++);
|
|
}
|
|
|
|
p = b; i = 0;
|
|
do {
|
|
if((j = *p++) != 0)
|
|
v[x[j]++] = i;
|
|
} while(++i < n);
|
|
|
|
x[0] = i = 0;
|
|
p = v;
|
|
h = -1;
|
|
w = -l;
|
|
u[0] = (struct huft*)NULL;
|
|
q = (struct huft*)NULL;
|
|
z = 0;
|
|
|
|
for(; k <= g; k++){
|
|
a = c[k];
|
|
while(a--){
|
|
while(k > w + l){
|
|
h++;
|
|
w += l;
|
|
z = (z = g - w) > (unsigned)l ? l : z;
|
|
if((f = 1 << (j = k - w)) > a + 1)
|
|
{
|
|
f -= a + 1;
|
|
xp = c + k;
|
|
while(++j < z)
|
|
{
|
|
if((f <<= 1) <= *++xp)
|
|
break;
|
|
f -= *xp;
|
|
}
|
|
}
|
|
z = 1 << j;
|
|
q = new huft[z + 1];
|
|
hufts += z + 1;
|
|
*t = q + 1;
|
|
*(t = &(q->v.t)) = (struct huft*)NULL;
|
|
u[h] = ++q;
|
|
|
|
if(h){
|
|
x[h] = i;
|
|
r.b = (uchar)l;
|
|
r.e = (uchar)(16 + j);
|
|
r.v.t = q;
|
|
j = i >> (w - l);
|
|
u[h-1][j] = r;
|
|
}
|
|
}
|
|
|
|
r.b = (uchar)(k - w);
|
|
if(p >= v + n)
|
|
r.e = 99;
|
|
else
|
|
if(*p < s){
|
|
r.e = (uchar)(*p < 256 ? 16 : 15);
|
|
r.v.n = *p++;
|
|
}
|
|
else {
|
|
r.e = (uchar)e[*p - s]; /* non-simple--look up in lists */
|
|
r.v.n = d[*p++ - s];
|
|
}
|
|
|
|
f = 1 << (k - w);
|
|
for(j = i >> w; j < z; j += f)
|
|
q[j] = r;
|
|
|
|
for(j = 1 << (k - 1); i & j; j >>= 1)
|
|
i ^= j;
|
|
i ^= j;
|
|
|
|
while((i & ((1 << w) - 1)) != x[h]){
|
|
h--;
|
|
w -= l;
|
|
}
|
|
}
|
|
}
|
|
return y != 0 && n != 1;
|
|
}
|
|
|
|
int huft_free(struct huft* t)
|
|
{
|
|
struct huft *p,*q;
|
|
p = t;
|
|
while(p != (struct huft*)NULL){
|
|
q = (--p)->v.t;
|
|
// free(p);
|
|
delete p;
|
|
p = q;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void flush(unsigned w)
|
|
{
|
|
unsigned n;
|
|
uchar *p;
|
|
|
|
p = slide;
|
|
while(w){
|
|
n = (n = OUTBUFSIZ - outcnt) < w ? n : w;
|
|
memcpy(outptr,p,n);
|
|
outptr += n;
|
|
if((outcnt += n) == OUTBUFSIZ)
|
|
FlushOutput();
|
|
p += n;
|
|
w -= n;
|
|
}
|
|
}
|
|
|
|
int inflate_codes(struct huft* tl,struct huft* td,int bl,int bd)
|
|
{
|
|
unsigned e;
|
|
unsigned n,d;
|
|
unsigned w;
|
|
struct huft *t;
|
|
unsigned ml,md;
|
|
unsigned int b;
|
|
unsigned k;
|
|
|
|
b = bb;
|
|
k = bk;
|
|
w = wp;
|
|
|
|
ml = mask_bits[bl];
|
|
md = mask_bits[bd];
|
|
while(1){
|
|
NEEDBITS((unsigned)bl)
|
|
if((e = (t = tl + ((unsigned)b & ml))->e) > 16)
|
|
do {
|
|
if(e == 99)
|
|
return 1;
|
|
DUMPBITS(t->b)
|
|
e -= 16;
|
|
NEEDBITS(e)
|
|
} while((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
|
|
DUMPBITS(t->b)
|
|
if(e == 16){
|
|
slide[w++] = (uchar)t->v.n;
|
|
if(w == WSIZE){
|
|
flush(w);
|
|
w = 0;
|
|
}
|
|
}
|
|
else {
|
|
if(e == 15)
|
|
break;
|
|
NEEDBITS(e)
|
|
n = t->v.n + ((unsigned)b & mask_bits[e]);
|
|
DUMPBITS(e);
|
|
NEEDBITS((unsigned)bd)
|
|
if((e = (t = td + ((unsigned)b & md))->e) > 16)
|
|
do {
|
|
if(e == 99)
|
|
return 1;
|
|
DUMPBITS(t->b)
|
|
e -= 16;
|
|
NEEDBITS(e)
|
|
} while((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
|
|
DUMPBITS(t->b)
|
|
NEEDBITS(e)
|
|
d = w - t->v.n - ((unsigned)b & mask_bits[e]);
|
|
DUMPBITS(e)
|
|
do {
|
|
n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
|
|
if(w - d >= e){
|
|
memcpy(slide + w,slide + d,e);
|
|
w += e;
|
|
d += e;
|
|
}
|
|
else
|
|
do {
|
|
slide[w++] = slide[d++];
|
|
} while(--e);
|
|
if(w == WSIZE){
|
|
flush(w);
|
|
w = 0;
|
|
}
|
|
} while(n);
|
|
}
|
|
}
|
|
wp = w;
|
|
bb = b;
|
|
bk = k;
|
|
return 0;
|
|
}
|
|
|
|
int inflate_stored(void)
|
|
{
|
|
unsigned n;
|
|
unsigned w;
|
|
unsigned int b;
|
|
unsigned k;
|
|
|
|
b = bb;
|
|
k = bk;
|
|
w = wp;
|
|
n = k & 7;
|
|
DUMPBITS(n);
|
|
|
|
NEEDBITS(16)
|
|
n = ((unsigned)b & 0xffff);
|
|
DUMPBITS(16)
|
|
NEEDBITS(16)
|
|
if(n != (unsigned)((~b) & 0xffff))
|
|
return 1;
|
|
DUMPBITS(16)
|
|
|
|
while(n--){
|
|
NEEDBITS(8)
|
|
slide[w++] = (uchar)b;
|
|
if(w == WSIZE){
|
|
flush(w);
|
|
w = 0;
|
|
}
|
|
DUMPBITS(8)
|
|
}
|
|
|
|
wp = w;
|
|
bb = b;
|
|
bk = k;
|
|
return 0;
|
|
}
|
|
|
|
int inflate_fixed(void)
|
|
{
|
|
int i;
|
|
struct huft *tl;
|
|
struct huft *td;
|
|
int bl;
|
|
int bd;
|
|
unsigned l[288];
|
|
|
|
for(i = 0; i < 144; i++)
|
|
l[i] = 8;
|
|
for(; i < 256; i++)
|
|
l[i] = 9;
|
|
for(; i < 280; i++)
|
|
l[i] = 7;
|
|
for(; i < 288; i++)
|
|
l[i] = 8;
|
|
bl = 7;
|
|
if((i = huft_build(l,288,257,cplens,cplext,&tl,&bl)) != 0)
|
|
return i;
|
|
|
|
for(i = 0; i < 30; i++)
|
|
l[i] = 5;
|
|
bd = 5;
|
|
if((i = huft_build(l,30,0,cpdist,cpdext,&td,&bd)) > 1){
|
|
huft_free(tl);
|
|
return i;
|
|
}
|
|
|
|
if(inflate_codes(tl,td,bl,bd))
|
|
return 1;
|
|
|
|
huft_free(tl);
|
|
huft_free(td);
|
|
return 0;
|
|
}
|
|
|
|
int inflate_dynamic(void)
|
|
{
|
|
int i;
|
|
unsigned j;
|
|
unsigned l;
|
|
unsigned m;
|
|
unsigned n;
|
|
struct huft *tl;
|
|
struct huft *td;
|
|
int bl;
|
|
int bd;
|
|
unsigned nb;
|
|
unsigned nl;
|
|
unsigned nd;
|
|
unsigned ll[286+30];
|
|
unsigned int b;
|
|
unsigned k;
|
|
|
|
b = bb;
|
|
k = bk;
|
|
|
|
NEEDBITS(5)
|
|
nl = 257 + ((unsigned)b & 0x1f);
|
|
DUMPBITS(5)
|
|
NEEDBITS(5)
|
|
nd = 1 + ((unsigned)b & 0x1f);
|
|
DUMPBITS(5)
|
|
NEEDBITS(4)
|
|
nb = 4 + ((unsigned)b & 0xf);
|
|
DUMPBITS(4)
|
|
if(nl > 286 || nd > 30)
|
|
return 1;
|
|
for(j = 0; j < nb; j++){
|
|
NEEDBITS(3)
|
|
ll[border[j]] = (unsigned)b & 7;
|
|
DUMPBITS(3)
|
|
}
|
|
for(; j < 19; j++)
|
|
ll[border[j]] = 0;
|
|
bl = 7;
|
|
if((i = huft_build(ll,19,19,NULL,NULL,&tl,&bl)) != 0){
|
|
if(i == 1)
|
|
huft_free(tl);
|
|
return i;
|
|
}
|
|
n = nl + nd;
|
|
m = mask_bits[bl];
|
|
i = l = 0;
|
|
while((unsigned)i < n){
|
|
NEEDBITS((unsigned)bl)
|
|
j = (td = tl + ((unsigned)b & m))->b;
|
|
DUMPBITS(j)
|
|
j = td->v.n;
|
|
if(j < 16)
|
|
ll[i++] = l = j;
|
|
else
|
|
if(j == 16){
|
|
NEEDBITS(2)
|
|
j = 3 + ((unsigned)b & 3);
|
|
DUMPBITS(2)
|
|
if((unsigned)i + j > n)
|
|
return 1;
|
|
while(j--)
|
|
ll[i++] = l;
|
|
}
|
|
else
|
|
if(j == 17){
|
|
NEEDBITS(3)
|
|
j = 3 + ((unsigned)b & 7);
|
|
DUMPBITS(3)
|
|
if((unsigned)i + j > n)
|
|
return 1;
|
|
while(j--)
|
|
ll[i++] = 0;
|
|
l = 0;
|
|
}
|
|
else {
|
|
NEEDBITS(7)
|
|
j = 11 + ((unsigned)b & 0x7f);
|
|
DUMPBITS(7)
|
|
if((unsigned)i + j > n)
|
|
return 1;
|
|
while(j--)
|
|
ll[i++] = 0;
|
|
l = 0;
|
|
}
|
|
}
|
|
huft_free(tl);
|
|
|
|
bb = b;
|
|
bk = k;
|
|
bl = lbits;
|
|
if((i = huft_build(ll,nl,257,cplens,cplext,&tl,&bl)) != 0){
|
|
if(i == 1)
|
|
huft_free(tl);
|
|
return i;
|
|
}
|
|
bd = dbits;
|
|
if((i = huft_build(ll + nl,nd,0,cpdist,cpdext,&td,&bd)) != 0){
|
|
if(i == 1)
|
|
huft_free(td);
|
|
huft_free(tl);
|
|
return i;
|
|
}
|
|
if(inflate_codes(tl,td,bl,bd))
|
|
return 1;
|
|
huft_free(tl);
|
|
huft_free(td);
|
|
return 0;
|
|
}
|
|
|
|
int inflate_block(int* e)
|
|
{
|
|
unsigned t;
|
|
unsigned int b;
|
|
unsigned k;
|
|
|
|
b = bb;
|
|
k = bk;
|
|
|
|
NEEDBITS(1)
|
|
*e = (int)b & 1;
|
|
DUMPBITS(1)
|
|
|
|
NEEDBITS(2)
|
|
t = (unsigned)b & 3;
|
|
DUMPBITS(2)
|
|
|
|
bb = b;
|
|
bk = k;
|
|
|
|
if(t == 2)
|
|
return inflate_dynamic();
|
|
if(t == 0)
|
|
return inflate_stored();
|
|
if(t == 1)
|
|
return inflate_fixed();
|
|
return 2;
|
|
}
|
|
|
|
int inflate_entry(void)
|
|
{
|
|
int e;
|
|
int r;
|
|
unsigned h;
|
|
|
|
wp = 0;
|
|
bk = 0;
|
|
bb = 0;
|
|
|
|
h = 0;
|
|
do {
|
|
hufts = 0;
|
|
if((r = inflate_block(&e)) != 0)
|
|
return r;
|
|
if(hufts > h)
|
|
h = hufts;
|
|
} while(!e);
|
|
|
|
flush(wp);
|
|
return 0;
|
|
}
|
|
|
|
void inflate(void)
|
|
{
|
|
inflate_entry();
|
|
}
|
|
|
|
int ReadByte(unsigned short* x)
|
|
{
|
|
return ReadMemoryByte(x);
|
|
}
|
|
|