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