Rev 6639 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6617 | IgorA | 1 | ; trees.asm -- output deflated data using Huffman coding |
2 | ; Copyright (C) 1995-2012 Jean-loup Gailly |
||
3 | ; detect_data_type() function provided freely by Cosmin Truta, 2006 |
||
4 | ; For conditions of distribution and use, see copyright notice in zlib.h |
||
5 | |||
6 | ; ALGORITHM |
||
7 | |||
8 | ; The "deflation" process uses several Huffman trees. The more |
||
9 | ; common source values are represented by shorter bit sequences. |
||
10 | |||
11 | ; Each code tree is stored in a compressed form which is itself |
||
12 | ; a Huffman encoding of the lengths of all the code strings (in |
||
13 | ; ascending order by source values). The actual code strings are |
||
14 | ; reconstructed from the lengths in the inflate process, as described |
||
15 | ; in the deflate specification. |
||
16 | |||
17 | ; REFERENCES |
||
18 | |||
19 | ; Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". |
||
20 | ; Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc |
||
21 | |||
22 | ; Storer, James A. |
||
23 | ; Data Compression: Methods and Theory, pp. 49-50. |
||
24 | ; Computer Science Press, 1988. ISBN 0-7167-8156-5. |
||
25 | |||
26 | ; Sedgewick, R. |
||
27 | ; Algorithms, p290. |
||
28 | ; Addison-Wesley, 1983. ISBN 0-201-06672-6. |
||
29 | |||
30 | ; =========================================================================== |
||
31 | ; Constants |
||
32 | |||
33 | |||
34 | MAX_BL_BITS equ 7 |
||
35 | ; Bit length codes must not exceed MAX_BL_BITS bits |
||
36 | |||
37 | END_BLOCK equ 256 |
||
38 | ; end of block literal code |
||
39 | |||
40 | REP_3_6 equ 16 |
||
41 | ; repeat previous bit length 3-6 times (2 bits of repeat count) |
||
42 | |||
43 | REPZ_3_10 equ 17 |
||
44 | ; repeat a zero length 3-10 times (3 bits of repeat count) |
||
45 | |||
46 | REPZ_11_138 equ 18 |
||
47 | ; repeat a zero length 11-138 times (7 bits of repeat count) |
||
48 | |||
49 | align 4 |
||
50 | extra_lbits dd \ ;int [LENGTH_CODES] ;extra bits for each length code |
||
51 | 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 |
||
52 | |||
53 | align 4 |
||
54 | extra_dbits dd \ ;int [D_CODES] ;extra bits for each distance code |
||
55 | 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 |
||
56 | |||
57 | align 4 |
||
58 | extra_blbits dd \ ;int [BL_CODES] ;extra bits for each bit length code |
||
59 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 |
||
60 | |||
61 | align 4 |
||
62 | bl_order db 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 |
||
63 | ; The lengths of the bit length codes are sent in order of decreasing |
||
64 | ; probability, to avoid transmitting the lengths for unused bit length codes. |
||
65 | |||
66 | |||
67 | ; =========================================================================== |
||
68 | ; Local data. These are initialized only once. |
||
69 | |||
70 | |||
71 | DIST_CODE_LEN equ 512 ;see definition of array dist_code below |
||
72 | |||
73 | if GEN_TREES_H eq 1 ;| !(STDC) |
||
74 | ; non ANSI compilers may not accept trees.inc |
||
75 | |||
76 | align 4 |
||
77 | static_ltree rb sizeof.ct_data * (L_CODES+2) |
||
78 | ; The static literal tree. Since the bit lengths are imposed, there is no |
||
79 | ; need for the L_CODES extra codes used during heap construction. However |
||
80 | ; The codes 286 and 287 are needed to build a canonical tree (see _tr_init |
||
81 | ; below). |
||
82 | |||
83 | align 4 |
||
84 | static_dtree rb sizeof.ct_data * D_CODES |
||
85 | ; The static distance tree. (Actually a trivial tree since all codes use |
||
86 | ; 5 bits.) |
||
87 | |||
88 | align 4 |
||
89 | _dist_code rb DIST_CODE_LEN ;uch[] |
||
90 | ; Distance codes. The first 256 values correspond to the distances |
||
91 | ; 3 .. 258, the last 256 values correspond to the top 8 bits of |
||
92 | ; the 15 bit distances. |
||
93 | |||
94 | align 4 |
||
95 | _length_code rb MAX_MATCH-MIN_MATCH+1 ;uch[] |
||
96 | ; length code for each normalized match length (0 == MIN_MATCH) |
||
97 | |||
98 | align 4 |
||
99 | base_length rd LENGTH_CODES ;int[] |
||
100 | ; First normalized length for each code (0 = MIN_MATCH) |
||
101 | |||
102 | align 4 |
||
103 | base_dist rd D_CODES ;int[] |
||
104 | ; First normalized distance for each code (0 = distance of 1) |
||
105 | |||
106 | else |
||
107 | include 'trees.inc' |
||
108 | end if ;GEN_TREES_H |
||
109 | |||
110 | struct static_tree_desc ;_s |
||
111 | static_tree dd ? ;const ct_data * ;static tree or NULL |
||
112 | extra_bits dd ? ;const intf * ;extra bits for each code or NULL |
||
113 | extra_base dd ? ;int ;base index for extra_bits |
||
114 | elems dd ? ;int ;max number of elements in the tree |
||
115 | max_length dd ? ;int ;max bit length for the codes |
||
116 | ends |
||
117 | |||
118 | align 4 |
||
119 | static_l_desc static_tree_desc static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS |
||
120 | |||
121 | align 4 |
||
122 | static_d_desc static_tree_desc static_dtree, extra_dbits, 0, D_CODES, MAX_BITS |
||
123 | |||
124 | align 4 |
||
125 | static_bl_desc static_tree_desc 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS |
||
126 | |||
127 | ; =========================================================================== |
||
128 | ; Local (static) routines in this file. |
||
129 | |||
130 | |||
131 | macro send_code s, c, tree |
||
132 | { |
||
133 | if DEBUG eq 1 |
||
134 | ; if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)) |
||
135 | end if |
||
136 | push eax ebx |
||
137 | if c eq eax |
||
138 | else |
||
139 | mov eax,c |
||
140 | end if |
||
141 | imul eax,sizeof.ct_data |
||
142 | add eax,tree |
||
143 | movzx ebx,word[eax+Len] |
||
144 | push ebx |
||
145 | movzx ebx,word[eax+Code] |
||
146 | push ebx |
||
147 | stdcall send_bits, s ;tree[c].Code, tree[c].Len |
||
148 | pop ebx eax |
||
149 | } |
||
150 | ; Send a code of the given tree[c] and tree must not have side effects |
||
151 | |||
152 | ; =========================================================================== |
||
153 | ; Output a short LSB first on the stream. |
||
154 | ; IN assertion: there is enough room in pendingBuf. |
||
155 | |||
156 | macro put_short s, w |
||
157 | { |
||
158 | movzx eax,word[s+deflate_state.pending] |
||
159 | add eax,[s+deflate_state.pending_buf] |
||
160 | mov word[eax],w |
||
161 | add word[s+deflate_state.pending],2 |
||
162 | } |
||
163 | |||
164 | ; =========================================================================== |
||
165 | ; Send a value on a given number of bits. |
||
166 | ; IN assertion: length <= 16 and value fits in length bits. |
||
167 | |||
168 | ;void (s, value, length) |
||
169 | ; deflate_state* s |
||
170 | ; int value ;value to send |
||
171 | ; int length ;number of bits |
||
172 | align 4 |
||
173 | proc send_bits uses eax ecx edi, s:dword, value:dword, length:dword |
||
174 | ; Tracevv((stderr," l %2d v %4x ", length, value)); |
||
175 | ;zlib_debug 'send_bits value = %d',[value] |
||
176 | ;if DEBUG eq 1 |
||
177 | mov eax,[length] |
||
178 | cmp eax,0 |
||
179 | jle @f |
||
180 | cmp eax,15 |
||
181 | jle .end1 |
||
182 | @@: |
||
183 | zlib_debug 'invalid length' ;Assert(..>0 && ..<=15) |
||
184 | .end1: |
||
185 | mov edi,[s] |
||
186 | add [edi+deflate_state.bits_sent],eax |
||
187 | |||
188 | ; If not enough room in bi_buf, use (valid) bits from bi_buf and |
||
189 | ; (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) |
||
190 | ; unused bits in value. |
||
191 | |||
192 | mov ecx,Buf_size |
||
193 | sub ecx,eax |
||
194 | cmp [edi+deflate_state.bi_valid],ecx |
||
195 | jle @f ;if (..>..) |
||
196 | mov eax,[value] |
||
197 | mov ecx,[edi+deflate_state.bi_valid] |
||
198 | shl eax,cl |
||
199 | or [edi+deflate_state.bi_buf],ax |
||
200 | mov cx,[edi+deflate_state.bi_buf] |
||
201 | put_short edi, cx |
||
202 | mov eax,[value] |
||
203 | mov ecx,Buf_size |
||
204 | sub ecx,[edi+deflate_state.bi_valid] |
||
205 | shr eax,cl |
||
206 | mov [edi+deflate_state.bi_buf],ax |
||
207 | mov eax,[length] |
||
208 | sub eax,Buf_size |
||
209 | jmp .end0 |
||
210 | @@: ;else |
||
211 | mov eax,[value] |
||
212 | mov ecx,[edi+deflate_state.bi_valid] |
||
213 | shl eax,cl |
||
214 | or [edi+deflate_state.bi_buf],ax |
||
215 | mov eax,[length] |
||
216 | .end0: |
||
217 | add [edi+deflate_state.bi_valid],eax |
||
218 | ;else ;!DEBUG |
||
219 | |||
220 | ;{ int len = length; |
||
221 | ; if (s->bi_valid > (int)Buf_size - len) { |
||
222 | ; int val = value; |
||
223 | ; s->bi_buf |= (uint_16)val << s->bi_valid; |
||
224 | ; put_short(s, s->bi_buf); |
||
225 | ; s->bi_buf = (uint_16)val >> (Buf_size - s->bi_valid); |
||
226 | ; s->bi_valid += len - Buf_size; |
||
227 | ; } else { |
||
228 | ; s->bi_buf |= (uint_16)(value) << s->bi_valid; |
||
229 | ; s->bi_valid += len; |
||
230 | ; } |
||
231 | ;} |
||
232 | ;end if ;DEBUG |
||
233 | ret |
||
234 | endp |
||
235 | |||
236 | ; the arguments must not have side effects |
||
237 | |||
238 | ; =========================================================================== |
||
239 | ; Initialize the various 'constant' tables. |
||
240 | |||
241 | ;int static_init_done = 0 |
||
242 | |||
243 | ;void () |
||
244 | align 4 |
||
245 | proc tr_static_init |
||
246 | if GEN_TREES_H eq 1 |
||
247 | |||
248 | ; int n ;iterates over tree elements |
||
249 | ; int bits ;bit counter |
||
250 | ; int length ;length value |
||
251 | ; int code ;code value |
||
252 | ; int dist ;distance index |
||
253 | ; uint_16 bl_count[MAX_BITS+1]; |
||
254 | ; number of codes at each bit length for an optimal tree |
||
255 | |||
256 | ; if (static_init_done) return; |
||
257 | |||
258 | ; For some embedded targets, global variables are not initialized: |
||
259 | ;if NO_INIT_GLOBAL_POINTERS |
||
260 | ; static_l_desc.static_tree = static_ltree; |
||
261 | ; static_l_desc.extra_bits = extra_lbits; |
||
262 | ; static_d_desc.static_tree = static_dtree; |
||
263 | ; static_d_desc.extra_bits = extra_dbits; |
||
264 | ; static_bl_desc.extra_bits = extra_blbits; |
||
265 | ;end if |
||
266 | |||
267 | ; Initialize the mapping length (0..255) -> length code (0..28) |
||
268 | ; length = 0; |
||
269 | ; for (code = 0; code < LENGTH_CODES-1; code++) { |
||
270 | ; base_length[code] = length; |
||
271 | ; for (n = 0; n < (1< |
||
272 | ; _length_code[length++] = (uch)code; |
||
273 | ; } |
||
274 | ; } |
||
275 | ; Assert (length == 256, "tr_static_init: length != 256"); |
||
276 | ; Note that the length 255 (match length 258) can be represented |
||
277 | ; in two different ways: code 284 + 5 bits or code 285, so we |
||
278 | ; overwrite length_code[255] to use the best encoding: |
||
279 | |||
280 | ; _length_code[length-1] = (uch)code; |
||
281 | |||
282 | ; Initialize the mapping dist (0..32K) -> dist code (0..29) |
||
283 | ; dist = 0; |
||
284 | ; for (code = 0 ; code < 16; code++) { |
||
285 | ; base_dist[code] = dist; |
||
286 | ; for (n = 0; n < (1< |
||
287 | ; _dist_code[dist++] = (uch)code; |
||
288 | ; } |
||
289 | ; } |
||
290 | ; Assert (dist == 256, "tr_static_init: dist != 256"); |
||
291 | ; dist >>= 7; /* from now on, all distances are divided by 128 */ |
||
292 | ; for ( ; code < D_CODES; code++) { |
||
293 | ; base_dist[code] = dist << 7; |
||
294 | ; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { |
||
295 | ; _dist_code[256 + dist++] = (uch)code; |
||
296 | ; } |
||
297 | ; } |
||
298 | ; Assert (dist == 256, "tr_static_init: 256+dist != 512"); |
||
299 | |||
300 | ; Construct the codes of the static literal tree |
||
301 | ; for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; |
||
302 | ; n = 0; |
||
303 | ; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; |
||
304 | ; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; |
||
305 | ; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; |
||
306 | ; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; |
||
307 | ; Codes 286 and 287 do not exist, but we must include them in the |
||
308 | ; tree construction to get a canonical Huffman tree (longest code |
||
309 | ; all ones) |
||
310 | |||
311 | ; gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); |
||
312 | |||
313 | ; The static distance tree is trivial: |
||
314 | ; for (n = 0; n < D_CODES; n++) { |
||
315 | ; static_dtree[n].Len = 5; |
||
316 | ; static_dtree[n].Code = bi_reverse((unsigned)n, 5); |
||
317 | ; } |
||
318 | ; static_init_done = 1; |
||
319 | |||
320 | if GEN_TREES_H eq 1 |
||
321 | call gen_trees_header |
||
322 | end if |
||
323 | end if ;(GEN_TREES_H) | !(STDC) |
||
324 | ret |
||
325 | endp |
||
326 | |||
327 | ; =========================================================================== |
||
328 | ; Genererate the file trees.h describing the static trees. |
||
329 | |||
330 | ;# define SEPARATOR(i, last, width) \ |
||
331 | ; ((i) == (last)? "\n};\n\n" : \ |
||
332 | ; ((i) % (width) == (width)-1 ? ",\n" : ", ")) |
||
333 | |||
334 | ;void () |
||
335 | align 4 |
||
336 | proc gen_trees_header |
||
337 | ; FILE *header = fopen("trees.inc", "w"); |
||
338 | ; int i; |
||
339 | |||
340 | ; Assert (header != NULL, "Can't open trees.inc"); |
||
341 | ; fprintf(header, |
||
342 | ; "/* header created automatically with -DGEN_TREES_H */\n\n"); |
||
343 | |||
344 | ; fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); |
||
345 | ; for (i = 0; i < L_CODES+2; i++) { |
||
346 | ; fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, |
||
347 | ; static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); |
||
348 | ; } |
||
349 | |||
350 | ; fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); |
||
351 | ; for (i = 0; i < D_CODES; i++) { |
||
352 | ; fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, |
||
353 | ; static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); |
||
354 | ; } |
||
355 | |||
356 | ; fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); |
||
357 | ; for (i = 0; i < DIST_CODE_LEN; i++) { |
||
358 | ; fprintf(header, "%2u%s", _dist_code[i], |
||
359 | ; SEPARATOR(i, DIST_CODE_LEN-1, 20)); |
||
360 | ; } |
||
361 | |||
362 | ; fprintf(header, |
||
363 | ; "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); |
||
364 | ; for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { |
||
365 | ; fprintf(header, "%2u%s", _length_code[i], |
||
366 | ; SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); |
||
367 | ; } |
||
368 | |||
369 | ; fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); |
||
370 | ; for (i = 0; i < LENGTH_CODES; i++) { |
||
371 | ; fprintf(header, "%1u%s", base_length[i], |
||
372 | ; SEPARATOR(i, LENGTH_CODES-1, 20)); |
||
373 | ; } |
||
374 | |||
375 | ; fprintf(header, "local const int base_dist[D_CODES] = {\n"); |
||
376 | ; for (i = 0; i < D_CODES; i++) { |
||
377 | ; fprintf(header, "%5u%s", base_dist[i], |
||
378 | ; SEPARATOR(i, D_CODES-1, 10)); |
||
379 | ; } |
||
380 | |||
381 | ; fclose(header); |
||
382 | ret |
||
383 | endp |
||
384 | |||
385 | ; =========================================================================== |
||
386 | ; Initialize the tree data structures for a new zlib stream. |
||
387 | |||
388 | ;void (s) |
||
389 | ; deflate_state* s; |
||
390 | align 4 |
||
391 | proc _tr_init uses eax edi, s:dword |
||
392 | mov edi,[s] |
||
393 | ;zlib_debug '_tr_init' |
||
394 | call tr_static_init |
||
395 | |||
396 | mov eax,edi |
||
397 | add eax,deflate_state.dyn_ltree |
||
398 | mov [edi+deflate_state.l_desc.dyn_tree],eax |
||
399 | mov [edi+deflate_state.l_desc.stat_desc],static_l_desc |
||
400 | |||
401 | add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree |
||
402 | mov [edi+deflate_state.d_desc.dyn_tree],eax |
||
403 | mov [edi+deflate_state.d_desc.stat_desc],static_d_desc |
||
404 | |||
405 | add eax,deflate_state.bl_tree-deflate_state.dyn_dtree |
||
406 | mov [edi+deflate_state.bl_desc.dyn_tree],eax |
||
407 | mov [edi+deflate_state.bl_desc.stat_desc],static_bl_desc; |
||
408 | |||
409 | mov word[edi+deflate_state.bi_buf],0 |
||
410 | mov dword[edi+deflate_state.bi_valid],0 |
||
411 | if DEBUG eq 1 |
||
412 | mov dword[edi+deflate_state.compressed_len],0 |
||
413 | mov dword[edi+deflate_state.bits_sent],0 |
||
414 | end if |
||
415 | |||
416 | ; Initialize the first block of the first file: |
||
417 | stdcall init_block,edi |
||
418 | ret |
||
419 | endp |
||
420 | |||
421 | ; =========================================================================== |
||
422 | ; Initialize a new block. |
||
423 | |||
424 | ;void (s) |
||
425 | ; deflate_state* s |
||
426 | align 4 |
||
427 | proc init_block uses eax ecx edi, s:dword |
||
428 | ; int n ;iterates over tree elements |
||
429 | mov edi,[s] |
||
430 | |||
431 | ; Initialize the trees. |
||
432 | mov eax,edi |
||
433 | add eax,deflate_state.dyn_ltree+Freq |
||
434 | mov ecx,L_CODES |
||
435 | @@: |
||
436 | mov word[eax],0 |
||
437 | add eax,sizeof.ct_data |
||
438 | loop @b |
||
439 | mov eax,edi |
||
440 | add eax,deflate_state.dyn_dtree+Freq |
||
441 | mov ecx,D_CODES |
||
442 | @@: |
||
443 | mov word[eax],0 |
||
444 | add eax,sizeof.ct_data |
||
445 | loop @b |
||
446 | mov eax,edi |
||
447 | add eax,deflate_state.bl_tree+Freq |
||
448 | mov ecx,BL_CODES |
||
449 | @@: |
||
450 | mov word[eax],0 |
||
451 | add eax,sizeof.ct_data |
||
452 | loop @b |
||
453 | |||
454 | mov ecx,sizeof.ct_data*END_BLOCK+deflate_state.dyn_ltree+Freq |
||
455 | mov word[ecx+edi],1 |
||
456 | mov dword[edi+deflate_state.static_len],0 |
||
457 | mov dword[edi+deflate_state.opt_len],0 |
||
458 | mov dword[edi+deflate_state.matches],0 |
||
459 | mov dword[edi+deflate_state.last_lit],0 |
||
460 | ret |
||
461 | endp |
||
462 | |||
463 | SMALLEST equ 1 |
||
464 | ; Index within the heap array of least frequent node in the Huffman tree |
||
465 | |||
466 | |||
467 | ; =========================================================================== |
||
468 | ; Remove the smallest element from the heap and recreate the heap with |
||
469 | ; one less element. Updates heap and heap_len. |
||
470 | |||
471 | macro pqremove s, tree, top |
||
472 | { |
||
473 | mov eax,s |
||
474 | add eax,deflate_state.heap+2*SMALLEST |
||
475 | movzx top,word[eax] |
||
476 | push ebx |
||
477 | mov ebx,[s+deflate_state.heap_len] |
||
478 | mov bx,[s+deflate_state.heap+2*ebx] |
||
479 | mov word[eax],bx |
||
480 | dec dword[s+deflate_state.heap_len] |
||
481 | pop ebx |
||
482 | stdcall pqdownheap, s, tree, SMALLEST |
||
483 | } |
||
484 | |||
485 | ; =========================================================================== |
||
486 | ; Compares to subtrees, using the tree depth as tie breaker when |
||
487 | ; the subtrees have equal frequency. This minimizes the worst case length. |
||
488 | |||
489 | macro smaller tree, n, m, depth, m_end |
||
490 | { |
||
491 | ;if (..<.. || (..==.. && depth[n] <= depth[m])) |
||
492 | local .end0 |
||
493 | movzx eax,n |
||
494 | imul eax,sizeof.ct_data |
||
495 | add eax,tree |
||
496 | mov ax,word[eax+Freq] |
||
497 | movzx ebx,m |
||
498 | imul ebx,sizeof.ct_data |
||
499 | add ebx,tree |
||
500 | mov bx,word[ebx+Freq] |
||
501 | cmp ax,bx |
||
502 | jl .end0 |
||
503 | jne m_end |
||
504 | movzx eax,n |
||
505 | add eax,depth |
||
506 | mov al,byte[eax] |
||
507 | movzx ebx,m |
||
508 | add ebx,depth |
||
509 | mov bl,byte[ebx] |
||
510 | cmp al,bl |
||
511 | jg m_end |
||
512 | .end0: |
||
513 | } |
||
514 | |||
515 | ; =========================================================================== |
||
516 | ; Restore the heap property by moving down the tree starting at node k, |
||
517 | ; exchanging a node with the smallest of its two sons if necessary, stopping |
||
518 | ; when the heap property is re-established (each father smaller than its |
||
519 | ; two sons). |
||
520 | |||
521 | ;void (s, tree, k) |
||
522 | ; deflate_state* s |
||
523 | ; ct_data* tree ;the tree to restore |
||
524 | ; int k ;node to move down |
||
525 | align 4 |
||
526 | proc pqdownheap, s:dword, tree:dword, k:dword |
||
527 | locals |
||
528 | v dw ? |
||
529 | endl |
||
530 | pushad |
||
531 | mov edi,[s] |
||
532 | mov eax,[k] |
||
533 | ;zlib_debug 'pqdownheap k = %d',eax |
||
534 | mov esi,eax |
||
535 | shl esi,1 |
||
536 | mov ax,[edi+deflate_state.heap+2*eax] |
||
537 | mov [v],ax |
||
538 | ;esi = j ;left son of k |
||
539 | .cycle0: ;while (..<=..) |
||
540 | cmp esi,[edi+deflate_state.heap_len] |
||
541 | jg .cycle0end |
||
542 | ; Set j to the smallest of the two sons: |
||
543 | ;;cmp esi,[edi+deflate_state.heap_len] |
||
544 | jge .end1 ;if (..<.. && |
||
545 | mov ecx,edi |
||
546 | add ecx,deflate_state.depth |
||
547 | mov edx,esi |
||
548 | shl edx,1 |
||
549 | add edx,edi |
||
550 | add edx,deflate_state.heap |
||
551 | smaller [tree], word[edx+2], word[edx], ecx, .end1 |
||
552 | inc esi |
||
553 | .end1: |
||
554 | ; Exit if v is smaller than both sons |
||
555 | mov ecx,edi |
||
556 | add ecx,deflate_state.depth |
||
557 | mov dx,[edi+deflate_state.heap+2*esi] |
||
558 | smaller [tree], [v], dx, ecx, .end2 |
||
559 | jmp .cycle0end ;break |
||
560 | .end2: |
||
561 | ; Exchange v with the smallest son |
||
562 | mov dx,[edi+deflate_state.heap+2*esi] |
||
563 | mov eax,[k] |
||
564 | mov [edi+deflate_state.heap+2*eax],dx |
||
565 | mov [k],esi |
||
566 | ; And continue down the tree, setting j to the left son of k |
||
567 | shl esi,1 |
||
568 | jmp .cycle0 |
||
569 | .cycle0end: |
||
570 | mov eax,[k] |
||
571 | mov bx,[v] |
||
572 | mov [edi+deflate_state.heap+2*eax],bx |
||
573 | popad |
||
574 | ret |
||
575 | endp |
||
576 | |||
577 | ; =========================================================================== |
||
578 | ; Compute the optimal bit lengths for a tree and update the total bit length |
||
579 | ; for the current block. |
||
580 | ; IN assertion: the fields freq and dad are set, heap[heap_max] and |
||
581 | ; above are the tree nodes sorted by increasing frequency. |
||
582 | ; OUT assertions: the field len is set to the optimal bit length, the |
||
583 | ; array bl_count contains the frequencies for each bit length. |
||
584 | ; The length opt_len is updated; static_len is also updated if stree is |
||
585 | ; not null. |
||
586 | |||
587 | ;void (s, desc) |
||
588 | ; deflate_state* s |
||
589 | ; tree_desc* desc ;the tree descriptor |
||
590 | align 4 |
||
591 | proc gen_bitlen, s:dword, desc:dword |
||
592 | locals |
||
593 | tree dd ? ;ct_data* ;= desc.dyn_tree |
||
594 | max_code dd ? ;int ;= desc.max_code |
||
595 | stree dd ? ;ct_data* ;= desc.stat_desc.static_tree |
||
596 | extra dd ? ;intf* ;= desc.stat_desc.extra_bits |
||
597 | base dd ? ;int ;= desc.stat_desc.extra_base |
||
598 | max_length dd ? ;int ;= desc.stat_desc.max_length |
||
599 | h dd ? ;int ;heap index |
||
600 | m dd ? ;int ;iterate over the tree elements |
||
601 | bits dd ? ;int ;bit length |
||
602 | xbits dd ? ;int ;extra bits |
||
603 | f dw ? ;uint_16 ;frequency |
||
604 | overflow dd 0 ;int ;number of elements with bit length too large |
||
605 | endl |
||
606 | pushad |
||
607 | ;zlib_debug 'gen_bitlen' |
||
608 | mov edi,[s] |
||
609 | mov edx,[desc] |
||
610 | mov eax,[edx+tree_desc.dyn_tree] |
||
611 | mov [tree],eax |
||
612 | mov eax,[edx+tree_desc.max_code] |
||
613 | mov [max_code],eax |
||
614 | mov ebx,[edx+tree_desc.stat_desc] |
||
615 | mov eax,[ebx+static_tree_desc.static_tree] |
||
616 | mov [stree],eax |
||
617 | mov eax,[ebx+static_tree_desc.extra_bits] |
||
618 | mov [extra],eax |
||
619 | mov eax,[ebx+static_tree_desc.extra_base] |
||
620 | mov [base],eax |
||
621 | mov eax,[ebx+static_tree_desc.max_length] |
||
622 | mov [max_length],eax |
||
623 | |||
624 | xor ecx,ecx |
||
625 | .cycle0: |
||
626 | cmp ecx,MAX_BITS |
||
627 | jg .cycle0end ;for (..;..<=..;..) |
||
628 | mov word[edi+deflate_state.bl_count+2*ecx],0 |
||
629 | inc ecx |
||
630 | jmp .cycle0 |
||
631 | align 4 |
||
632 | .cycle0end: |
||
633 | |||
634 | ; In a first pass, compute the optimal bit lengths (which may |
||
635 | ; overflow in the case of the bit length tree). |
||
636 | |||
637 | mov eax,[edi+deflate_state.heap_max] |
||
638 | movzx eax,word[edi+deflate_state.heap+2*eax] |
||
639 | imul eax,sizeof.ct_data |
||
640 | add eax,[tree] |
||
641 | mov word[eax+Len],0 ;root of the heap |
||
642 | |||
643 | mov eax,[edi+deflate_state.heap_max] |
||
644 | inc eax |
||
645 | mov [h],eax |
||
646 | .cycle1: |
||
647 | cmp dword[h],HEAP_SIZE |
||
648 | jge .cycle1end ;for (..;..<..;..) |
||
649 | mov eax,[h] |
||
650 | movzx ecx,word[edi+deflate_state.heap+2*eax] |
||
651 | ;ecx = n |
||
652 | mov eax,sizeof.ct_data |
||
653 | imul eax,ecx |
||
654 | add eax,[tree] |
||
655 | movzx eax,word[eax+Dad] |
||
656 | imul eax,sizeof.ct_data |
||
657 | add eax,[tree] |
||
658 | movzx eax,word[eax+Len] |
||
659 | inc eax |
||
660 | mov [bits],eax ;bits = tree[tree[n].Dad].Len + 1 |
||
661 | mov eax,[max_length] |
||
662 | cmp [bits],eax |
||
663 | jle @f ;if (..>..) |
||
664 | mov [bits],eax |
||
665 | inc dword[overflow] |
||
666 | @@: |
||
667 | mov esi,[bits] |
||
668 | mov eax,sizeof.ct_data |
||
669 | imul eax,ecx |
||
670 | add eax,[tree] |
||
671 | mov word[eax+Len],si |
||
672 | ; We overwrite tree[n].Dad which is no longer needed |
||
673 | |||
674 | cmp ecx,[max_code] |
||
675 | jle @f |
||
676 | inc dword[h] |
||
677 | jmp .cycle1 ;if (..>..) continue ;not a leaf node |
||
678 | @@: |
||
679 | |||
680 | mov eax,[bits] |
||
681 | shl eax,1 ;*= sizeof.uint_16 |
||
682 | inc word[eax+edi+deflate_state.bl_count] |
||
683 | mov dword[xbits],0 |
||
684 | cmp ecx,[base] |
||
685 | jl @f ;if (..>=..) |
||
686 | mov eax,ecx |
||
687 | sub eax,[base] |
||
688 | shl eax,2 ;*= sizeof.dd |
||
689 | add eax,[extra] |
||
690 | mov eax,[eax] |
||
691 | mov [xbits],eax |
||
692 | @@: |
||
693 | mov eax,sizeof.ct_data |
||
694 | imul eax,ecx |
||
695 | add eax,[tree] |
||
696 | movzx eax,word[eax+Freq] |
||
697 | mov [f],ax |
||
698 | mov esi,[bits] |
||
699 | add esi,[xbits] |
||
700 | imul eax,esi |
||
701 | add [edi+deflate_state.opt_len],eax |
||
702 | cmp dword[stree],0 |
||
703 | je @f ;if (..) |
||
704 | movzx eax,word[f] |
||
705 | mov esi,sizeof.ct_data |
||
706 | imul esi,ecx |
||
707 | add esi,[tree] |
||
708 | movzx esi,word[esi+Len] |
||
709 | add esi,[xbits] |
||
710 | imul eax,esi |
||
711 | add [edi+deflate_state.static_len],eax |
||
712 | @@: |
||
713 | inc dword[h] |
||
714 | jmp .cycle1 |
||
715 | align 4 |
||
716 | .cycle1end: |
||
717 | cmp dword[overflow],0 |
||
718 | je .end_f ;if (..==0) return |
||
719 | |||
720 | ; Trace((stderr,"\nbit length overflow\n")); |
||
721 | ; This happens for example on obj2 and pic of the Calgary corpus |
||
722 | |||
723 | ; Find the first bit length which could increase: |
||
724 | .cycle2: ;do |
||
725 | mov eax,[max_length] |
||
726 | dec eax |
||
727 | mov [bits],eax |
||
728 | shl eax,1 ;*= sizeof.dw |
||
729 | add eax,edi |
||
730 | add eax,deflate_state.bl_count |
||
731 | @@: |
||
732 | cmp word[eax],0 |
||
733 | jne @f ;while (..==0) bits-- |
||
734 | dec dword[bits] |
||
735 | sub eax,2 |
||
736 | jmp @b |
||
737 | @@: |
||
738 | dec word[eax] ;move one leaf down the tree |
||
739 | add word[eax+2],2 ;move one overflow item as its brother |
||
740 | mov eax,[max_length] |
||
741 | dec word[edi+deflate_state.bl_count+2*eax] |
||
742 | ; The brother of the overflow item also moves one step up, |
||
743 | ; but this does not affect bl_count[max_length] |
||
744 | |||
745 | sub dword[overflow],2 |
||
746 | cmp dword[overflow],0 |
||
747 | jg .cycle2 ;while (..>0) |
||
748 | |||
749 | ; Now recompute all bit lengths, scanning in increasing frequency. |
||
750 | ; h is still equal to HEAP_SIZE. (It is simpler to reconstruct all |
||
751 | ; lengths instead of fixing only the wrong ones. This idea is taken |
||
752 | ; from 'ar' written by Haruhiko Okumura.) |
||
753 | |||
754 | mov eax,[max_length] |
||
755 | mov [bits],eax |
||
756 | .cycle3: |
||
757 | cmp dword[bits],0 |
||
758 | je .end_f ;for (..;..!=0;..) |
||
759 | mov eax,[bits] |
||
760 | shl eax,1 ;*= sizeof.dw |
||
761 | movzx ecx,word[eax+edi+deflate_state.bl_count] |
||
762 | .cycle4: ;while (..!=0) |
||
763 | cmp ecx,0 |
||
764 | je .cycle4end |
||
765 | dec dword[h] |
||
766 | mov eax,[h] |
||
767 | movzx eax,word[edi+deflate_state.heap+2*eax] |
||
768 | mov [m],eax ;m = s.heap[--h] |
||
769 | cmp eax,[max_code] |
||
770 | jle @f ;if (..>..) continue |
||
771 | dec ecx |
||
772 | jmp .cycle4 |
||
773 | @@: |
||
774 | mov esi,[m] |
||
775 | imul esi,sizeof.ct_data |
||
776 | add esi,[tree] ;esi = &tree[m] |
||
777 | mov eax,[bits] |
||
778 | cmp word[esi+Len],ax |
||
779 | je @f ;if (..!=..) |
||
780 | ; Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); |
||
781 | movzx ebx,word[esi+Len] |
||
782 | sub eax,ebx |
||
783 | movzx ebx,word[esi+Freq] |
||
784 | imul eax,ebx ;eax = (bits - tree[m].Len) * tree[m].Freq |
||
785 | add [edi+deflate_state.opt_len],eax |
||
786 | mov eax,[bits] |
||
787 | mov word[esi+Len],ax |
||
788 | @@: |
||
789 | dec ecx |
||
790 | jmp .cycle4 |
||
791 | .cycle4end: |
||
792 | dec dword[bits] |
||
793 | jmp .cycle3 |
||
794 | .end_f: |
||
795 | popad |
||
796 | ret |
||
797 | endp |
||
798 | |||
799 | ; =========================================================================== |
||
800 | ; Generate the codes for a given tree and bit counts (which need not be |
||
801 | ; optimal). |
||
802 | ; IN assertion: the array bl_count contains the bit length statistics for |
||
803 | ; the given tree and the field len is set for all tree elements. |
||
804 | ; OUT assertion: the field code is set for all tree elements of non |
||
805 | ; zero code length. |
||
806 | |||
807 | ;void (tree, max_code, bl_count) |
||
808 | ; ct_data *tree ;the tree to decorate |
||
809 | ; int max_code ;largest code with non zero frequency |
||
810 | ; uint_16p bl_count ;number of codes at each bit length |
||
811 | align 4 |
||
812 | proc gen_codes uses eax ebx ecx edx edi, tree:dword, max_code:dword, bl_count:dword |
||
813 | locals |
||
814 | u_code dw 0 ;uint_16 ;running code value |
||
815 | bits dd 1 ;int ;bit index |
||
816 | next_code rw MAX_BITS+1 ;uint_16[] ;next code value for each bit length |
||
817 | endl |
||
818 | ; The distribution counts are first used to generate the code values |
||
819 | ; without bit reversal. |
||
820 | ;zlib_debug 'gen_codes' |
||
821 | mov ebx,ebp |
||
822 | sub ebx,2*(MAX_BITS+1) |
||
823 | |||
824 | .cycle0: ;for (..;..<=..;..) |
||
825 | cmp dword[bits],MAX_BITS |
||
826 | jg .cycle0end |
||
827 | mov eax,[bits] |
||
828 | dec eax |
||
829 | shl eax,1 |
||
830 | add eax,[bl_count] |
||
831 | mov ax,word[eax] |
||
832 | add ax,[u_code] |
||
833 | shl ax,1 ;ax = (u_code + bl_count[bits-1]) << 1 |
||
834 | mov [u_code],ax |
||
835 | mov ecx,[bits] |
||
836 | mov word[ebx+2*ecx],ax ;next_code[bits] = u_code |
||
837 | inc dword[bits] |
||
838 | jmp .cycle0 |
||
839 | .cycle0end: |
||
840 | ; Check that the bit counts in bl_count are consistent. The last code |
||
841 | ; must be all ones. |
||
842 | |||
843 | mov eax,[bl_count] |
||
844 | mov ax,word[eax+2*MAX_BITS] |
||
845 | add ax,[u_code] |
||
846 | dec ax |
||
847 | cmp ax,(1 shl MAX_BITS)-1 |
||
848 | je @f |
||
849 | zlib_debug 'inconsistent bit counts' ;Assert(..==..) |
||
850 | @@: |
||
851 | ; Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); |
||
852 | |||
853 | xor ecx,ecx ;n = 0 |
||
854 | .cycle1: ;for (..;..<=..;..) |
||
855 | cmp ecx,[max_code] |
||
856 | jg .cycle1end |
||
857 | mov edx,sizeof.ct_data |
||
858 | imul edx,ecx |
||
859 | add edx,[tree] ;edx = &tree[n] |
||
860 | movzx edi,word[edx+Len] |
||
861 | cmp edi,0 |
||
862 | jne @f ;if (..==0) continue |
||
863 | inc ecx |
||
864 | jmp .cycle1 |
||
865 | @@: |
||
866 | ; Now reverse the bits |
||
867 | movzx eax,word[ebx+2*edi] |
||
868 | stdcall bi_reverse, eax, edi |
||
869 | mov word[edx+Code],ax |
||
870 | inc word[ebx+2*edi] |
||
871 | |||
872 | ; Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", |
||
873 | ; n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); |
||
874 | inc ecx |
||
875 | jmp .cycle1 |
||
876 | .cycle1end: |
||
877 | ret |
||
878 | endp |
||
879 | |||
880 | ; =========================================================================== |
||
881 | ; Construct one Huffman tree and assigns the code bit strings and lengths. |
||
882 | ; Update the total bit length for the current block. |
||
883 | ; IN assertion: the field freq is set for all tree elements. |
||
884 | ; OUT assertions: the fields len and code are set to the optimal bit length |
||
885 | ; and corresponding code. The length opt_len is updated; static_len is |
||
886 | ; also updated if stree is not null. The field max_code is set. |
||
887 | |||
888 | ;void (s, desc) |
||
889 | ; deflate_state* s |
||
890 | ; tree_desc *desc ;the tree descriptor |
||
891 | align 4 |
||
892 | proc build_tree uses eax ebx ecx edx edi, s:dword, desc:dword |
||
893 | locals |
||
894 | tree dd ? ;ct_data* ;= desc.dyn_tree |
||
895 | stree dd ? ;ct_data* ;= desc.stat_desc.static_tree |
||
896 | elems dd ? ;int ;= desc.stat_desc.elems |
||
897 | m dd ? ;int ;iterate over heap elements |
||
898 | max_code dd -1 ;int ;largest code with non zero frequency |
||
899 | node dd ? ;int ;new node being created |
||
900 | endl |
||
901 | ; Construct the initial heap, with least frequent element in |
||
902 | ; heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. |
||
903 | ; heap[0] is not used. |
||
904 | mov ebx,[desc] |
||
905 | mov eax,[ebx+tree_desc.dyn_tree] |
||
906 | mov [tree],eax |
||
907 | mov ecx,[ebx+tree_desc.stat_desc] |
||
908 | mov eax,[ecx+static_tree_desc.static_tree] |
||
909 | mov [stree],eax |
||
910 | mov ecx,[ecx+static_tree_desc.elems] |
||
911 | mov [elems],ecx |
||
912 | mov edi,[s] |
||
913 | ;zlib_debug 'build_tree cycle0 ecx = %d',ecx |
||
914 | |||
915 | mov dword[edi+deflate_state.heap_len],0 |
||
916 | mov dword[edi+deflate_state.heap_max],HEAP_SIZE |
||
917 | |||
918 | cmp ecx,0 |
||
919 | jle .cycle0end |
||
920 | xor edx,edx |
||
921 | .cycle0: ;for (..;..<..;..) |
||
922 | mov eax,edx |
||
923 | imul eax,sizeof.ct_data |
||
924 | add eax,[tree] |
||
925 | cmp word[eax+Freq],0 |
||
926 | je @f ;if (..!=0) |
||
927 | inc dword[edi+deflate_state.heap_len] |
||
928 | mov eax,[edi+deflate_state.heap_len] |
||
929 | mov [max_code],edx |
||
930 | mov [edi+deflate_state.heap+2*eax],dx |
||
931 | mov eax,edx |
||
932 | add eax,edi |
||
933 | add eax,deflate_state.depth |
||
934 | mov byte[eax],0 |
||
935 | jmp .end0 |
||
936 | align 4 |
||
937 | @@: ;else |
||
938 | mov word[eax+Len],0 |
||
939 | .end0: |
||
940 | inc edx |
||
941 | loop .cycle0 |
||
942 | align 4 |
||
943 | .cycle0end: |
||
944 | |||
945 | ; The pkzip format requires that at least one distance code exists, |
||
946 | ; and that at least one bit should be sent even if there is only one |
||
947 | ; possible code. So to avoid special checks later on we force at least |
||
948 | ; two codes of non zero frequency. |
||
949 | |||
950 | .cycle1: ;while (..<..) |
||
951 | cmp dword[edi+deflate_state.heap_len],2 |
||
952 | jge .cycle1end |
||
953 | inc dword[edi+deflate_state.heap_len] |
||
954 | xor eax,eax |
||
955 | cmp dword[max_code],2 |
||
956 | jge @f |
||
957 | inc dword[max_code] |
||
958 | mov eax,[max_code] |
||
959 | @@: |
||
960 | mov ecx,[edi+deflate_state.heap_len] |
||
961 | mov [edi+deflate_state.heap+2*ecx],ax |
||
962 | mov [node],eax |
||
963 | imul eax,sizeof.ct_data |
||
964 | add eax,[tree] |
||
965 | mov word[eax+Freq],1 |
||
966 | mov eax,[node] |
||
967 | mov byte[edi+deflate_state.depth+eax],0 |
||
968 | dec dword[edi+deflate_state.opt_len] |
||
969 | cmp dword[stree],0 |
||
970 | je .cycle1 ;if (..) |
||
971 | mov eax,[node] |
||
972 | imul eax,sizeof.ct_data |
||
973 | add eax,[stree] |
||
974 | movzx eax,word[eax+Len] |
||
975 | sub [edi+deflate_state.static_len],eax |
||
976 | ; node is 0 or 1 so it does not have extra bits |
||
977 | jmp .cycle1 |
||
978 | align 4 |
||
979 | .cycle1end: |
||
980 | mov eax,[max_code] |
||
981 | mov [ebx+tree_desc.max_code],eax |
||
982 | |||
983 | ; The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, |
||
984 | ; establish sub-heaps of increasing lengths: |
||
985 | |||
986 | mov ecx,[edi+deflate_state.heap_len] |
||
987 | shr ecx,1 |
||
988 | .cycle2: ;for (..;..>=..;..) |
||
989 | cmp ecx,1 |
||
990 | jl .cycle2end |
||
991 | stdcall pqdownheap, edi, [tree], ecx |
||
992 | dec ecx |
||
993 | jmp .cycle2 |
||
994 | align 4 |
||
995 | .cycle2end: |
||
996 | |||
997 | ; Construct the Huffman tree by repeatedly combining the least two |
||
998 | ; frequent nodes. |
||
999 | |||
1000 | mov eax,[elems] |
||
1001 | mov [node],eax ;next internal node of the tree |
||
1002 | .cycle3: ;do |
||
1003 | pqremove edi, [tree], ecx ;n = node of least frequency |
||
1004 | movzx edx,word[eax] |
||
1005 | mov [m],edx ;m = node of next least frequency |
||
1006 | |||
1007 | mov eax,[edi+deflate_state.heap_max] |
||
1008 | dec eax |
||
1009 | mov [edi+deflate_state.heap+2*eax],cx ;keep the nodes sorted by frequency |
||
1010 | dec eax |
||
1011 | mov [edi+deflate_state.heap_max],eax |
||
1012 | mov [edi+deflate_state.heap+2*eax],dx |
||
1013 | |||
1014 | ; Create a new node father of n and m |
||
1015 | ;;mov edx,[m] |
||
1016 | imul edx,sizeof.ct_data |
||
1017 | add edx,[tree] |
||
1018 | mov ax,word[edx+Freq] |
||
1019 | mov edx,ecx |
||
1020 | imul edx,sizeof.ct_data |
||
1021 | add edx,[tree] |
||
1022 | add ax,word[edx+Freq] |
||
1023 | mov edx,[node] |
||
1024 | imul edx,sizeof.ct_data |
||
1025 | add edx,[tree] |
||
1026 | mov word[edx+Freq],ax |
||
1027 | |||
1028 | mov eax,ecx |
||
1029 | add eax,edi |
||
1030 | add eax,deflate_state.depth |
||
1031 | mov al,byte[eax] |
||
1032 | mov edx,[m] |
||
1033 | add edx,edi |
||
1034 | add edx,deflate_state.depth |
||
1035 | mov ah,byte[edx] |
||
1036 | cmp al,ah |
||
1037 | jl @f ;if (al>=ah) al=al : al=ah |
||
1038 | mov al,ah |
||
1039 | @@: |
||
1040 | inc al |
||
1041 | mov edx,[node] |
||
1042 | add edx,edi |
||
1043 | add edx,deflate_state.depth |
||
1044 | mov byte[edx],al |
||
1045 | |||
1046 | mov eax,[node] |
||
1047 | mov edx,[m] |
||
1048 | imul edx,sizeof.ct_data |
||
1049 | add edx,[tree] |
||
1050 | mov [edx+Dad],ax |
||
1051 | mov edx,ecx |
||
1052 | imul edx,sizeof.ct_data |
||
1053 | add edx,[tree] |
||
1054 | mov [edx+Dad],ax |
||
1055 | ;if DUMP_BL_TREE eq 1 |
||
1056 | ; if (tree == s->bl_tree) { |
||
1057 | ; fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", |
||
1058 | ; node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); |
||
1059 | ; } |
||
1060 | ;end if |
||
1061 | ; and insert the new node in the heap |
||
1062 | mov ecx,[node] |
||
1063 | mov [edi+deflate_state.heap+2*SMALLEST],cx |
||
1064 | inc dword[node] |
||
1065 | stdcall pqdownheap, edi, [tree], SMALLEST |
||
1066 | cmp dword[edi+deflate_state.heap_len],2 |
||
1067 | jge .cycle3 ;while (..>=..) |
||
1068 | |||
1069 | mov cx,[edi+deflate_state.heap+2*SMALLEST] |
||
1070 | dec dword[edi+deflate_state.heap_max] |
||
1071 | mov eax,[edi+deflate_state.heap_max] |
||
1072 | mov [edi+deflate_state.heap+2*eax],cx |
||
1073 | |||
1074 | ; At this point, the fields freq and dad are set. We can now |
||
1075 | ; generate the bit lengths. |
||
1076 | |||
1077 | stdcall gen_bitlen, edi, [desc] |
||
1078 | |||
1079 | ; The field len is now set, we can generate the bit codes |
||
1080 | mov eax,edi |
||
1081 | add eax,deflate_state.bl_count |
||
1082 | stdcall gen_codes, [tree], [max_code], eax |
||
1083 | ret |
||
1084 | endp |
||
1085 | |||
1086 | ; =========================================================================== |
||
1087 | ; Scan a literal or distance tree to determine the frequencies of the codes |
||
1088 | ; in the bit length tree. |
||
1089 | |||
1090 | ;void (s, tree, max_code) |
||
1091 | ; deflate_state* s |
||
1092 | ; ct_data *tree ;the tree to be scanned |
||
1093 | ; int max_code ;and its largest code of non zero frequency |
||
1094 | align 4 |
||
1095 | proc scan_tree uses eax ebx ecx edi, s:dword, tree:dword, max_code:dword |
||
1096 | locals |
||
1097 | n dd ? ;int ;iterates over all tree elements |
||
1098 | prevlen dd -1 ;int ;last emitted length |
||
1099 | curlen dd ? ;int ;length of current code |
||
1100 | nextlen dd ? ;int ;= tree[0].Len ;length of next code |
||
1101 | count dd 0 ;int ;repeat count of the current code |
||
1102 | max_count dd 7 ;int ;max repeat count |
||
1103 | min_count dd 4 ;int ;min repeat count |
||
1104 | endl |
||
1105 | mov edi,[s] |
||
1106 | ;zlib_debug 'scan_tree' |
||
1107 | mov eax,[tree] |
||
1108 | movzx eax,word[eax+Len] |
||
1109 | mov [nextlen],eax |
||
1110 | cmp eax,0 |
||
1111 | jne @f ;if (..==0) |
||
1112 | mov dword[max_count],138 |
||
1113 | mov dword[min_count],3 |
||
1114 | @@: |
||
1115 | mov eax,[max_code] |
||
1116 | inc eax |
||
1117 | imul eax,sizeof.ct_data |
||
1118 | add eax,[tree] |
||
1119 | mov word[eax+Len],0xffff ;guard |
||
1120 | |||
1121 | xor ecx,ecx |
||
1122 | .cycle0: |
||
1123 | cmp ecx,[max_code] |
||
1124 | jg .cycle0end ;for (..;..<=..;..) |
||
1125 | mov eax,[nextlen] |
||
1126 | mov [curlen],eax |
||
1127 | mov eax,ecx |
||
1128 | inc eax |
||
1129 | imul eax,sizeof.ct_data |
||
1130 | add eax,[tree] |
||
1131 | movzx eax,word[eax+Len] |
||
1132 | mov [nextlen],eax |
||
1133 | inc dword[count] |
||
1134 | mov ebx,[count] |
||
1135 | cmp ebx,[max_count] |
||
1136 | jge .end0 |
||
1137 | mov eax,[nextlen] |
||
1138 | cmp [curlen],eax |
||
1139 | jne .end0 ;if (..<.. && ..==..) |
||
1140 | inc ecx |
||
1141 | jmp .cycle0 ;continue |
||
1142 | .end0: |
||
1143 | cmp ebx,[min_count] |
||
1144 | jge .end1 ;else if (..<..) |
||
1145 | mov eax,[curlen] |
||
1146 | imul eax,sizeof.ct_data |
||
1147 | add eax,edi |
||
1148 | add eax,deflate_state.bl_tree+Freq |
||
1149 | add word[eax],bx |
||
1150 | jmp .end4 |
||
1151 | .end1: |
||
1152 | cmp dword[curlen],0 |
||
1153 | je .end2 ;else if (..!=0) |
||
1154 | mov eax,[curlen] |
||
1155 | cmp eax,[prevlen] |
||
1156 | je @f ;if (..!=..) |
||
1157 | imul eax,sizeof.ct_data |
||
1158 | add eax,edi |
||
1159 | add eax,deflate_state.bl_tree+Freq |
||
1160 | inc word[eax] |
||
1161 | @@: |
||
1162 | mov eax,REP_3_6 |
||
1163 | imul eax,sizeof.ct_data |
||
1164 | add eax,edi |
||
1165 | add eax,deflate_state.bl_tree+Freq |
||
1166 | inc word[eax] |
||
1167 | jmp .end4 |
||
1168 | .end2: |
||
1169 | cmp ebx,10 |
||
1170 | jg .end3 ;else if (..<=..) |
||
1171 | mov eax,REPZ_3_10 |
||
1172 | imul eax,sizeof.ct_data |
||
1173 | add eax,edi |
||
1174 | add eax,deflate_state.bl_tree+Freq |
||
1175 | inc word[eax] |
||
1176 | jmp .end4 |
||
1177 | .end3: ;else |
||
1178 | mov eax,REPZ_11_138 |
||
1179 | imul eax,sizeof.ct_data |
||
1180 | add eax,edi |
||
1181 | add eax,deflate_state.bl_tree+Freq |
||
1182 | inc word[eax] |
||
1183 | .end4: |
||
1184 | mov dword[curlen],0 |
||
1185 | mov eax,[curlen] |
||
1186 | mov [prevlen],eax |
||
1187 | mov [nextlen],eax |
||
1188 | cmp eax,0 |
||
1189 | jne .end5 ;if (..==0) |
||
1190 | mov dword[max_count],138 |
||
1191 | mov dword[min_count],3 |
||
1192 | jmp .end7 |
||
1193 | .end5: |
||
1194 | mov eax,[curlen] |
||
1195 | cmp eax,[nextlen] |
||
1196 | jne .end6 ;else if (..==..) |
||
1197 | mov dword[max_count],6 |
||
1198 | mov dword[min_count],3 |
||
1199 | jmp .end7 |
||
1200 | .end6: ;else |
||
1201 | mov dword[max_count],7 |
||
1202 | mov dword[min_count],4 |
||
1203 | .end7: |
||
1204 | inc ecx |
||
1205 | jmp .cycle0 |
||
1206 | .cycle0end: |
||
1207 | ret |
||
1208 | endp |
||
1209 | |||
1210 | ; =========================================================================== |
||
1211 | ; Send a literal or distance tree in compressed form, using the codes in |
||
1212 | ; bl_tree. |
||
1213 | |||
1214 | ;void (s, tree, max_code) |
||
1215 | ; deflate_state* s |
||
1216 | ; ct_data *tree ;the tree to be scanned |
||
1217 | ; int max_code ;and its largest code of non zero frequency |
||
1218 | align 4 |
||
1219 | proc send_tree uses eax ebx ecx edi, s:dword, tree:dword, max_code:dword |
||
1220 | locals |
||
1221 | n dd ? ;int ;iterates over all tree elements |
||
1222 | prevlen dd -1 ;int ;last emitted length |
||
1223 | curlen dd ? ;int ;length of current code |
||
1224 | nextlen dd ? ;int ;= tree[0].Len ;length of next code |
||
1225 | count dd 0 ;int ;repeat count of the current code |
||
1226 | max_count dd 7 ;int ;max repeat count |
||
1227 | min_count dd 4 ;int ;min repeat count |
||
1228 | endl |
||
1229 | mov edi,[s] |
||
1230 | ;zlib_debug 'send_tree' |
||
1231 | ; *** tree[max_code+1].Len = -1 ;guard already set |
||
1232 | mov eax,[tree] |
||
1233 | movzx eax,word[eax+Len] |
||
1234 | mov [nextlen],eax |
||
1235 | cmp eax,0 |
||
1236 | jne @f ;if (..==0) |
||
1237 | mov dword[max_count],138 |
||
1238 | mov dword[min_count],3 |
||
1239 | @@: |
||
1240 | |||
1241 | xor ecx,ecx |
||
1242 | .cycle0: ;for (..;..<=..;..) |
||
1243 | cmp ecx,[max_code] |
||
1244 | jg .cycle0end |
||
1245 | mov eax,[nextlen] |
||
1246 | mov [curlen],eax |
||
1247 | mov eax,ecx |
||
1248 | inc eax |
||
1249 | imul eax,sizeof.ct_data |
||
1250 | add eax,[tree] |
||
1251 | movzx eax,word[eax+Len] |
||
1252 | mov [nextlen],eax |
||
1253 | inc dword[count] |
||
1254 | mov ebx,[count] |
||
1255 | cmp ebx,[max_count] |
||
1256 | jge .end0 |
||
1257 | mov eax,[nextlen] |
||
1258 | cmp [curlen],eax |
||
1259 | jne .end0 ;if (..<.. && ..==..) |
||
1260 | inc ecx |
||
1261 | jmp .cycle0 ;continue |
||
1262 | .end0: |
||
1263 | cmp ebx,[min_count] |
||
1264 | jge .end1 ;else if (..<..) |
||
1265 | @@: ;do |
||
1266 | mov ebx,edi |
||
1267 | add ebx,deflate_state.bl_tree |
||
1268 | send_code edi, [curlen], ebx |
||
1269 | dec dword[count] |
||
1270 | cmp dword[count],0 |
||
1271 | jne @b ;while (..!=0) |
||
1272 | jmp .end4 |
||
1273 | align 4 |
||
1274 | .end1: |
||
1275 | cmp dword[curlen],0 |
||
1276 | je .end2 ;else if (..!=0) |
||
1277 | mov eax,[curlen] |
||
1278 | cmp eax,[prevlen] |
||
1279 | je @f ;if (..!=..) |
||
1280 | mov ebx,edi |
||
1281 | add ebx,deflate_state.bl_tree |
||
1282 | send_code edi, eax, ebx |
||
1283 | dec dword[count] |
||
1284 | @@: |
||
1285 | cmp dword[count],3 |
||
1286 | jl @f |
||
1287 | cmp dword[count],6 |
||
1288 | jle .end8 |
||
1289 | @@: |
||
1290 | zlib_debug ' 3_6?' ;Assert(..>=.. && ..<=..) |
||
1291 | .end8: |
||
1292 | mov ebx,edi |
||
1293 | add ebx,deflate_state.bl_tree |
||
1294 | send_code edi, REP_3_6, ebx |
||
1295 | mov ebx,[count] |
||
1296 | sub ebx,3 |
||
1297 | stdcall send_bits, edi, ebx, 2 |
||
1298 | jmp .end4 |
||
1299 | .end2: |
||
1300 | cmp ebx,10 |
||
1301 | jg .end3 ;else if (..<=..) |
||
1302 | mov ebx,edi |
||
1303 | add ebx,deflate_state.bl_tree |
||
1304 | send_code edi, REPZ_3_10, ebx |
||
1305 | mov ebx,[count] |
||
1306 | sub ebx,3 |
||
1307 | stdcall send_bits, edi, ebx, 3 |
||
1308 | jmp .end4 |
||
1309 | .end3: ;else |
||
1310 | mov ebx,edi |
||
1311 | add ebx,deflate_state.bl_tree |
||
1312 | send_code edi, REPZ_11_138, ebx |
||
1313 | mov ebx,[count] |
||
1314 | sub ebx,11 |
||
1315 | stdcall send_bits, edi, ebx, 7 |
||
1316 | .end4: |
||
1317 | mov dword[curlen],0 |
||
1318 | mov eax,[curlen] |
||
1319 | mov [prevlen],eax |
||
1320 | mov [nextlen],eax |
||
1321 | cmp eax,0 |
||
1322 | jne .end5 ;if (..==0) |
||
1323 | mov dword[max_count],138 |
||
1324 | mov dword[min_count],3 |
||
1325 | jmp .end7 |
||
1326 | .end5: |
||
1327 | mov eax,[curlen] |
||
1328 | cmp eax,[nextlen] |
||
1329 | jne .end6 ;else if (..==..) |
||
1330 | mov dword[max_count],6 |
||
1331 | mov dword[min_count],3 |
||
1332 | jmp .end7 |
||
1333 | .end6: ;else |
||
1334 | mov dword[max_count],7 |
||
1335 | mov dword[min_count],4 |
||
1336 | .end7: |
||
1337 | inc ecx |
||
1338 | jmp .cycle0 |
||
1339 | align 4 |
||
1340 | .cycle0end: |
||
1341 | ret |
||
1342 | endp |
||
1343 | |||
1344 | ; =========================================================================== |
||
1345 | ; Construct the Huffman tree for the bit lengths and return the index in |
||
1346 | ; bl_order of the last bit length code to send. |
||
1347 | |||
1348 | ;int (s) |
||
1349 | ; deflate_state* s |
||
1350 | align 4 |
||
1351 | proc build_bl_tree uses edi, s:dword |
||
1352 | locals |
||
1353 | max_blindex dd ? ;int ;index of last bit length code of non zero freq |
||
1354 | endl |
||
1355 | mov edi,[s] |
||
1356 | ; Determine the bit length frequencies for literal and distance trees |
||
1357 | mov eax,edi |
||
1358 | add eax,deflate_state.dyn_ltree |
||
1359 | stdcall scan_tree, edi, eax, [edi+deflate_state.l_desc.max_code] |
||
1360 | mov eax,edi |
||
1361 | add eax,deflate_state.dyn_dtree |
||
1362 | stdcall scan_tree, edi, eax, [edi+deflate_state.d_desc.max_code] |
||
1363 | |||
1364 | ; Build the bit length tree: |
||
1365 | mov eax,edi |
||
1366 | add eax,deflate_state.bl_desc |
||
1367 | stdcall build_tree, edi, eax |
||
1368 | ; opt_len now includes the length of the tree representations, except |
||
1369 | ; the lengths of the bit lengths codes and the 5+5+4 bits for the counts. |
||
1370 | |||
1371 | ; Determine the number of bit length codes to send. The pkzip format |
||
1372 | ; requires that at least 4 bit length codes be sent. (appnote.txt says |
||
1373 | ; 3 but the actual value used is 4.) |
||
1374 | |||
1375 | mov dword[max_blindex],BL_CODES-1 |
||
1376 | .cycle0: ;for (..;..>=..;..) |
||
1377 | cmp dword[max_blindex],3 |
||
1378 | jl .cycle0end |
||
1379 | dec dword[max_blindex] |
||
1380 | mov eax,[max_blindex] |
||
1381 | add eax,bl_order |
||
1382 | movzx eax,byte[eax] |
||
1383 | imul eax,sizeof.ct_data |
||
1384 | add eax,edi |
||
1385 | add eax,deflate_state.bl_tree+Len |
||
1386 | cmp word[eax],0 |
||
1387 | jne .cycle0end ;if (..!=0) break |
||
1388 | jmp .cycle0 |
||
1389 | .cycle0end: |
||
1390 | ; Update opt_len to include the bit length tree and counts |
||
1391 | mov eax,[max_blindex] |
||
1392 | inc eax |
||
1393 | imul eax,3 |
||
1394 | add eax,5+5+4 |
||
1395 | add [edi+deflate_state.opt_len],eax |
||
1396 | ; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); |
||
1397 | |||
1398 | mov eax,[max_blindex] |
||
1399 | ret |
||
1400 | endp |
||
1401 | |||
1402 | ; =========================================================================== |
||
1403 | ; Send the header for a block using dynamic Huffman trees: the counts, the |
||
1404 | ; lengths of the bit length codes, the literal tree and the distance tree. |
||
1405 | ; IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. |
||
1406 | |||
1407 | ;void (s, lcodes, dcodes, blcodes) |
||
1408 | ; deflate_state* s |
||
1409 | ; int lcodes, dcodes, blcodes ;number of codes for each tree |
||
1410 | align 4 |
||
1411 | proc send_all_trees uses eax ebx ecx edi, s:dword, lcodes:dword, dcodes:dword, blcodes:dword |
||
1412 | ;ecx = index in bl_order |
||
1413 | ;zlib_debug 'send_all_trees' |
||
1414 | cmp dword[lcodes],257 |
||
1415 | jl @f |
||
1416 | cmp dword[dcodes],1 |
||
1417 | jl @f |
||
1418 | cmp dword[blcodes],4 |
||
1419 | jge .end0 |
||
1420 | @@: |
||
1421 | zlib_debug 'not enough codes' ;Assert(..>=.. && ..>=.. && ..>=..) |
||
1422 | .end0: |
||
1423 | cmp dword[lcodes],L_CODES |
||
1424 | jg @f |
||
1425 | cmp dword[dcodes],D_CODES |
||
1426 | jg @f |
||
1427 | cmp dword[blcodes],BL_CODES |
||
1428 | jle .end1 |
||
1429 | @@: |
||
1430 | zlib_debug 'too many codes' ;Assert(..<=.. && ..<=.. && ..<=..) |
||
1431 | .end1: |
||
1432 | ; Tracev((stderr, "\nbl counts: ")); |
||
1433 | mov edi,[s] |
||
1434 | mov eax,[lcodes] |
||
1435 | sub eax,257 |
||
1436 | stdcall send_bits, edi, eax, 5 ;not +255 as stated in appnote.txt |
||
1437 | mov eax,[dcodes] |
||
1438 | dec eax |
||
1439 | stdcall send_bits, edi, eax, 5 |
||
1440 | mov eax,[blcodes] |
||
1441 | sub eax,4 |
||
1442 | stdcall send_bits, edi, eax, 4 ;not -3 as stated in appnote.txt |
||
1443 | xor ecx,ecx |
||
1444 | .cycle0: |
||
1445 | cmp ecx,[blcodes] |
||
1446 | jge .cycle0end ;for (..;..<..;..) |
||
1447 | ; Tracev((stderr, "\nbl code %2d ", bl_order[ecx])); |
||
1448 | mov eax,ecx |
||
1449 | add eax,bl_order |
||
1450 | movzx eax,byte[eax] |
||
1451 | imul eax,sizeof.ct_data |
||
1452 | mov ebx,edi |
||
1453 | add ebx,deflate_state.bl_tree+Len |
||
1454 | add ebx,eax |
||
1455 | stdcall send_bits, edi, ebx, 3 |
||
1456 | inc ecx |
||
1457 | jmp .cycle0 |
||
1458 | align 4 |
||
1459 | .cycle0end: |
||
1460 | ; Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); |
||
1461 | |||
1462 | mov ebx,[lcodes] |
||
1463 | dec ebx |
||
1464 | mov eax,edi |
||
1465 | add eax,deflate_state.dyn_ltree |
||
1466 | stdcall send_tree, edi, eax, ebx ;literal tree |
||
1467 | ; Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); |
||
1468 | |||
1469 | mov ebx,[dcodes] |
||
1470 | dec ebx |
||
1471 | add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree |
||
1472 | stdcall send_tree, edi, eax, ebx ;distance tree |
||
1473 | ; Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); |
||
1474 | ret |
||
1475 | endp |
||
1476 | |||
1477 | ; =========================================================================== |
||
1478 | ; Send a stored block |
||
1479 | |||
1480 | ;void (s, buf, stored_len, last) |
||
1481 | ; deflate_state* s |
||
1482 | ; charf *buf ;input block |
||
1483 | ; ulg stored_len ;length of input block |
||
1484 | ; int last ;one if this is the last block for a file |
||
1485 | align 4 |
||
1486 | proc _tr_stored_block uses eax edi, s:dword, buf:dword, stored_len:dword, last:dword |
||
1487 | mov edi,[s] |
||
1488 | mov eax,[last] |
||
1489 | add eax,STORED_BLOCK shl 1 |
||
1490 | stdcall send_bits, edi, eax, 3 ;send block type |
||
1491 | if DEBUG eq 1 |
||
1492 | mov eax,[edi+deflate_state.compressed_len] |
||
1493 | add eax,3+7 |
||
1494 | and eax,not 7 |
||
1495 | mov [edi+deflate_state.compressed_len],eax |
||
1496 | mov eax,[stored_len] |
||
1497 | add eax,4 |
||
1498 | shl eax,3 |
||
1499 | add [edi+deflate_state.compressed_len],eax |
||
1500 | end if |
||
1501 | stdcall copy_block, edi, [buf], [stored_len], 1 ;with header |
||
1502 | ret |
||
1503 | endp |
||
1504 | |||
1505 | ; =========================================================================== |
||
1506 | ; Flush the bits in the bit buffer to pending output (leaves at most 7 bits) |
||
1507 | |||
1508 | ;void (s) |
||
1509 | ; deflate_state* s; |
||
1510 | align 4 |
||
1511 | proc _tr_flush_bits, s:dword |
||
1512 | stdcall bi_flush, [s] |
||
1513 | ret |
||
1514 | endp |
||
1515 | |||
1516 | ; =========================================================================== |
||
1517 | ; Send one empty static block to give enough lookahead for inflate. |
||
1518 | ; This takes 10 bits, of which 7 may remain in the bit buffer. |
||
1519 | |||
1520 | ;void (s) |
||
1521 | ; deflate_state* s |
||
1522 | align 4 |
||
1523 | proc _tr_align uses edi, s:dword |
||
1524 | mov edi,[s] |
||
1525 | stdcall send_bits, edi, STATIC_TREES shl 1, 3 |
||
1526 | send_code edi, END_BLOCK, static_ltree |
||
1527 | if DEBUG eq 1 |
||
1528 | add [edi+deflate_state.compressed_len],10 ;3 for block type, 7 for EOB |
||
1529 | end if |
||
1530 | stdcall bi_flush, edi |
||
1531 | ret |
||
1532 | endp |
||
1533 | |||
1534 | ; =========================================================================== |
||
1535 | ; Determine the best encoding for the current block: dynamic trees, static |
||
1536 | ; trees or store, and output the encoded block to the zip file. |
||
1537 | |||
1538 | ;void (s, buf, stored_len, last) |
||
1539 | ; deflate_state* s |
||
1540 | ; charf *buf ;input block, or NULL if too old |
||
1541 | ; ulg stored_len ;length of input block |
||
1542 | ; int last ;one if this is the last block for a file |
||
1543 | align 4 |
||
1544 | proc _tr_flush_block uses eax ebx edi, s:dword, buf:dword, stored_len:dword, last:dword |
||
1545 | locals |
||
1546 | opt_lenb dd ? ;ulg |
||
1547 | static_lenb dd ? ;opt_len and static_len in bytes |
||
1548 | max_blindex dd 0 ;int ;index of last bit length code of non zero freq |
||
1549 | endl |
||
1550 | ; Build the Huffman trees unless a stored block is forced |
||
1551 | mov edi,[s] |
||
1552 | ;zlib_debug '_tr_flush_block' |
||
1553 | cmp word[edi+deflate_state.level],0 |
||
1554 | jle .end0 ;if (..>0) |
||
1555 | |||
1556 | ; Check if the file is binary or text |
||
1557 | mov ebx,[edi+deflate_state.strm] |
||
1558 | cmp word[ebx+z_stream.data_type],Z_UNKNOWN |
||
1559 | jne @f ;if (..==..) |
||
1560 | stdcall detect_data_type, edi |
||
1561 | mov [ebx+z_stream.data_type],ax |
||
1562 | @@: |
||
1563 | |||
1564 | ; Construct the literal and distance trees |
||
1565 | mov eax,edi |
||
1566 | add eax,deflate_state.l_desc |
||
1567 | stdcall build_tree, edi, eax |
||
1568 | ; Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); |
||
1569 | |||
1570 | mov eax,edi |
||
1571 | add eax,deflate_state.d_desc |
||
1572 | stdcall build_tree, edi, eax |
||
1573 | ; Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); |
||
1574 | ; At this point, opt_len and static_len are the total bit lengths of |
||
1575 | ; the compressed block data, excluding the tree representations. |
||
1576 | |||
1577 | ; Build the bit length tree for the above two trees, and get the index |
||
1578 | ; in bl_order of the last bit length code to send. |
||
1579 | |||
1580 | stdcall build_bl_tree, edi |
||
1581 | mov [max_blindex],eax |
||
1582 | |||
1583 | ; Determine the best encoding. Compute the block lengths in bytes. |
||
1584 | mov eax,[edi+deflate_state.opt_len] |
||
1585 | add eax,3+7 |
||
1586 | shr eax,3 |
||
1587 | mov [opt_lenb],eax |
||
1588 | mov eax,[edi+deflate_state.static_len] |
||
1589 | add eax,3+7 |
||
1590 | shr eax,3 |
||
1591 | mov [static_lenb],eax |
||
1592 | |||
1593 | ; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", |
||
1594 | ; opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, |
||
1595 | ; s->last_lit)); |
||
1596 | |||
1597 | cmp eax,[opt_lenb] |
||
1598 | jg .end1 ;if (..<=..) |
||
1599 | mov [opt_lenb],eax |
||
1600 | jmp .end1 |
||
1601 | .end0: ;else |
||
1602 | cmp dword[buf],0 |
||
1603 | jne @f |
||
1604 | zlib_debug 'lost buf' ;Assert(..!=0) |
||
1605 | @@: |
||
1606 | mov eax,[stored_len] |
||
1607 | add eax,5 |
||
1608 | mov [static_lenb],eax |
||
1609 | mov [opt_lenb],eax ;force a stored block |
||
1610 | .end1: |
||
1611 | |||
1612 | if FORCE_STORED eq 1 |
||
1613 | cmp dword[buf],0 |
||
1614 | je .end2 ;if (..!=0) ;force stored block |
||
1615 | else |
||
1616 | mov eax,[stored_len] |
||
1617 | add eax,4 |
||
1618 | cmp eax,[opt_lenb] |
||
1619 | jg .end2 |
||
1620 | cmp dword[buf],0 |
||
1621 | je .end2 ;if (..<=.. && ..!=0) |
||
1622 | ;4: two words for the lengths |
||
1623 | end if |
||
1624 | ; The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. |
||
1625 | ; Otherwise we can't have processed more than WSIZE input bytes since |
||
1626 | ; the last block flush, because compression would have been |
||
1627 | ; successful. If LIT_BUFSIZE <= WSIZE, it is never too late to |
||
1628 | ; transform a block into a stored block. |
||
1629 | |||
1630 | stdcall _tr_stored_block, edi, [buf], [stored_len], [last] |
||
1631 | jmp .end4 |
||
1632 | .end2: |
||
1633 | if FORCE_STATIC eq 1 |
||
1634 | cmp dword[static_lenb],0 |
||
1635 | jl .end3 ;else if (..>=0) ;force static trees |
||
1636 | else |
||
1637 | cmp word[edi+deflate_state.strategy],Z_FIXED |
||
1638 | je @f |
||
1639 | mov eax,[opt_lenb] |
||
1640 | cmp [static_lenb],eax |
||
1641 | je @f ;else if (..==.. || ..==..) |
||
1642 | jmp .end3 |
||
1643 | @@: |
||
1644 | end if |
||
1645 | mov eax,STATIC_TREES shl 1 |
||
1646 | add eax,[last] |
||
1647 | stdcall send_bits, edi, eax, 3 |
||
1648 | stdcall compress_block, edi, static_ltree, static_dtree |
||
1649 | if DEBUG eq 1 |
||
1650 | mov eax,[edi+deflate_state.static_len] |
||
1651 | add eax,3 |
||
1652 | add [edi+deflate_state.compressed_len],eax |
||
1653 | end if |
||
1654 | jmp .end4 |
||
1655 | .end3: ;else |
||
1656 | mov eax,DYN_TREES shl 1 |
||
1657 | add eax,[last] |
||
1658 | stdcall send_bits, edi, eax, 3 |
||
1659 | mov eax,[max_blindex] |
||
1660 | inc eax |
||
1661 | push eax |
||
1662 | mov eax,[edi+deflate_state.d_desc.max_code] |
||
1663 | inc eax |
||
1664 | push eax |
||
1665 | mov eax,[edi+deflate_state.l_desc.max_code] |
||
1666 | inc eax |
||
1667 | stdcall send_all_trees, edi, eax ;, ..., ... |
||
1668 | mov eax,edi |
||
1669 | add eax,deflate_state.dyn_dtree |
||
1670 | push eax |
||
1671 | add eax,deflate_state.dyn_ltree-deflate_state.dyn_dtree |
||
1672 | stdcall compress_block, edi, eax ;, ... |
||
1673 | if DEBUG eq 1 |
||
1674 | mov eax,[edi+deflate_state.opt_len] |
||
1675 | add eax,3 |
||
1676 | add [edi+deflate_state.compressed_len],eax |
||
1677 | end if |
||
1678 | .end4: |
||
1679 | ; Assert (s->compressed_len == s->bits_sent, "bad compressed size"); |
||
1680 | ; The above check is made mod 2^32, for files larger than 512 MB |
||
1681 | ; and uLong implemented on 32 bits. |
||
1682 | |||
1683 | stdcall init_block,edi |
||
1684 | |||
1685 | cmp dword[last],0 |
||
1686 | je @f ;if (..) |
||
1687 | stdcall bi_windup,edi |
||
1688 | if DEBUG eq 1 |
||
1689 | add [edi+deflate_state.compressed_len],7 ;align on byte boundary |
||
1690 | end if |
||
1691 | @@: |
||
1692 | ; Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, |
||
1693 | ; s->compressed_len-7*last)); |
||
1694 | ret |
||
1695 | endp |
||
1696 | |||
1697 | ; =========================================================================== |
||
1698 | ; Save the match info and tally the frequency counts. Return true if |
||
1699 | ; the current block must be flushed. |
||
1700 | |||
1701 | ;int (s, dist, lc) |
||
1702 | ; deflate_state* s |
||
1703 | ; unsigned dist ;distance of matched string |
||
1704 | ; unsigned lc ;match length-MIN_MATCH or unmatched char (if dist==0) |
||
1705 | align 4 |
||
1706 | proc _tr_tally uses ebx edi, s:dword, dist:dword, lc:dword |
||
1707 | mov edi,[s] |
||
1708 | ;zlib_debug '_tr_tally' |
||
1709 | mov eax,[edi+deflate_state.last_lit] |
||
1710 | shl eax,1 |
||
1711 | add eax,[edi+deflate_state.d_buf] |
||
1712 | mov ebx,[dist] |
||
1713 | mov word[eax],bx |
||
1714 | mov eax,[edi+deflate_state.last_lit] |
||
1715 | add eax,[edi+deflate_state.l_buf] |
||
1716 | mov ebx,[lc] |
||
1717 | mov byte[eax],bl |
||
1718 | inc dword[edi+deflate_state.last_lit] |
||
1719 | cmp dword[dist],0 |
||
1720 | jne @f ;if (..==0) |
||
1721 | ; lc is the unmatched char |
||
1722 | mov eax,[lc] |
||
1723 | imul eax,sizeof.ct_data |
||
1724 | add eax,edi |
||
1725 | inc word[eax+deflate_state.dyn_ltree+Freq] |
||
1726 | jmp .end0 |
||
1727 | @@: ;else |
||
1728 | inc dword[edi+deflate_state.matches] |
||
1729 | ; Here, lc is the match length - MIN_MATCH |
||
1730 | dec dword[dist] ;dist = match distance - 1 |
||
1731 | MAX_DIST edi |
||
1732 | cmp word[dist],ax |
||
1733 | jge @f |
||
1734 | cmp word[lc],MAX_MATCH-MIN_MATCH |
||
1735 | jg @f |
||
1736 | d_code [dist] |
||
1737 | cmp ax,D_CODES |
||
1738 | jl .end2 |
||
1739 | @@: |
||
1740 | zlib_debug '_tr_tally: bad match' ;Assert(..<.. && ..<=.. && ..<..) |
||
1741 | .end2: |
||
1742 | mov eax,[lc] |
||
1743 | add eax,_length_code |
||
1744 | movzx eax,byte[eax] |
||
1745 | add eax,LITERALS+1 |
||
1746 | imul eax,sizeof.ct_data |
||
1747 | add eax,edi |
||
1748 | add eax,deflate_state.dyn_ltree+Freq |
||
1749 | inc word[eax] |
||
1750 | d_code [dist] |
||
1751 | imul eax,sizeof.ct_data |
||
1752 | add eax,edi |
||
1753 | add eax,deflate_state.dyn_dtree+Freq |
||
1754 | inc word[eax] |
||
1755 | .end0: |
||
1756 | |||
1757 | if TRUNCATE_BLOCK eq 1 |
||
1758 | ; Try to guess if it is profitable to stop the current block here |
||
1759 | mov eax,[edi+deflate_state.last_lit] |
||
1760 | and eax,0x1fff |
||
1761 | cmp eax,0 |
||
1762 | jne .end1 |
||
1763 | cmp word[edi+deflate_state.level],2 |
||
1764 | jle .end1 ;if (..==.. && ..>..) |
||
1765 | ; Compute an upper bound for the compressed length |
||
1766 | ; ulg out_length = (ulg)s->last_lit*8L; |
||
1767 | ; ulg in_length = (ulg)((long)s->strstart - s->block_start); |
||
1768 | ; int dcode; |
||
1769 | ; for (dcode = 0; dcode < D_CODES; dcode++) { |
||
1770 | ; out_length += (ulg)s->dyn_dtree[dcode].Freq * |
||
1771 | ; (5L+extra_dbits[dcode]); |
||
1772 | ; } |
||
1773 | ; out_length >>= 3; |
||
1774 | ; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", |
||
1775 | ; s->last_lit, in_length, out_length, |
||
1776 | ; 100L - out_length*100L/in_length)); |
||
1777 | ; if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; |
||
1778 | .end1: |
||
1779 | end if |
||
1780 | mov ebx,[edi+deflate_state.last_lit] |
||
1781 | mov edi,[edi+deflate_state.lit_bufsize] |
||
1782 | dec edi |
||
1783 | xor eax,eax |
||
1784 | cmp ebx,edi |
||
1785 | jne @f |
||
1786 | inc eax ;return (..==..) |
||
1787 | @@: |
||
1788 | ; We avoid equality with lit_bufsize because of wraparound at 64K |
||
1789 | ; on 16 bit machines and because stored blocks are restricted to |
||
1790 | ; 64K-1 bytes. |
||
1791 | ret |
||
1792 | endp |
||
1793 | |||
1794 | ; =========================================================================== |
||
1795 | ; Send the block data compressed using the given Huffman trees |
||
1796 | |||
1797 | ;void (s, ltree, dtree) |
||
1798 | ; deflate_state* s; |
||
1799 | ; ct_data *ltree ;literal tree |
||
1800 | ; ct_data *dtree ;distance tree |
||
1801 | align 4 |
||
1802 | proc compress_block uses eax edi, s:dword, ltree:dword, dtree:dword |
||
1803 | locals |
||
1804 | dist dd ? ;unsigned ;distance of matched string |
||
1805 | lc dd ? ;int ;match length or unmatched char (if dist == 0) |
||
1806 | lx dd 0 ;unsigned ;running index in l_buf |
||
1807 | u_code dd ? ;unsigned ;the code to send |
||
1808 | extra dd ? ;int ;number of extra bits to send |
||
1809 | endl |
||
1810 | mov edi,[s] |
||
1811 | cmp dword[edi+deflate_state.last_lit],0 |
||
1812 | je .end0 ;if (..!=0) |
||
1813 | .cycle0: ; do |
||
1814 | mov eax,[lx] |
||
1815 | shl eax,1 |
||
1816 | add eax,[edi+deflate_state.d_buf] |
||
1817 | movzx eax,word[eax] |
||
1818 | mov [dist],eax |
||
1819 | mov eax,[lx] |
||
1820 | add eax,[edi+deflate_state.l_buf] |
||
1821 | movzx eax,byte[eax] |
||
1822 | mov [lc],eax |
||
1823 | inc dword[lx] |
||
1824 | cmp dword[dist],0 |
||
1825 | jne @f ;if (..==0) |
||
1826 | send_code edi, [lc], [ltree] ;send a literal byte |
||
1827 | ; Tracecv(isgraph(lc), (stderr," '%c' ", lc)); |
||
1828 | jmp .end1 |
||
1829 | @@: ;else |
||
1830 | ; Here, lc is the match length - MIN_MATCH |
||
1831 | mov eax,[lc] |
||
1832 | add eax,_length_code |
||
1833 | movzx eax,byte[eax] |
||
1834 | mov [u_code],eax |
||
1835 | add eax,LITERALS+1 |
||
1836 | send_code edi, eax, [ltree] ;send the length code |
||
1837 | mov eax,[u_code] |
||
1838 | shl eax,2 |
||
1839 | add eax,extra_lbits |
||
1840 | mov eax,[eax] |
||
1841 | mov [extra],eax |
||
1842 | cmp eax,0 |
||
1843 | je @f ;if (..!=0) |
||
1844 | mov eax,[u_code] |
||
1845 | shl eax,2 |
||
1846 | add eax,base_length |
||
1847 | mov eax,[eax] |
||
1848 | sub [lc],eax |
||
1849 | stdcall send_bits, edi, [lc], [extra] ;send the extra length bits |
||
1850 | @@: |
||
1851 | dec dword[dist] ;dist is now the match distance - 1 |
||
1852 | d_code [dist] |
||
1853 | mov [u_code],eax |
||
1854 | cmp eax,D_CODES |
||
1855 | jl @f |
||
1856 | zlib_debug 'bad d_code' ;Assert(..<..) |
||
1857 | @@: |
||
1858 | send_code edi, [u_code], [dtree] ;send the distance code |
||
1859 | mov eax,[u_code] |
||
1860 | shl eax,2 |
||
1861 | add eax,extra_dbits |
||
1862 | mov eax,[eax] |
||
1863 | mov [extra],eax |
||
1864 | cmp eax,0 |
||
1865 | je .end1 ;if (..!=0) |
||
1866 | mov eax,[u_code] |
||
1867 | shl eax,2 |
||
1868 | add eax,base_dist |
||
1869 | mov eax,[eax] |
||
1870 | sub [dist],eax |
||
1871 | stdcall send_bits, edi, [dist], [extra] ;send the extra distance bits |
||
1872 | .end1: ;literal or match pair ? |
||
1873 | |||
1874 | ; Check that the overlay between pending_buf and d_buf+l_buf is ok: |
||
1875 | mov eax,[lx] |
||
1876 | shl eax,1 |
||
1877 | add eax,[edi+deflate_state.lit_bufsize] |
||
1878 | cmp word[edi+deflate_state.pending],ax |
||
1879 | jl @f |
||
1880 | zlib_debug 'pendingBuf overflow' ;Assert(..<..) |
||
1881 | @@: |
||
1882 | mov eax,[edi+deflate_state.last_lit] |
||
1883 | cmp [lx],eax |
||
1884 | jl .cycle0 ;while (..<..) |
||
1885 | align 4 |
||
1886 | .end0: |
||
1887 | |||
1888 | send_code edi, END_BLOCK, [ltree] |
||
1889 | ret |
||
1890 | endp |
||
1891 | |||
1892 | ; =========================================================================== |
||
1893 | ; Check if the data type is TEXT or BINARY, using the following algorithm: |
||
1894 | ; - TEXT if the two conditions below are satisfied: |
||
1895 | ; a) There are no non-portable control characters belonging to the |
||
1896 | ; "black list" (0..6, 14..25, 28..31). |
||
1897 | ; b) There is at least one printable character belonging to the |
||
1898 | ; "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). |
||
1899 | ; - BINARY otherwise. |
||
1900 | ; - The following partially-portable control characters form a |
||
1901 | ; "gray list" that is ignored in this detection algorithm: |
||
1902 | ; (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). |
||
1903 | ; IN assertion: the fields Freq of dyn_ltree are set. |
||
1904 | |||
1905 | ;int (s) |
||
1906 | ; deflate_state* s |
||
1907 | align 4 |
||
1908 | proc detect_data_type uses ebx ecx edi, s:dword |
||
1909 | ; black_mask is the bit mask of black-listed bytes |
||
1910 | ; set bits 0..6, 14..25, and 28..31 |
||
1911 | ; 0xf3ffc07f = binary 11110011111111111100000001111111 |
||
1912 | locals |
||
1913 | black_mask dd 0xf3ffc07f |
||
1914 | ; int n; |
||
1915 | endl |
||
1916 | mov edi,[s] |
||
1917 | ;zlib_debug 'detect_data_type' |
||
1918 | |||
1919 | ; Check for non-textual ("black-listed") bytes. |
||
1920 | xor ecx,ecx |
||
1921 | mov ebx,edi |
||
1922 | add ebx,deflate_state.dyn_ltree+Freq |
||
1923 | .cycle0: |
||
1924 | cmp ecx,31 |
||
1925 | jg .cycle0end ;for (..;..<=..;..,..) |
||
1926 | bt dword[black_mask],0 |
||
1927 | jnc @f |
||
1928 | cmp word[ebx],0 |
||
1929 | je @f ;if (..&.. && ..!=0) |
||
1930 | mov eax,Z_BINARY |
||
1931 | jmp .end_f |
||
1932 | @@: |
||
1933 | shr dword[black_mask],1 |
||
1934 | add ebx,sizeof.ct_data |
||
1935 | inc ecx |
||
1936 | jmp .cycle0 |
||
1937 | .cycle0end: |
||
1938 | |||
1939 | ; Check for textual ("white-listed") bytes. |
||
1940 | mov ebx,edi |
||
1941 | add ebx,deflate_state.dyn_ltree+Freq+9*sizeof.ct_data |
||
1942 | cmp word[ebx],0 |
||
1943 | jne @f |
||
1944 | add ebx,sizeof.ct_data |
||
1945 | cmp word[ebx],0 |
||
1946 | jne @f |
||
1947 | add ebx,3*sizeof.ct_data |
||
1948 | cmp word[ebx],0 |
||
1949 | je .end0 |
||
1950 | @@: ;if (..!=0 || ..!=0 || ..!= 0) |
||
1951 | mov eax,Z_TEXT |
||
1952 | jmp .end_f |
||
1953 | .end0: |
||
1954 | mov ecx,32 |
||
1955 | mov ebx,edi |
||
1956 | add ebx,deflate_state.dyn_ltree+Freq |
||
1957 | .cycle1: |
||
1958 | cmp ecx,LITERALS |
||
1959 | jge .cycle1end ;for (..;..<..;..,..) |
||
1960 | cmp word[ebx],0 |
||
1961 | je @f ;if (..!=0) |
||
1962 | mov eax,Z_TEXT |
||
1963 | jmp .end_f |
||
1964 | @@: |
||
1965 | add ebx,sizeof.ct_data |
||
1966 | inc ecx |
||
1967 | jmp .cycle1 |
||
1968 | .cycle1end: |
||
1969 | |||
1970 | ; There are no "black-listed" or "white-listed" bytes: |
||
1971 | ; this stream either is empty or has tolerated ("gray-listed") bytes only. |
||
1972 | |||
1973 | mov eax,Z_BINARY |
||
1974 | .end_f: |
||
1975 | ret |
||
1976 | endp |
||
1977 | |||
1978 | ; =========================================================================== |
||
1979 | ; Reverse the first len bits of a code, using straightforward code (a faster |
||
1980 | ; method would use a table) |
||
1981 | ; IN assertion: 1 <= len <= 15 |
||
1982 | |||
1983 | ;unsigned (code, len) |
||
1984 | ; unsigned code ;the value to invert |
||
1985 | ; int len ;its bit length |
||
1986 | align 4 |
||
1987 | proc bi_reverse uses ebx, p1code:dword, len:dword |
||
1988 | ;zlib_debug 'bi_reverse' |
||
1989 | xor eax,eax |
||
1990 | @@: ;do |
||
1991 | mov ebx,[p1code] |
||
1992 | and ebx,1 |
||
1993 | or eax,ebx |
||
1994 | shr dword[p1code],1 |
||
1995 | shl eax,1 |
||
1996 | dec dword[len] |
||
1997 | cmp dword[len],0 |
||
1998 | jg @b ;while (..>..) |
||
1999 | shl eax,1 |
||
2000 | ret |
||
2001 | endp |
||
2002 | |||
2003 | ; =========================================================================== |
||
2004 | ; Flush the bit buffer, keeping at most 7 bits in it. |
||
2005 | |||
2006 | ;void (s) |
||
2007 | ; deflate_state* s |
||
2008 | align 4 |
||
2009 | proc bi_flush uses eax ecx edi, s:dword |
||
2010 | mov edi,[s] |
||
2011 | cmp dword[edi+deflate_state.bi_valid],16 |
||
2012 | jne @f ;if (..==..) |
||
2013 | mov cx,[edi+deflate_state.bi_buf] |
||
2014 | put_short edi,cx |
||
2015 | mov word[edi+deflate_state.bi_buf],0 |
||
2016 | mov dword[edi+deflate_state.bi_valid],0 |
||
2017 | jmp .end0 |
||
2018 | @@: ;else if (..>=..) |
||
2019 | cmp dword[edi+deflate_state.bi_valid],8 |
||
2020 | jl .end0 |
||
2021 | mov cl,byte[edi+deflate_state.bi_buf] |
||
2022 | put_byte edi,cl |
||
2023 | shr word[edi+deflate_state.bi_buf],8 |
||
2024 | sub dword[edi+deflate_state.bi_valid],8 |
||
2025 | .end0: |
||
2026 | ret |
||
2027 | endp |
||
2028 | |||
2029 | ; =========================================================================== |
||
2030 | ; Flush the bit buffer and align the output on a byte boundary |
||
2031 | |||
2032 | ;void (s) |
||
2033 | ; deflate_state* s |
||
2034 | align 4 |
||
2035 | proc bi_windup uses eax ecx edi, s:dword |
||
2036 | mov edi,[s] |
||
2037 | cmp dword[edi+deflate_state.bi_valid],8 |
||
2038 | jle @f ;if (..>..) |
||
2039 | mov cx,[edi+deflate_state.bi_buf] |
||
2040 | put_short edi, cx |
||
2041 | jmp .end0 |
||
2042 | @@: ;else if (..>0) |
||
2043 | cmp dword[edi+deflate_state.bi_valid],0 |
||
2044 | jle .end0 |
||
2045 | mov cl,byte[edi+deflate_state.bi_buf] |
||
2046 | put_byte edi, cl |
||
2047 | .end0: |
||
2048 | mov word[edi+deflate_state.bi_buf],0 |
||
2049 | mov dword[edi+deflate_state.bi_valid],0 |
||
2050 | if DEBUG eq 1 |
||
2051 | mov eax,[edi+deflate_state.bits_sent] |
||
2052 | add eax,7 |
||
2053 | and eax,not 7 |
||
2054 | mov [edi+deflate_state.bits_sent],eax |
||
2055 | end if |
||
2056 | ret |
||
2057 | endp |
||
2058 | |||
2059 | ; =========================================================================== |
||
2060 | ; Copy a stored block, storing first the length and its |
||
2061 | ; one's complement if requested. |
||
2062 | |||
2063 | ;void (s, buf, len, header) |
||
2064 | ; deflate_state* s |
||
2065 | ; charf *buf ;the input data |
||
2066 | ; unsigned len ;its length |
||
2067 | ; int header ;true if block header must be written |
||
2068 | align 4 |
||
2069 | proc copy_block uses eax ebx ecx edi esi, s:dword, buf:dword, len:dword, p4header:dword |
||
2070 | mov edi,[s] |
||
2071 | stdcall bi_windup,edi ;align on byte boundary |
||
2072 | |||
2073 | cmp dword[p4header],0 |
||
2074 | je @f ;if (..) |
||
2075 | mov ecx,[len] |
||
2076 | put_short edi, cx |
||
2077 | not cx |
||
2078 | put_short edi, cx |
||
2079 | if DEBUG eq 1 |
||
2080 | add dword[edi+deflate_state.bits_sent],2*16 |
||
2081 | end if |
||
2082 | @@: |
||
2083 | if DEBUG eq 1 |
||
2084 | mov ecx,[len] |
||
2085 | shl ecx,3 |
||
2086 | add [edi+deflate_state.bits_sent],ecx |
||
2087 | end if |
||
2088 | mov ecx,[len] |
||
2089 | mov esi,[buf] |
||
2090 | @@: ;while (len--) |
||
2091 | lodsb |
||
2092 | mov bl,al |
||
2093 | put_byte edi, bl |
||
2094 | loop @b |
||
2095 | ret |
||
2096 | endp=>=> |