3 Part of the swftools installer.
\r
5 Copyright (c) 1997-2004 Matthias Kramm <kramm@quiss.org>
\r
7 This program is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 This program is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with this program; if not, write to the Free Software
\r
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
\r
27 0x10, 0x20, 0x40, 0x80,
\r
28 0x100, 0x200, 0x400, 0x800,
\r
29 0x1000, 0x2000, 0x4000, 0x8000,
\r
30 0x10000, 0x20000, 0x40000, 0x80000,
\r
31 0x100000, 0x200000, 0x400000, 0x800000,
\r
32 0x1000000, 0x2000000, 0x4000000, 0x8000000,
\r
33 0x10000000,0x20000000,0x40000000,0x80000000
\r
36 static void* malloc_z(int len)
\r
38 void* buf = malloc(len);
\r
40 fprintf(stderr, "\nout of memory\n");
\r
43 memset(buf, 0, len);
\r
47 typedef struct _dpackead {
\r
52 typedef struct _tree {
\r
58 typedef struct _depack_internal
\r
70 dpackead_t dpackead;
\r
73 readfunc_t readfunc;
\r
75 writefunc_t writefunc;
\r
82 } depack_internal_t;
\r
84 void depack_destroy(depack_t*d)
\r
86 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
87 free(i->mem);i->mem=0;
\r
88 free(d->internal);d->internal=0;i=0;
\r
91 static readbytes(depack_t*d, int num)
\r
93 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
95 if(i->mempos+num<=i->DMEMSIZE) {
\r
96 i->readfunc(i->reader, &i->mem[i->mempos],num);
\r
97 i->writefunc(i->writer, &i->mem[i->mempos],num);
\r
99 i->readfunc(i->reader, &i->mem[i->mempos],i->DMEMSIZE - i->mempos);
\r
100 i->writefunc(i->writer, &i->mem[i->mempos],i->DMEMSIZE - i->mempos);
\r
101 i->readfunc(i->reader, &i->mem[0],num-(i->DMEMSIZE - i->mempos));
\r
102 i->writefunc(i->writer, &i->mem[0],num-(i->DMEMSIZE - i->mempos));
\r
104 i->mempos=(i->mempos+num)&i->DMEMSIZEA;
\r
108 int move(U8*dest, U8*src, int len)
\r
117 static lookback(depack_t*d, int back,int len)
\r
119 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
121 int x,z=(i->mempos-back)&i->DMEMSIZEA;
\r
124 if(i->mempos+len <= i->DMEMSIZE &&
\r
125 z+len <= i->DMEMSIZE)
\r
127 move(&i->mem[i->mempos],&i->mem[z],len);
\r
128 i->writefunc(i->writer, &i->mem[i->mempos],len);
\r
129 i->mempos=(i->mempos+len)&i->DMEMSIZEA;
\r
131 for(x=0;x<len;x++) {
\r
132 i->mem[i->mempos]=i->mem[z];
\r
133 i->writefunc(i->writer, &i->mem[i->mempos],1);
\r
134 i->mempos=(i->mempos+1)&i->DMEMSIZEA;
\r
135 z=(z+1)&i->DMEMSIZEA;
\r
141 static inline U8 readbit(depack_internal_t*i)
\r
144 if(i->c==0) i->readfunc(i->reader, &i->b,4);
\r
145 return (i->b>>(31-i->c++))&1;
\r
148 static inline U32 readval(depack_internal_t*i,int b)
\r
152 for(l=b-1;l>=0;l--)
\r
157 static tree_t gettree(depack_t*d)
\r
159 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
164 memset(&tree, 0, sizeof(tree));
\r
166 tree.depth = readval(i,4)+1;
\r
168 for(x=0;x<tree.depth;x++)
\r
171 r=0;while(!readbit(i)) r++;
\r
172 if(readbit(i)) r=-r;
\r
177 tree.base[tree.depth]=z;
\r
178 tree.bits[tree.depth]=0;
\r
181 /* for(z=0;z<=l;z++)
\r
183 if(i->ttree[n].bits[z]>16)
\r
186 printf("%c","0123456789abcdefg"[ttree[n].bits[z]]);
\r
191 static void showtree(tree_t tree)
\r
196 for(t=0;t<=tree.depth;t++)
\r
199 printf("[%d] %d: %05x-%05x (%d=%d+%d+1)\n",t,lastbits, last,tree.base[t],lastbits+(t-1)+1, lastbits,t-1);
\r
201 lastbits = tree.bits[t];
\r
205 static int gettreeval(depack_t*d, tree_t*tree)
\r
207 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
210 while(!readbit(i)) x++;
\r
211 if(x<17) return tree->base[x]+readval(i, tree->bits[x]);
\r
215 static int get_memsize(int b)
\r
225 void depack_init(depack_t*d, void*reader, readfunc_t readfunc)
\r
227 d->internal = malloc_z(sizeof(depack_internal_t));
\r
228 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
230 fprintf(stderr, "depacker not initialized yet"); exit(1);
\r
233 i->reader = reader;
\r
234 i->readfunc = readfunc;
\r
240 i->readfunc(i->reader,&i->dpackead.back, 4);
\r
241 i->readfunc(i->reader,&i->dpackead.len, 4);
\r
243 i->DMEMSIZE = get_memsize(i->dpackead.len);
\r
244 i->DMEMSIZEA = i->DMEMSIZE-1;
\r
245 i->mem = malloc_z(i->DMEMSIZE);
\r
247 i->T_REP = gettree(d);
\r
248 i->T_STORE = gettree(d);
\r
249 i->T_CNUM = gettree(d);
\r
250 //showtree(i->T_CNUM);
\r
251 i->T_BACK = gettree(d);
\r
252 //showtree(i->T_BACK);
\r
253 i->T_BACK2 = gettree(d);
\r
254 //showtree(i->T_BACK);
\r
255 i->T_BACK3 = gettree(d);
\r
256 //showtree(i->T_BACK3);
\r
258 d->size = i->dpackead.len;
\r
261 void depack_process(depack_t*d, void*writer,writefunc_t writefunc)
\r
263 depack_internal_t*i = (depack_internal_t*)d->internal;
\r
264 i->writer = writer;
\r
265 i->writefunc = writefunc;
\r
266 while(i->pos<i->dpackead.len)
\r
270 store=gettreeval(d,&i->T_STORE)+1;
\r
272 readbytes(d,store);
\r
274 if(i->pos<i->dpackead.len)
\r
276 rep = gettreeval(d,&i->T_REP)+1;
\r
281 len = gettreeval(d,&i->T_CNUM)+1;
\r
283 if(len == 1) back = readval(i,3)+1;
\r
284 if(len == 2) back = gettreeval(d,&i->T_BACK2)+1;
\r
285 if(len == 3) back = gettreeval(d,&i->T_BACK3)+1;
\r
286 if(len >= 4) back = gettreeval(d,&i->T_BACK)+1;
\r
288 lookback(d,back,len);
\r
293 if(i->pos!=i->dpackead.len) {
\r
294 fprintf(stderr, "Internal error");
\r