3f3343d30e363cc559baca46f4a7115ae3844cd0
[swftools.git] / installer / depack.c
1 /* depack.c\r
2 \r
3    Part of the swftools installer.\r
4    \r
5    Copyright (c) 1997-2004 Matthias Kramm <kramm@quiss.org> \r
6  \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
11 \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
16 \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
20 \r
21 #include "stdlib.h"\r
22 #include "stdio.h"\r
23 #include "depack.h"\r
24 \r
25 U32 dbittab[] = {\r
26     0x1,       0x2,       0x4,       0x8,\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
34 };\r
35 \r
36 static void* malloc_z(int len)\r
37 {\r
38     void* buf = malloc(len);\r
39     if(buf == 0) {\r
40         fprintf(stderr, "\nout of memory\n");\r
41         exit(1);\r
42     }\r
43     memset(buf, 0, len);\r
44     return buf;\r
45 }\r
46 \r
47 typedef struct _dpackead {\r
48     int back;\r
49     int len;\r
50 } dpackead_t;\r
51 \r
52 typedef struct _tree {   \r
53     int depth;\r
54     U8  bits[17];\r
55     U32 base[17];\r
56 } tree_t;\r
57 \r
58 typedef struct _depack_internal\r
59 {\r
60     int DMEMSIZE;\r
61     int DMEMSIZEA;\r
62 \r
63     tree_t T_REP;\r
64     tree_t T_STORE;\r
65     tree_t T_CNUM;\r
66     tree_t T_BACK;\r
67     tree_t T_BACK2;\r
68     tree_t T_BACK3;\r
69 \r
70     dpackead_t dpackead;\r
71 \r
72     void*reader;\r
73     readfunc_t readfunc;\r
74     void*writer;\r
75     writefunc_t writefunc;\r
76 \r
77     U8* mem;\r
78     int mempos;\r
79     int pos;\r
80     U8 c;\r
81     U32 b;\r
82 } depack_internal_t;\r
83 \r
84 void depack_destroy(depack_t*d)\r
85 {\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
89 }\r
90 \r
91 static readbytes(depack_t*d, int num)\r
92 {\r
93     depack_internal_t*i = (depack_internal_t*)d->internal;\r
94 \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
98     } else {\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
103     }\r
104     i->mempos=(i->mempos+num)&i->DMEMSIZEA;\r
105     i->pos+=num;\r
106 }\r
107 \r
108 int move(U8*dest, U8*src, int len)\r
109 {\r
110     if(len) do {\r
111         *dest=*src;\r
112         src++;\r
113         dest++;\r
114     } while(--len);\r
115 }\r
116 \r
117 static lookback(depack_t*d, int back,int len)\r
118 {\r
119     depack_internal_t*i = (depack_internal_t*)d->internal;\r
120 \r
121     int x,z=(i->mempos-back)&i->DMEMSIZEA;\r
122     char fail=0;\r
123 \r
124     if(i->mempos+len <= i->DMEMSIZE && \r
125        z+len <= i->DMEMSIZE) \r
126     {\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
130     } else {\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
136         }\r
137     }\r
138     i->pos += len;\r
139 }\r
140 \r
141 static inline U8 readbit(depack_internal_t*i)\r
142 {\r
143     i->c&=31;\r
144     if(i->c==0) i->readfunc(i->reader, &i->b,4);\r
145     return (i->b>>(31-i->c++))&1;\r
146 }\r
147 \r
148 static inline U32 readval(depack_internal_t*i,int b)\r
149 {\r
150     unsigned v=0;\r
151     signed char l;\r
152     for(l=b-1;l>=0;l--)\r
153         v|=readbit(i)<<l;\r
154     return v;\r
155 }\r
156 \r
157 static tree_t gettree(depack_t*d)\r
158 {\r
159     depack_internal_t*i = (depack_internal_t*)d->internal;\r
160 \r
161     int l;\r
162     int x,y,z=0,b=0,r;\r
163     tree_t tree;\r
164     memset(&tree, 0, sizeof(tree));\r
165    \r
166     tree.depth = readval(i,4)+1;\r
167 \r
168     for(x=0;x<tree.depth;x++)\r
169     {\r
170         tree.base[x]=z;\r
171         r=0;while(!readbit(i)) r++;\r
172         if(readbit(i)) r=-r;\r
173         b+=r;\r
174         tree.bits[x]=b;\r
175         z+=dbittab[b];\r
176     }\r
177     tree.base[tree.depth]=z;\r
178     tree.bits[tree.depth]=0;\r
179     return tree;\r
180 \r
181 /*    for(z=0;z<=l;z++)\r
182     {\r
183         if(i->ttree[n].bits[z]>16) \r
184             printf(".");\r
185         else                       \r
186             printf("%c","0123456789abcdefg"[ttree[n].bits[z]]);\r
187     }\r
188     printf("\n");*/\r
189 }\r
190 \r
191 static void showtree(tree_t tree)\r
192 {\r
193     int t;\r
194     int last=0;\r
195     int lastbits = 0;\r
196     for(t=0;t<=tree.depth;t++)\r
197     {\r
198         if(t>0)\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
200         last=tree.base[t];\r
201         lastbits = tree.bits[t];\r
202     }\r
203 }\r
204 \r
205 static int gettreeval(depack_t*d, tree_t*tree)\r
206 {\r
207     depack_internal_t*i = (depack_internal_t*)d->internal;\r
208 \r
209     U8 x=0;\r
210     while(!readbit(i)) x++;\r
211     if(x<17) return tree->base[x]+readval(i, tree->bits[x]);\r
212     else     return -1;\r
213 }\r
214 \r
215 static int get_memsize(int b)\r
216 {\r
217     int t,c=1;\r
218     for(t=0;;t++) {\r
219         if(c>=b) return c;\r
220         c<<=1;\r
221     }\r
222     return 0;\r
223 }\r
224 \r
225 void depack_init(depack_t*d, void*reader, readfunc_t readfunc)\r
226 {\r
227     d->internal = malloc_z(sizeof(depack_internal_t));\r
228     depack_internal_t*i = (depack_internal_t*)d->internal;\r
229     if(i==0) {\r
230         fprintf(stderr, "depacker not initialized yet"); exit(1);\r
231     }\r
232 \r
233     i->reader = reader;\r
234     i->readfunc = readfunc;\r
235 \r
236     i->mempos=0;\r
237     i->pos=0;\r
238     i->b=i->c=0;\r
239 \r
240     i->readfunc(i->reader,&i->dpackead.back, 4);\r
241     i->readfunc(i->reader,&i->dpackead.len, 4);\r
242 \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
246 \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
257 \r
258     d->size = i->dpackead.len;\r
259 }\r
260 \r
261 void depack_process(depack_t*d, void*writer,writefunc_t writefunc)\r
262 {\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
267     {\r
268         int store,rep,x;\r
269 \r
270         store=gettreeval(d,&i->T_STORE)+1;\r
271 \r
272         readbytes(d,store);\r
273 \r
274         if(i->pos<i->dpackead.len)\r
275         {\r
276             rep = gettreeval(d,&i->T_REP)+1;\r
277 \r
278             for(x=0;x<rep;x++)\r
279             {\r
280                 int back,len;\r
281                 len = gettreeval(d,&i->T_CNUM)+1;\r
282 \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
287 \r
288                 lookback(d,back,len);\r
289             }\r
290         }\r
291     }\r
292 \r
293     if(i->pos!=i->dpackead.len) {\r
294         fprintf(stderr, "Internal error");\r
295         exit(1);\r
296     }\r
297 }\r
298 \r
299 /*\r
300 \r
301                 mov eax,[b1]\r
302                 mov ebx,[b2]\r
303                 shld eax,ebx,cl\r
304                 mov [b1],eax\r
305                 shr ebx,cl\r
306                 mov [b2],ebx\r
307                 sub cnt,cl\r
308                 cmp cnt,32-8\r
309                 ja jj\r
310 mm:             xor eax,eax\r
311                 call read\r
312                 shl eax,[cnt]\r
313                 or  [b2],eax\r
314                 add cnt,8\r
315                 cmp cnt,32-8\r
316                 jb mm\r
317 jj:\r
318 \r
319 */\r
320 \r
321