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