Subversion Repositories Kolibri OS

Rev

Rev 6741 | Rev 6797 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6617 IgorA 1
; deflate.asm -- compress data using the deflation algorithm
2
; Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
3
; For conditions of distribution and use, see copyright notice in zlib.inc
4
 
5
;  ALGORITHM
6
 
7
;      The "deflation" process depends on being able to identify portions
8
;      of the input text which are identical to earlier input (within a
9
;      sliding window trailing behind the input currently being processed).
10
 
11
;      The most straightforward technique turns out to be the fastest for
12
;      most input files: try all possible matches and select the longest.
13
;      The key feature of this algorithm is that insertions into the string
14
;      dictionary are very simple and thus fast, and deletions are avoided
15
;      completely. Insertions are performed at each input character, whereas
16
;      string matches are performed only when the previous match ends. So it
17
;      is preferable to spend more time in matches to allow very fast string
18
;      insertions and avoid deletions. The matching algorithm for small
19
;      strings is inspired from that of Rabin & Karp. A brute force approach
20
;      is used to find longer strings when a small match has been found.
21
;      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
22
;      (by Leonid Broukhis).
23
;         A previous version of this file used a more sophisticated algorithm
24
;      (by Fiala and Greene) which is guaranteed to run in linear amortized
25
;      time, but has a larger average cost, uses more memory and is patented.
26
;      However the F&G algorithm may be faster for some highly redundant
27
;      files if the parameter max_chain_length (described below) is too large.
28
 
29
;  ACKNOWLEDGEMENTS
30
 
31
;      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
32
;      I found it in 'freeze' written by Leonid Broukhis.
33
;      Thanks to many people for bug reports and testing.
34
 
35
;  REFERENCES
36
 
37
;      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
38
;      Available in http://tools.ietf.org/html/rfc1951
39
 
40
;      A description of the Rabin and Karp algorithm is given in the book
41
;         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
42
 
43
;      Fiala,E.R., and Greene,D.H.
44
;         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
45
 
46
 
47
deflate_copyright db ' deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ',0
48
 
49
;  If you use the zlib library in a product, an acknowledgment is welcome
50
;  in the documentation of your product. If for some reason you cannot
51
;  include such an acknowledgment, I would appreciate that you keep this
52
;  copyright string in the executable of your product.
53
 
54
; ===========================================================================
55
;  Function prototypes.
56
 
57
;enum block_state
58
need_more   equ 1 ;block not completed, need more input or more output
59
block_done  equ 2 ;block flush performed
60
finish_started equ 3 ;finish started, need only more output at next deflate
61
finish_done equ 4 ;finish done, accept no more input or output
62
 
63
; ===========================================================================
64
; Local data
65
 
66
NIL equ 0
67
; Tail of hash chains
68
 
69
TOO_FAR equ 4096
70
; Matches of length 3 are discarded if their distance exceeds TOO_FAR
71
 
72
; Values for max_lazy_match, good_match and max_chain_length, depending on
73
; the desired pack level (0..9). The values given below have been tuned to
74
; exclude worst case performance for pathological files. Better values may be
75
; found for specific files.
76
 
77
struct config_s ;config
78
	good_length dw ? ;uint_16 ;reduce lazy search above this match length
79
	max_lazy    dw ? ;uint_16 ;do not perform lazy search above this match length
80
	nice_length dw ? ;uint_16 ;quit search above this match length
81
	max_chain   dw ? ;uint_16
82
	co_func     dd ? ;compress_func
83
ends
84
 
85
align 16
86
configuration_table:
87
	config_s  0,   0,   0,    0, deflate_stored  ;store only
88
	config_s  4,   4,   8,    4, deflate_fast ;max speed, no lazy matches
89
if FASTEST eq 0
90
	config_s  4,   5,  16,    8, deflate_fast
91
	config_s  4,   6,  32,   32, deflate_fast
92
	config_s  4,   4,  16,   16, deflate_slow ;lazy matches
93
	config_s  8,  16,  32,   32, deflate_slow
94
	config_s  8,  16, 128,  128, deflate_slow
95
	config_s  8,  32, 128,  256, deflate_slow
96
	config_s 32, 128, 258, 1024, deflate_slow
97
	config_s 32, 258, 258, 4096, deflate_slow ;max compression
98
end if
99
 
100
; Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
101
; For deflate_fast() (levels <= 3) good is ignored and lazy has a different
102
; meaning.
103
 
104
 
105
EQUAL equ 0
106
; result of memcmp for equal strings
107
 
108
; rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH
109
macro RANK f, reg
110
{
111
local .end0
112
	xor reg,reg
113
	cmp f,4
114
	jle .end0
115
		sub reg,9
116
	.end0:
117
	add reg,f
118
	add reg,f
119
}
120
 
121
; ===========================================================================
122
; Update a hash value with the given input byte
123
; IN  assertion: all calls to to UPDATE_HASH are made with consecutive
124
;    input characters, so that a running hash key can be computed from the
125
;    previous key instead of complete recalculation each time.
126
 
127
macro UPDATE_HASH s,h,c
128
{
129
push ebx ecx
130
	mov ebx,h
131
	mov ecx,[s+deflate_state.hash_shift]
132
	shl ebx,cl
133
	xor ebx,c
134
	and ebx,[s+deflate_state.hash_mask]
135
	mov h,ebx
136
pop ecx ebx
137
}
138
 
139
; ===========================================================================
140
; Insert string str in the dictionary and set match_head to the previous head
141
; of the hash chain (the most recent string with same hash key). Return
142
; the previous length of the hash chain.
143
; If this file is compiled with -DFASTEST, the compression level is forced
144
; to 1, and no hash chains are maintained.
145
; IN  assertion: all calls to to INSERT_STRING are made with consecutive
146
;    input characters and the first MIN_MATCH bytes of str are valid
147
;    (except for the last MIN_MATCH-1 bytes of the input file).
148
 
149
macro INSERT_STRING s, str, match_head
150
{
151
	mov eax,[s+deflate_state.window]
152
	add eax,str
153
	add eax,MIN_MATCH-1
154
	movzx eax,byte[eax]
155
	UPDATE_HASH s, [s+deflate_state.ins_h], eax
156
	mov eax,[s+deflate_state.ins_h]
157
	shl eax,2
158
	add eax,[s+deflate_state.head]
159
	mov eax,[eax]
160
	mov match_head,eax
161
if FASTEST eq 0
162
push ebx
163
	mov ebx,[s+deflate_state.w_mask]
164
	and ebx,str
165
	add ebx,[s+deflate_state.prev]
166
	mov byte[ebx],al
167
pop ebx
168
end if
169
	mov eax,[s+deflate_state.ins_h]
170
	shl eax,2
171
	add eax,[s+deflate_state.head]
172
	push str
173
	pop dword[eax]
174
}
175
 
176
; ===========================================================================
177
; Initialize the hash table (avoiding 64K overflow for 16 bit systems).
178
; prev[] will be initialized on the fly.
179
 
180
macro CLEAR_HASH s
181
{
182
	mov eax,[s+deflate_state.hash_size]
183
	dec eax
184
	shl eax,2
185
	add eax,[s+deflate_state.head]
186
	mov dword[eax],NIL
187
	mov eax,[s+deflate_state.hash_size]
188
	dec eax
189
	shl eax,2 ;sizeof(*s.head)
190
	stdcall zmemzero, [s+deflate_state.head], eax
191
}
192
 
193
align 4
194
proc deflateInit, strm:dword, level:dword
195
	stdcall deflateInit_, [strm], [level], ZLIB_VERSION, sizeof.z_stream
196
	ret
197
endp
198
 
199
; =========================================================================
200
;int (strm, level, version, stream_size)
6639 IgorA 201
;    z_streamp strm
202
;    int level
203
;    const char *version
204
;    int stream_size
6617 IgorA 205
align 4
206
proc deflateInit_, strm:dword, level:dword, version:dword, stream_size:dword
207
	stdcall deflateInit2_, [strm], [level], Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,\
208
			Z_DEFAULT_STRATEGY, [version], [stream_size]
209
	; To do: ignore strm->next_in if we use it as window
210
	ret
211
endp
212
 
213
align 4
214
proc deflateInit2, strm:dword, level:dword, method:dword, windowBits:dword, memLevel:dword, strategy:dword
215
	stdcall deflateInit2_, [strm],[level],[method],[windowBits],[memLevel],\
216
		[strategy], ZLIB_VERSION, sizeof.z_stream
217
	ret
218
endp
219
 
220
; =========================================================================
221
;int (strm, level, method, windowBits, memLevel, strategy,
222
;                  version, stream_size)
6639 IgorA 223
;    z_streamp strm
224
;    int  level
225
;    int  method
226
;    int  windowBits
227
;    int  memLevel
228
;    int  strategy
229
;    const char *version
230
;    int stream_size
6617 IgorA 231
align 4
232
proc deflateInit2_ uses ebx ecx edx edi, strm:dword, level:dword, method:dword,\
233
	windowBits:dword, memLevel:dword, strategy:dword, version:dword, stream_size:dword
234
locals
235
	wrap dd 1 ;int
236
	overlay dd ? ;uint_16p
237
endl
238
	; We overlay pending_buf and d_buf+l_buf. This works since the average
239
	; output size for (length,distance) codes is <= 24 bits.
240
 
241
	mov eax,[version]
242
	cmp eax,Z_NULL
243
	je @f
244
	mov ebx,dword[ZLIB_VERSION]
245
	cmp dword[eax],ebx
246
	jne @f
247
	cmp dword[stream_size],sizeof.z_stream
248
	je .end0
249
	@@: ;if (..==0 || ..[0]!=..[0] || ..!=..)
250
		mov eax,Z_VERSION_ERROR
251
		jmp .end_f
252
	.end0:
253
	mov ebx,[strm]
254
	cmp ebx,Z_NULL
255
	jne @f ;if (..==0) return ..
256
		mov eax,Z_STREAM_ERROR
257
		jmp .end_f
258
	@@:
259
 
260
	mov dword[ebx+z_stream.msg],Z_NULL
261
	cmp dword[ebx+z_stream.zalloc],0
262
	jne @f ;if (..==0)
263
if Z_SOLO eq 1
264
		mov eax,Z_STREAM_ERROR
265
		jmp .end_f
266
else
267
		mov dword[ebx+z_stream.zalloc],zcalloc
268
		mov dword[ebx+z_stream.opaque],0
269
end if
270
	@@:
271
	cmp dword[ebx+z_stream.zfree],0
272
	jne @f ;if (..==0)
273
if Z_SOLO eq 1
274
		mov eax,Z_STREAM_ERROR
275
		jmp .end_f
276
else
277
		mov dword[ebx+z_stream.zfree],zcfree
278
end if
279
	@@:
280
 
281
if FASTEST eq 1
282
	cmp dword[level],0
283
	je @f ;if (..!=0)
284
		mov dword[level],1
285
	@@:
286
else
287
	cmp dword[level],Z_DEFAULT_COMPRESSION
288
	jne @f ;if (..==0)
289
		mov dword[level],6
290
	@@:
291
end if
292
 
293
	cmp dword[windowBits],0
294
	jge @f ;if (..<0) ;suppress zlib wrapper
295
		mov dword[wrap],0
296
		neg dword[windowBits]
297
		inc dword[windowBits]
298
		jmp .end1
299
	@@:
300
if GZIP eq 1
301
	cmp dword[windowBits],15
302
	jle .end1 ;else if (..>15)
303
		mov dword[wrap],2 ;write gzip wrapper instead
304
		sub dword[windowBits],16
305
end if
306
	.end1:
307
	cmp dword[memLevel],1
308
	jl .end2
309
	cmp dword[memLevel],MAX_MEM_LEVEL
310
	jg .end2
311
	cmp dword[method],Z_DEFLATED
312
	jne .end2
313
	cmp dword[windowBits],8
314
	jl .end2
315
	cmp dword[windowBits],15
316
	jg .end2
317
	cmp dword[level],0
318
	jl .end2
319
	cmp dword[level],9
320
	jg .end2
321
	cmp dword[strategy],0
322
	jl .end2
323
	cmp dword[strategy],Z_FIXED
324
	jle @f
325
	.end2: ;if (..<.. || ..>.. || ..!=.. || ..<.. || ..>.. || ..<0 || ..>.. || ..<0 || ..>..)
326
		mov eax,Z_STREAM_ERROR
327
		jmp .end_f
328
	@@:
329
	cmp dword[windowBits],8
330
	jne @f ;if (..==..)
331
		inc dword[windowBits] ;until 256-byte window bug fixed
332
	@@:
333
	ZALLOC ebx, 1, sizeof.deflate_state
334
	;eax = s
335
	cmp eax,Z_NULL
336
	jne @f ;if (..==0)
337
		mov eax,Z_MEM_ERROR
338
		jmp .end_f
339
	@@:
340
	mov edi,eax ;edi = s
341
	mov [ebx+z_stream.state],edi
342
	mov [edi+deflate_state.strm],ebx
343
 
344
	mov eax,[wrap]
345
	mov [edi+deflate_state.wrap],eax
346
	mov [edi+deflate_state.gzhead],Z_NULL
347
	mov ecx,[windowBits]
348
	mov [edi+deflate_state.w_bits],ecx
349
	xor eax,eax
350
	inc eax
351
	shl eax,cl
352
	mov [edi+deflate_state.w_size],eax
353
	dec eax
354
	mov [edi+deflate_state.w_mask],eax
355
 
356
	mov ecx,[memLevel]
357
	add ecx,7
358
	mov [edi+deflate_state.hash_bits],ecx
359
	xor eax,eax
360
	inc eax
361
	shl eax,cl
362
	mov [edi+deflate_state.hash_size],eax
363
	dec eax
364
	mov [edi+deflate_state.hash_mask],eax
365
	add ecx,MIN_MATCH-1
366
	xor edx,edx
367
	mov eax,ecx
368
	mov ecx,MIN_MATCH
369
	div ecx
370
	mov [edi+deflate_state.hash_shift],eax
371
 
372
	ZALLOC ebx, [edi+deflate_state.w_size], 2 ;2*sizeof(Byte)
373
	mov [edi+deflate_state.window],eax
374
	ZALLOC ebx, [edi+deflate_state.w_size], 4 ;sizeof(Pos)
375
	mov [edi+deflate_state.prev],eax
376
	ZALLOC ebx, [edi+deflate_state.hash_size], 4 ;sizeof(Pos)
377
	mov [edi+deflate_state.head],eax
378
 
379
	mov dword[edi+deflate_state.high_water],0 ;nothing written to s->window yet
380
 
381
	mov ecx,[memLevel]
382
	add ecx,6
383
	xor eax,eax
384
	inc eax
385
	shl eax,cl
386
	mov [edi+deflate_state.lit_bufsize],eax ;16K elements by default
387
 
388
	ZALLOC ebx, eax, 4 ;sizeof(uint_16)+2
389
	mov [overlay],eax
390
	mov [edi+deflate_state.pending_buf],eax
391
	mov eax,[edi+deflate_state.lit_bufsize]
392
	imul eax,4 ;sizeof(uint_16)+2
393
	mov [edi+deflate_state.pending_buf_size],eax
394
 
395
	cmp dword[edi+deflate_state.window],Z_NULL
396
	je .end3
397
	cmp dword[edi+deflate_state.prev],Z_NULL
398
	je .end3
399
	cmp dword[edi+deflate_state.head],Z_NULL
400
	je .end3
401
	cmp dword[edi+deflate_state.pending_buf],Z_NULL
402
	je .end3
403
		jmp @f
404
	.end3: ;if (..==0 || ..==0 || ..==0 || ..==0)
405
		mov dword[edi+deflate_state.status],FINISH_STATE
406
		ERR_MSG Z_MEM_ERROR
407
		mov [ebx+z_stream.msg],eax
408
		stdcall deflateEnd, ebx
409
		mov eax,Z_MEM_ERROR
410
		jmp .end_f
411
	@@:
412
	mov eax,[edi+deflate_state.lit_bufsize]
413
	shr eax,1 ;/=sizeof(uint_16)
414
	add eax,[overlay]
415
	mov [edi+deflate_state.d_buf],eax
416
	mov eax,[edi+deflate_state.lit_bufsize]
417
	imul eax,3 ;1+sizeof(uint_16)
418
	add eax,[edi+deflate_state.pending_buf]
419
	mov [edi+deflate_state.l_buf],eax
420
 
421
	mov eax,[level]
422
	mov [edi+deflate_state.level],ax
423
	mov eax,[strategy]
424
	mov [edi+deflate_state.strategy],ax
425
	mov eax,[method]
426
	mov [edi+deflate_state.method],al
427
 
428
	stdcall deflateReset, ebx
429
.end_f:
430
zlib_debug 'deflateInit2_ strategy = %d',[strategy]
431
	ret
432
endp
433
 
434
; =========================================================================
435
;int (strm, dictionary, dictLength)
6639 IgorA 436
;    z_streamp strm
437
;    const Bytef *dictionary
438
;    uInt  dictLength
6617 IgorA 439
align 4
440
proc deflateSetDictionary uses ebx edi, strm:dword, dictionary:dword, dictLength:dword
441
locals
442
;    deflate_state *s;
443
;    uInt str, n;
444
	wrap dd ? ;int
445
	avail dd ? ;unsigned
446
;    z_const unsigned char *next;
447
endl
448
	mov ebx,[strm]
449
	cmp ebx,Z_NULL
450
	je @f
451
	mov edi,[ebx+z_stream.state]
452
	cmp edi,Z_NULL
453
	je @f
454
	cmp dword[dictionary],Z_NULL
455
	je @f ;if (..==0 || ..==0 || ..==0)
456
		jmp .end0
457
	@@:
458
		mov eax,Z_STREAM_ERROR
459
		jmp .end_f
460
	.end0:
461
 
462
	mov eax,[edi+deflate_state.wrap]
463
	mov [wrap],eax
464
;    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
465
;        return Z_STREAM_ERROR;
466
 
467
	; when using zlib wrappers, compute Adler-32 for provided dictionary
468
;    if (wrap == 1)
469
;        strm->adler = adler32(strm->adler, dictionary, dictLength);
470
;    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
471
 
472
	; if dictionary would fill window, just replace the history
473
;    if (dictLength >= s->w_size) {
474
;        if (wrap == 0) {            /* already empty otherwise */
475
;            CLEAR_HASH(s);
476
;            s->strstart = 0;
477
;            s->block_start = 0L;
478
;            s->insert = 0;
479
;        }
480
;        dictionary += dictLength - s->w_size;  /* use the tail */
481
;        dictLength = s->w_size;
482
;    }
483
 
484
	; insert dictionary into window and hash
485
;    avail = strm->avail_in;
486
;    next = strm->next_in;
487
;    strm->avail_in = dictLength;
488
;    strm->next_in = (z_const Bytef *)dictionary;
489
;    fill_window(s);
490
;    while (s->lookahead >= MIN_MATCH) {
491
;        str = s->strstart;
492
;        n = s->lookahead - (MIN_MATCH-1);
493
;        do {
494
;            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
495
if FASTEST eq 0
496
;            s->prev[str & s->w_mask] = s->head[s->ins_h];
497
end if
498
;            s->head[s->ins_h] = (Pos)str;
499
;            str++;
500
;        } while (--n);
501
;        s->strstart = str;
502
;        s->lookahead = MIN_MATCH-1;
503
;        fill_window(s);
504
;    }
505
;    s->strstart += s->lookahead;
506
;    s->block_start = (long)s->strstart;
507
;    s->insert = s->lookahead;
508
;    s->lookahead = 0;
509
;    s->match_length = s->prev_length = MIN_MATCH-1;
510
;    s->match_available = 0;
511
;    strm->next_in = next;
512
;    strm->avail_in = avail;
513
;    s->wrap = wrap;
514
	mov eax,Z_OK
515
.end_f:
516
	ret
517
endp
518
 
519
; =========================================================================
520
;int (strm)
6639 IgorA 521
;    z_streamp strm
6617 IgorA 522
align 4
523
proc deflateResetKeep uses ebx edi, strm:dword
524
;    deflate_state *s;
525
 
526
	mov ebx,[strm]
527
	cmp ebx,Z_NULL
528
	je @f
529
	mov edi,[ebx+z_stream.state]
530
	cmp edi,Z_NULL
531
	je @f
532
	cmp dword[ebx+z_stream.zalloc],0
533
	je @f
534
	cmp dword[ebx+z_stream.zfree],0
535
	je @f ;if (..==0 || ..==0 || ..==0 || ..==0)
536
		jmp .end0
537
	@@:
538
		mov eax,Z_STREAM_ERROR
539
		jmp .end_f
540
	.end0:
541
 
542
	mov dword[ebx+z_stream.total_out],0
543
	mov dword[ebx+z_stream.total_in],0
544
	mov dword[ebx+z_stream.msg],Z_NULL ;use zfree if we ever allocate msg dynamically
545
	mov word[ebx+z_stream.data_type],Z_UNKNOWN
546
 
6741 IgorA 547
	mov dword[edi+deflate_state.pending],0
6617 IgorA 548
	mov eax,[edi+deflate_state.pending_buf]
549
	mov [edi+deflate_state.pending_out],eax
550
 
551
	cmp dword[edi+deflate_state.wrap],0
552
	jge @f ;if (..<0)
553
		neg dword[edi+deflate_state.wrap]
554
		inc dword[edi+deflate_state.wrap] ;was made negative by deflate(..., Z_FINISH)
555
	@@:
556
	mov eax,BUSY_STATE
557
	cmp dword[edi+deflate_state.wrap],0
558
	je @f
559
		mov eax,INIT_STATE
560
	@@:
561
	mov dword[edi+deflate_state.status],eax
562
	stdcall adler32, 0, Z_NULL, 0
563
if GZIP eq 1
564
	cmp dword[edi+deflate_state.wrap],2
565
	jne @f
6639 IgorA 566
		xor eax,eax ;stdcall calc_crc32, 0, Z_NULL, 0
6617 IgorA 567
	@@:
568
end if
569
	mov dword[ebx+z_stream.adler],eax
570
	mov dword[edi+deflate_state.last_flush],Z_NO_FLUSH
571
 
572
	stdcall _tr_init, edi
573
 
574
	mov eax,Z_OK
575
.end_f:
576
	ret
577
endp
578
 
579
; =========================================================================
580
;int (strm)
6639 IgorA 581
;    z_streamp strm
6617 IgorA 582
align 4
583
proc deflateReset uses ebx, strm:dword
584
	mov ebx,[strm]
6639 IgorA 585
	zlib_debug 'deflateReset'
6617 IgorA 586
	stdcall deflateResetKeep, ebx
587
	cmp eax,0
588
	jne @f ;if (..==Z_OK)
589
		stdcall lm_init, [ebx+z_stream.state]
590
	@@:
591
	ret
592
endp
593
 
594
; =========================================================================
595
;int (strm, head)
6639 IgorA 596
;    z_streamp strm
597
;    gz_headerp head
6617 IgorA 598
align 4
599
proc deflateSetHeader uses ebx, strm:dword, head:dword
600
	mov ebx,[strm]
601
	cmp ebx,Z_NULL
602
	je @f
603
	mov ebx,[ebx+z_stream.state]
604
	cmp ebx,Z_NULL
605
	jne .end0
606
	@@: ;if (..==0 || ..==0) return ..
607
		mov eax,Z_STREAM_ERROR
608
		jmp .end_f
609
	.end0:
610
	cmp dword[ebx+deflate_state.wrap],2
611
	je @f ;if (..!=..) return ..
612
		mov eax,Z_STREAM_ERROR
613
		jmp .end_f
614
	@@:
615
	mov eax,[head]
616
	mov [ebx+deflate_state.gzhead],eax
617
	mov eax,Z_OK
618
.end_f:
619
	ret
620
endp
621
 
622
; =========================================================================
623
;int (strm, pending, bits)
6639 IgorA 624
;    unsigned *pending
625
;    int *bits
626
;    z_streamp strm
6617 IgorA 627
align 4
628
proc deflatePending uses ebx edi, strm:dword, pending:dword, bits:dword
629
	mov ebx,[strm]
630
	cmp ebx,Z_NULL
631
	je @f
632
	mov edi,[ebx+z_stream.state]
633
	cmp edi,Z_NULL
634
	jne .end0
635
	@@: ;if (..==0 || ..==0) return ..
636
		mov eax,Z_STREAM_ERROR
637
		jmp .end_f
638
	.end0:
639
	cmp dword[pending],Z_NULL
640
	je @f ;if (..!=..)
641
		mov eax,[pending]
6741 IgorA 642
		mov ebx,[edi+deflate_state.pending]
6617 IgorA 643
		mov [eax],ebx
644
	@@:
645
	cmp dword[bits],Z_NULL
646
	je @f ;if (..!=..)
647
		mov eax,[bits]
648
		mov ebx,[edi+deflate_state.bi_valid]
649
		mov [eax],ebx
650
	@@:
651
	mov eax,Z_OK
652
.end_f:
653
	ret
654
endp
655
 
656
; =========================================================================
657
;int (strm, bits, value)
6639 IgorA 658
;    z_streamp strm
659
;    int bits
660
;    int value
6617 IgorA 661
align 4
662
proc deflatePrime uses ebx edi, strm:dword, bits:dword, value:dword
663
;    int put;
664
 
665
	mov ebx,[strm]
666
	cmp ebx,Z_NULL
667
	je @f
668
	mov edi,[ebx+z_stream.state] ;s = strm.state
669
	cmp edi,Z_NULL
670
	jne .end0
671
	@@: ;if (..==0 || ..==0) return ..
672
		mov eax,Z_STREAM_ERROR
673
		jmp .end_f
674
	.end0:
675
;    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
676
;        return Z_BUF_ERROR;
677
;    do {
678
;        put = Buf_size - s->bi_valid;
679
;        if (put > bits)
680
;            put = bits;
681
;        s->bi_buf |= (uint_16)((value & ((1 << put) - 1)) << s->bi_valid);
682
;        s->bi_valid += put;
683
;        _tr_flush_bits(s);
684
;        value >>= put;
685
;        bits -= put;
686
;    } while (bits);
687
	mov eax,Z_OK
688
.end_f:
689
	ret
690
endp
691
 
692
; =========================================================================
693
;int (strm, level, strategy)
6639 IgorA 694
;    z_streamp strm
695
;    int level
696
;    int strategy
6617 IgorA 697
align 4
698
proc deflateParams uses ebx edi, strm:dword, level:dword, strategy:dword
699
;    compress_func func;
700
;    int err = Z_OK;
701
 
702
	mov ebx,[strm]
703
	cmp ebx,Z_NULL
704
	je @f
705
	mov edi,[ebx+z_stream.state] ;s = strm.state
706
	cmp edi,Z_NULL
707
	jne .end0
708
	@@: ;if (..==0 || ..==0) return ..
709
		mov eax,Z_STREAM_ERROR
710
		jmp .end_f
711
	.end0:
712
 
713
if FASTEST eq 1
714
	cmp dword[level],0
715
	je @f ;if (..!=0)
716
		mov dword[level],1
717
	@@:
718
else
719
	cmp dword[level],Z_DEFAULT_COMPRESSION
720
	jne @f ;if (..==0)
721
		mov dword[level],6
722
	@@:
723
end if
724
;    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
725
;        return Z_STREAM_ERROR;
726
;    }
727
;    func = configuration_table[s->level].func;
728
 
729
;    if ((strategy != s->strategy || func != configuration_table[level].func) &&
730
;        strm->total_in != 0) {
731
	; Flush the last buffer:
732
;        err = deflate(strm, Z_BLOCK);
733
;        if (err == Z_BUF_ERROR && s->pending == 0)
734
;            err = Z_OK;
735
;    }
736
;    if (s->level != level) {
737
;        s->level = level;
738
;        s->max_lazy_match   = configuration_table[level].max_lazy;
739
;        s->good_match       = configuration_table[level].good_length;
740
;        s->nice_match       = configuration_table[level].nice_length;
741
;        s->max_chain_length = configuration_table[level].max_chain;
742
;    }
743
;    s->strategy = strategy;
744
;    return err;
745
.end_f:
746
	ret
747
endp
748
 
749
; =========================================================================
750
;int (strm, good_length, max_lazy, nice_length, max_chain)
6639 IgorA 751
;    z_streamp strm
752
;    int good_length
753
;    int max_lazy
754
;    int nice_length
755
;    int max_chain
6617 IgorA 756
align 4
757
proc deflateTune uses ebx, strm:dword, good_length:dword, max_lazy:dword,\
758
			nice_length:dword, max_chain:dword
759
	mov ebx,[strm]
760
	cmp ebx,Z_NULL
761
	je @f
762
	cmp dword[ebx+z_stream.state],Z_NULL
763
	jne .end0
764
	@@: ;if (..==0 || ..==0) return ..
765
		mov eax,Z_STREAM_ERROR
766
		jmp .end_f
767
	.end0:
768
	mov ebx,[ebx+z_stream.state] ;s = strm.state
769
	mov eax,[good_length]
770
	mov [ebx+deflate_state.good_match],eax
771
	mov eax,[max_lazy]
772
	mov [ebx+deflate_state.max_lazy_match],eax
773
	mov eax,[nice_length]
774
	mov [ebx+deflate_state.nice_match],eax
775
	mov eax,[max_chain]
776
	mov [ebx+deflate_state.max_chain_length],eax
777
	mov eax,Z_OK
778
.end_f:
779
	ret
780
endp
781
 
782
; =========================================================================
783
; For the default windowBits of 15 and memLevel of 8, this function returns
784
; a close to exact, as well as small, upper bound on the compressed size.
785
; They are coded as constants here for a reason--if the #define's are
786
; changed, then this function needs to be changed as well.  The return
787
; value for 15 and 8 only works for those exact settings.
788
 
789
; For any setting other than those defaults for windowBits and memLevel,
790
; the value returned is a conservative worst case for the maximum expansion
791
; resulting from using fixed blocks instead of stored blocks, which deflate
792
; can emit on compressed data for some combinations of the parameters.
793
 
794
; This function could be more sophisticated to provide closer upper bounds for
795
; every combination of windowBits and memLevel.  But even the conservative
796
; upper bound of about 14% expansion does not seem onerous for output buffer
797
; allocation.
798
 
799
;uLong (strm, sourceLen)
6639 IgorA 800
;    z_streamp strm
801
;    uLong sourceLen
6617 IgorA 802
align 4
803
proc deflateBound, strm:dword, sourceLen:dword
804
;    deflate_state *s;
805
;    uLong complen, wraplen;
806
;    Bytef *str;
6639 IgorA 807
	zlib_debug 'deflateBound'
6617 IgorA 808
 
809
	; conservative upper bound for compressed data
810
;    complen = sourceLen +
811
;              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
812
 
813
	; if can't get parameters, return conservative bound plus zlib wrapper
814
;    if (strm == Z_NULL || strm->state == Z_NULL)
815
;        return complen + 6;
816
 
817
	; compute wrapper length
818
;    s = strm->state;
819
;    switch (s->wrap) {
820
;    case 0:                                 /* raw deflate */
821
;        wraplen = 0;
822
;        break;
823
;    case 1:                                 /* zlib wrapper */
824
;        wraplen = 6 + (s->strstart ? 4 : 0);
825
;        break;
826
;    case 2:                                 /* gzip wrapper */
827
;        wraplen = 18;
828
;        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
829
;            if (s->gzhead->extra != Z_NULL)
830
;                wraplen += 2 + s->gzhead->extra_len;
831
;            str = s->gzhead->name;
832
;            if (str != Z_NULL)
833
;                do {
834
;                    wraplen++;
835
;                } while (*str++);
836
;            str = s->gzhead->comment;
837
;            if (str != Z_NULL)
838
;                do {
839
;                    wraplen++;
840
;                } while (*str++);
841
;            if (s->gzhead->hcrc)
842
;                wraplen += 2;
843
;        }
844
;        break;
845
;    default:                                /* for compiler happiness */
846
;        wraplen = 6;
847
;    }
848
 
849
	; if not default parameters, return conservative bound
850
;    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
851
;        return complen + wraplen;
852
 
853
	; default settings: return tight bound for that case
854
;    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
855
;           (sourceLen >> 25) + 13 - 6 + wraplen;
856
.end_f:
857
	ret
858
endp
859
 
860
; =========================================================================
861
; Put a short in the pending buffer. The 16-bit value is put in MSB order.
862
; IN assertion: the stream state is correct and there is enough room in
863
; pending_buf.
864
 
865
;void (s, b)
6639 IgorA 866
;    deflate_state *s
867
;    uInt b
6617 IgorA 868
align 4
869
proc putShortMSB uses ebx ecx, s:dword, b:dword
870
	mov ebx,[s]
871
	mov ecx,[b]
872
	put_byte ebx, ch
873
	put_byte ebx, cl
874
	ret
875
endp
876
 
877
; =========================================================================
878
; Flush as much pending output as possible. All deflate() output goes
879
; through this function so some applications may wish to modify it
880
; to avoid allocating a large strm->next_out buffer and copying into it.
881
; (See also read_buf()).
882
 
883
;void (strm)
6639 IgorA 884
;    z_streamp strm
6617 IgorA 885
align 4
886
proc flush_pending uses eax ebx ecx edx, strm:dword
887
;ecx - len
888
;edx - deflate_state *s
889
;ebx - strm
6639 IgorA 890
	zlib_debug 'flush_pending'
6617 IgorA 891
	mov ebx,[strm]
892
	mov edx,[ebx+z_stream.state]
893
 
894
	stdcall _tr_flush_bits, edx
6741 IgorA 895
	mov ecx,[edx+deflate_state.pending]
6780 IgorA 896
	movzx eax,word[ebx+z_stream.avail_out]
897
	cmp ecx,eax
6617 IgorA 898
	jle @f ;if (..>..)
899
		movzx ecx,word[ebx+z_stream.avail_out]
900
	@@:
901
	cmp ecx,0
902
	je @f
903
 
904
	stdcall zmemcpy, [ebx+z_stream.next_out], [edx+deflate_state.pending_out], ecx
905
	add [ebx+z_stream.next_out],ecx
906
	add [edx+deflate_state.pending_out],ecx
907
	add [ebx+z_stream.total_out],ecx
908
	sub [ebx+z_stream.avail_out],cx
6741 IgorA 909
	sub [edx+deflate_state.pending],ecx
910
	cmp dword[edx+deflate_state.pending],0
6617 IgorA 911
	jne @f ;if (..==0)
912
		mov eax,[edx+deflate_state.pending_buf]
913
		mov [edx+deflate_state.pending_out],eax
914
	@@:
915
	ret
916
endp
917
 
918
; =========================================================================
919
;int (strm, flush)
6639 IgorA 920
;    z_streamp strm
921
;    int flush
6617 IgorA 922
align 4
923
proc deflate uses ebx ecx edx edi esi, strm:dword, flush:dword
924
locals
925
	old_flush dd ? ;int ;value of flush param for previous deflate call
926
	val dd ?
927
endl
928
	mov ebx,[strm]
929
zlib_debug 'deflate strm = %d',ebx
930
	cmp ebx,Z_NULL
931
	je @f
932
	mov edi,[ebx+z_stream.state] ;s = strm.state
933
	cmp edi,Z_NULL
934
	je @f
935
	cmp dword[flush],Z_BLOCK
936
	jg @f
937
	cmp dword[flush],0
6652 IgorA 938
	jge .end10 ;if (..==0 || ..==0 || ..>.. || ..<0)
6617 IgorA 939
	@@:
940
		mov eax,Z_STREAM_ERROR
941
		jmp .end_f
942
	.end10:
943
	cmp dword[ebx+z_stream.next_out],Z_NULL
944
	je .beg0
945
	cmp dword[ebx+z_stream.next_in],Z_NULL
946
	jne @f
6704 IgorA 947
	cmp dword[ebx+z_stream.avail_in],0
6617 IgorA 948
	jne .beg0
949
	@@:
950
	cmp dword[edi+deflate_state.status],FINISH_STATE
951
	jne .end0
952
	cmp dword[flush],Z_FINISH
953
	je .end0
6652 IgorA 954
	.beg0: ;if (..==0 || (..==0 && ..!=0) || (..==.. && ..!=..))
6617 IgorA 955
		ERR_RETURN ebx, Z_STREAM_ERROR
956
		jmp .end_f
957
	.end0:
958
	cmp word[ebx+z_stream.avail_out],0
959
	jne @f ;if (..==0)
960
		ERR_RETURN ebx, Z_BUF_ERROR
961
		jmp .end_f
962
	@@:
963
 
964
	mov dword[edi+deflate_state.strm],ebx ;just in case
965
	mov eax,[edi+deflate_state.last_flush]
966
	mov [old_flush],eax
967
	mov eax,[flush]
968
	mov [edi+deflate_state.last_flush],eax
969
 
970
	; Write the header
971
	cmp dword[edi+deflate_state.status],INIT_STATE
972
	jne .end2 ;if (..==..)
973
if GZIP eq 1
974
		cmp dword[edi+deflate_state.wrap],2
975
		jne .end1 ;if (..==..)
6639 IgorA 976
			xor eax,eax ;stdcall calc_crc32, 0, Z_NULL, 0
6617 IgorA 977
			mov [ebx+z_stream.adler],eax
978
			put_byte edi, 31
979
			put_byte edi, 139
980
			put_byte edi, 8
981
			cmp dword[edi+deflate_state.gzhead],Z_NULL
982
			jne .end3 ;if (..==0)
983
				put_byte edi, 0
984
				put_dword edi, 0
985
				xor cl,cl
986
				cmp word[edi+deflate_state.level],2
987
				jge @f
988
					mov cl,4
989
				@@:
990
				cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
991
				jl @f
992
					mov cl,4
993
				@@:
994
				cmp word[edi+deflate_state.level],9
995
				jne @f
996
					mov cl,2
997
				@@: ;..==.. ? 2 : (..>=.. || ..<.. ? 4 : 0)
998
				put_byte edi, cl
999
				put_byte edi, OS_CODE
1000
				mov dword[edi+deflate_state.status],BUSY_STATE
1001
				jmp .end2
1002
			.end3: ;else
1003
				mov edx,[edi+deflate_state.gzhead]
1004
				xor cl,cl
1005
				cmp [edx+gz_header.text],0
1006
				je @f
1007
					inc cl
1008
				@@:
1009
				cmp [edx+gz_header.hcrc],0
1010
				je @f
1011
					add cl,2
1012
				@@:
1013
				cmp [edx+gz_header.extra],Z_NULL
1014
				je @f
1015
					add cl,4
1016
				@@:
1017
				cmp [edx+gz_header.name],Z_NULL
1018
				je @f
1019
					add cl,8
1020
				@@:
1021
				cmp [edx+gz_header.comment],Z_NULL
1022
				je @f
1023
					add cl,16
1024
				@@:
1025
				put_byte edi, cl
1026
				mov ecx,[edx+gz_header.time]
1027
				put_dword edi, ecx
1028
				xor cl,cl
1029
				cmp word[edi+deflate_state.level],2
1030
				jge @f
1031
					mov cl,4
1032
				@@:
1033
				cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
1034
				jl @f
1035
					mov cl,4
1036
				@@:
1037
				cmp word[edi+deflate_state.level],9
1038
				jne @f
1039
					mov cl,2
1040
				@@: ;..==.. ? 2 : (..>=.. || ..<.. ? 4 : 0)
1041
				put_byte edi, cl
1042
				mov ecx,[edx+gz_header.os]
1043
				put_byte edi, cl
1044
				cmp dword[edx+gz_header.extra],Z_NULL
1045
				je @f ;if (..!=0)
1046
					mov ecx,[edx+gz_header.extra_len]
1047
					put_byte edi, cl
1048
					put_byte edi, ch
1049
				@@:
1050
				cmp dword[edx+gz_header.hcrc],0
1051
				je @f ;if (..)
1052
					stdcall calc_crc32, [ebx+z_stream.adler],\
6741 IgorA 1053
						[edi+deflate_state.pending_buf], [edi+deflate_state.pending]
6617 IgorA 1054
					mov [ebx+z_stream.adler],eax
1055
				@@:
1056
				mov dword[edi+deflate_state.gzindex],0
1057
				mov dword[edi+deflate_state.status],EXTRA_STATE
1058
			jmp .end2
1059
		.end1: ;else
1060
end if
1061
			mov edx,[edi+deflate_state.w_bits]
1062
			sub edx,8
1063
			shl edx,4
1064
			add edx,Z_DEFLATED
1065
			shl edx,8 ;edx = header
1066
			;esi = level_flags
1067
 
1068
			mov esi,3
1069
			cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
6652 IgorA 1070
			jge @f
6617 IgorA 1071
			cmp word[edi+deflate_state.level],2
6652 IgorA 1072
			jge .end30 ;if (..>=.. || ..<..)
1073
			@@:
6617 IgorA 1074
				xor esi,esi
1075
				jmp .end4
6652 IgorA 1076
			.end30:
6617 IgorA 1077
			cmp word[edi+deflate_state.level],6
1078
			jge @f ;else if (..<..)
1079
				mov esi,1
1080
				jmp .end4
1081
			@@:
1082
			;;cmp word[edi+deflate_state.level],6
1083
			jne .end4 ;else if (..==..)
1084
				mov esi,2
1085
			.end4:
1086
			shl esi,6
1087
			or edx,esi
1088
			cmp dword[edi+deflate_state.strstart],0
1089
			je @f ;if (..!=0)
1090
				or edx,PRESET_DICT
1091
			@@:
1092
			mov esi,edx
1093
			mov eax,edx
1094
			xor edx,edx
1095
			mov ecx,31
1096
			div ecx
1097
			add esi,31
1098
			sub esi,edx ;esi = header
1099
 
1100
			mov dword[edi+deflate_state.status],BUSY_STATE
1101
			stdcall putShortMSB, edi, esi
1102
 
1103
			; Save the adler32 of the preset dictionary:
1104
			cmp dword[edi+deflate_state.strstart],0
1105
			je @f ;if (..!=0)
1106
				mov ecx,[ebx+z_stream.adler]
1107
				bswap ecx
1108
				put_dword edi, ecx
1109
			@@:
6639 IgorA 1110
			xor eax,eax ;stdcall calc_crc32, 0, Z_NULL, 0
6617 IgorA 1111
			mov [ebx+z_stream.adler],eax
1112
	.end2:
1113
if GZIP eq 1
1114
	mov edx,[edi+deflate_state.gzhead]
1115
	cmp dword[edi+deflate_state.status],EXTRA_STATE
1116
	jne .end5 ;if (..==..)
1117
		cmp dword[edx+gz_header.extra],Z_NULL
1118
		je .end21 ;if (..!=..)
6741 IgorA 1119
			mov esi,[edi+deflate_state.pending]
6617 IgorA 1120
			;esi = beg ;start of bytes to update crc
1121
 
1122
			movzx ecx,word[edx+gz_header.extra_len]
1123
			.cycle0: ;while (..<..)
1124
			cmp dword[edi+deflate_state.gzindex],ecx
1125
			jge .cycle0end
6741 IgorA 1126
				mov eax,[edi+deflate_state.pending]
6617 IgorA 1127
				cmp eax,[edi+deflate_state.pending_buf_size]
1128
				jne .end24 ;if (..==..)
1129
					mov dword[edx+gz_header.hcrc],0
1130
					je @f
6741 IgorA 1131
					cmp [edi+deflate_state.pending],esi
6617 IgorA 1132
					jle @f ;if (.. && ..>..)
6741 IgorA 1133
						mov ecx,[edi+deflate_state.pending]
6617 IgorA 1134
						sub ecx,esi
1135
						mov eax,[edi+deflate_state.pending_buf]
1136
						add eax,esi
1137
						stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1138
						mov [ebx+z_stream.adler],eax
1139
					@@:
1140
					stdcall flush_pending, ebx
6741 IgorA 1141
					mov esi,[edi+deflate_state.pending]
6617 IgorA 1142
					cmp esi,[edi+deflate_state.pending_buf_size]
1143
					je .cycle0end ;if (..==..) break
1144
				.end24:
1145
				push ebx
1146
					mov ebx,[edi+deflate_state.gzindex]
1147
					add ebx,[edx+gz_header.extra]
1148
					mov bl,[ebx]
1149
					put_byte edi, bl
1150
				pop ebx
1151
				inc dword[edi+deflate_state.gzindex]
1152
				jmp .cycle0
1153
			.cycle0end:
1154
			mov dword[edx+gz_header.hcrc],0
1155
			je @f
6741 IgorA 1156
			cmp [edi+deflate_state.pending],esi
6617 IgorA 1157
			jle @f ;if (.. && ..>..)
6741 IgorA 1158
				mov ecx,[edi+deflate_state.pending]
6617 IgorA 1159
				sub ecx,esi
1160
				mov eax,[edi+deflate_state.pending_buf]
1161
				add eax,esi
1162
				stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1163
				mov [ebx+z_stream.adler],eax
1164
			@@:
1165
			mov eax,[edx+gz_header.extra_len]
1166
			cmp dword[edi+deflate_state.gzindex],eax
1167
			jne .end5 ;if (..==..)
1168
				mov dword[edi+deflate_state.gzindex],0
1169
				mov dword[edi+deflate_state.status],NAME_STATE
1170
			jmp .end5
1171
		.end21: ;else
1172
			mov dword[edi+deflate_state.status],NAME_STATE
1173
	.end5:
1174
	cmp dword[edi+deflate_state.status],NAME_STATE
1175
	jne .end6 ;if (..==..)
1176
		cmp dword[edx+gz_header.name],Z_NULL
1177
		je .end22 ;if (..!=..)
6741 IgorA 1178
			mov esi,[edi+deflate_state.pending]
6617 IgorA 1179
			;esi = beg ;start of bytes to update crc
1180
 
1181
			.cycle1: ;do
6741 IgorA 1182
				mov eax,[edi+deflate_state.pending]
6617 IgorA 1183
				cmp eax,[edi+deflate_state.pending_buf_size]
1184
				jne .end25 ;if (..==..)
1185
					mov dword[edx+gz_header.hcrc],0
1186
					je @f
6741 IgorA 1187
					cmp [edi+deflate_state.pending],esi
6617 IgorA 1188
					jle @f ;if (.. && ..>..)
6741 IgorA 1189
						mov ecx,[edi+deflate_state.pending]
6617 IgorA 1190
						sub ecx,esi
1191
						mov eax,[edi+deflate_state.pending_buf]
1192
						add eax,esi
1193
						stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1194
						mov [ebx+z_stream.adler],eax
1195
					@@:
1196
					stdcall flush_pending, ebx
6741 IgorA 1197
					mov esi,[edi+deflate_state.pending]
1198
					cmp esi,[edi+deflate_state.pending_buf_size]
6617 IgorA 1199
					jne .end25 ;if (..==..)
1200
						mov dword[val],1
1201
						jmp .cycle1end
1202
				.end25:
1203
				push ebx
1204
					mov ebx,[edi+deflate_state.gzindex]
1205
					add ebx,[edx+gz_header.name]
1206
					movzx ebx,byte[ebx]
1207
					mov [val],ebx
1208
					inc dword[edi+deflate_state.gzindex]
1209
					put_byte edi, bl
1210
				pop ebx
1211
				cmp dword[val],0
1212
				jne .cycle1 ;while (val != 0)
1213
			.cycle1end:
1214
			mov dword[edx+gz_header.hcrc],0
1215
			je @f
6741 IgorA 1216
			cmp [edi+deflate_state.pending],esi
6617 IgorA 1217
			jle @f ;if (.. && ..>..)
6741 IgorA 1218
				mov ecx,[edi+deflate_state.pending]
6617 IgorA 1219
				sub ecx,esi
1220
				mov eax,[edi+deflate_state.pending_buf]
1221
				add eax,esi
1222
				stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1223
				mov [ebx+z_stream.adler],eax
1224
			@@:
1225
			cmp dword[val],0
1226
			jne .end6 ;if (val == 0)
1227
				mov dword[edi+deflate_state.gzindex],0
1228
				mov dword[edi+deflate_state.status],COMMENT_STATE
1229
			jmp .end6
1230
		.end22: ;else
1231
			mov dword[edi+deflate_state.status],COMMENT_STATE;
1232
	.end6:
1233
	cmp dword[edi+deflate_state.status],COMMENT_STATE
1234
	jne .end7 ;if (..==..)
1235
		cmp dword[edx+gz_header.comment],Z_NULL
1236
		je .end23 ;if (..!=..)
6741 IgorA 1237
			mov esi,[edi+deflate_state.pending]
6617 IgorA 1238
			;esi = beg ;start of bytes to update crc
1239
 
1240
			.cycle2: ;do
6741 IgorA 1241
				mov eax,[edi+deflate_state.pending]
6617 IgorA 1242
				cmp eax,[edi+deflate_state.pending_buf_size]
1243
				jne .end26 ;if (..==..)
1244
					mov dword[edx+gz_header.hcrc],0
1245
					je @f
6741 IgorA 1246
					cmp [edi+deflate_state.pending],esi
6617 IgorA 1247
					jle @f ;if (.. && ..>..)
6741 IgorA 1248
						mov ecx,[edi+deflate_state.pending]
6617 IgorA 1249
						sub ecx,esi
1250
						mov eax,[edi+deflate_state.pending_buf]
1251
						add eax,esi
1252
						stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1253
						mov [ebx+z_stream.adler],eax
1254
					@@:
1255
					stdcall flush_pending, ebx
6741 IgorA 1256
					mov esi,[edi+deflate_state.pending]
1257
					cmp esi,[edi+deflate_state.pending_buf_size]
6617 IgorA 1258
					jne .end26 ;if (..==..)
1259
						mov dword[val],1
1260
						jmp .cycle2end
1261
				.end26:
1262
				push ebx
1263
					mov ebx,[edi+deflate_state.gzindex]
1264
					add ebx,[edx+gz_header.comment]
1265
					movzx ebx,byte[ebx]
1266
					mov [val],ebx
1267
					inc dword[edi+deflate_state.gzindex]
1268
					put_byte edi, bl
1269
				pop ebx
1270
				cmp dword[val],0
1271
				jne .cycle2 ;while (val != 0)
1272
			.cycle2end:
1273
			mov dword[edx+gz_header.hcrc],0
1274
			je @f
6741 IgorA 1275
			cmp [edi+deflate_state.pending],esi
6617 IgorA 1276
			jle @f ;if (.. && ..>..)
6741 IgorA 1277
				mov ecx,[edi+deflate_state.pending]
6617 IgorA 1278
				sub ecx,esi
1279
				mov eax,[edi+deflate_state.pending_buf]
1280
				add eax,esi
1281
				stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
1282
				mov [ebx+z_stream.adler],eax
1283
			@@:
1284
			cmp dword[val],0
1285
			jne .end7 ;if (val == 0)
1286
				mov dword[edi+deflate_state.status],HCRC_STATE
1287
			jmp .end7
1288
		.end23: ;else
1289
			mov dword[edi+deflate_state.status],HCRC_STATE
1290
	.end7:
1291
	cmp dword[edi+deflate_state.status],HCRC_STATE
1292
	jne .end8 ;if (..==..)
1293
		cmp dword[edx+gz_header.hcrc],0
1294
		je .end9 ;if (..)
6741 IgorA 1295
			mov ecx,[edi+deflate_state.pending]
6617 IgorA 1296
			add ecx,2
1297
			cmp ecx,[edi+deflate_state.pending_buf_size]
1298
			jle @f ;if (..>..)
1299
				stdcall flush_pending, ebx
1300
			@@:
6741 IgorA 1301
			mov ecx,[edi+deflate_state.pending]
6617 IgorA 1302
			add ecx,2
1303
			cmp ecx,[edi+deflate_state.pending_buf_size]
1304
			jg @f ;if (..<=..)
1305
				mov ecx,[ebx+z_stream.adler]
1306
				put_byte edi, cl
1307
				put_byte edi, ch
6639 IgorA 1308
				xor eax,eax ;stdcall calc_crc32, 0, Z_NULL, 0
6617 IgorA 1309
				mov [ebx+z_stream.adler],eax
1310
				mov dword[edi+deflate_state.status],BUSY_STATE
1311
			@@:
1312
			jmp .end8
1313
		.end9: ;else
1314
			mov dword[edi+deflate_state.status],BUSY_STATE
1315
	.end8:
1316
end if
1317
 
1318
	; Flush as much pending output as possible
6741 IgorA 1319
	cmp dword[edi+deflate_state.pending],0
6617 IgorA 1320
	je .end13 ;if (..!=0)
1321
		stdcall flush_pending, ebx
1322
		cmp word[ebx+z_stream.avail_out],0
1323
		jne @f ;if (..==0)
1324
			; Since avail_out is 0, deflate will be called again with
1325
			; more output space, but possibly with both pending and
1326
			; avail_in equal to zero. There won't be anything to do,
1327
			; but this is not an error situation so make sure we
1328
			; return OK instead of BUF_ERROR at next call of deflate:
1329
 
1330
			mov dword[edi+deflate_state.last_flush],-1
1331
			mov eax,Z_OK
1332
			jmp .end_f
1333
		@@:
1334
		; Make sure there is something to do and avoid duplicate consecutive
1335
		; flushes. For repeated and useless calls with Z_FINISH, we keep
1336
		; returning Z_STREAM_END instead of Z_BUF_ERROR.
1337
		jmp @f
1338
	.end13:
6704 IgorA 1339
	cmp dword[ebx+z_stream.avail_in],0
6617 IgorA 1340
	jne @f
1341
	RANK dword[old_flush],esi
1342
	RANK dword[flush],eax
1343
	cmp eax,esi
1344
	jg @f
1345
	cmp dword[flush],Z_FINISH
1346
	je @f ;else if (..==0 && ..<=.. && ..!=..)
1347
		ERR_RETURN ebx, Z_BUF_ERROR
1348
		jmp .end_f
1349
	@@:
1350
 
1351
	; User must not provide more input after the first FINISH:
1352
	cmp dword[edi+deflate_state.status],FINISH_STATE
1353
	jne @f
6704 IgorA 1354
	cmp dword[ebx+z_stream.avail_in],0
6617 IgorA 1355
	je @f ;if (..==.. && ..!=0)
1356
		ERR_RETURN ebx, Z_BUF_ERROR
1357
		jmp .end_f
1358
	@@:
1359
 
1360
	; Start a new block or continue the current one.
1361
 
6704 IgorA 1362
	cmp dword[ebx+z_stream.avail_in],0
6617 IgorA 1363
	jne @f
1364
	cmp dword[edi+deflate_state.lookahead],0
1365
	jne @f
1366
	cmp dword[flush],Z_NO_FLUSH
1367
	je .end11
1368
	cmp dword[edi+deflate_state.status],FINISH_STATE
1369
	je .end11
1370
	@@: ;if (..!=0 || ..!=0 || (..!=.. && ..!=..))
1371
		;edx = bstate
1372
		cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
1373
		jne @f
1374
			stdcall deflate_huff, edi, [flush]
1375
			jmp .end20
1376
		@@:
1377
		cmp word[edi+deflate_state.strategy],Z_RLE
1378
		jne @f
1379
			stdcall deflate_rle, edi, [flush]
1380
			jmp .end20
1381
		@@:
1382
		movzx eax,word[edi+deflate_state.level]
1383
		imul eax,sizeof.config_s
1384
		add eax,configuration_table+config_s.co_func
1385
		stdcall dword[eax], edi, [flush]
1386
		.end20:
1387
		mov edx,eax
1388
 
1389
		cmp edx,finish_started
1390
		je @f
1391
		cmp edx,finish_done
6652 IgorA 1392
		jne .end18
6617 IgorA 1393
		@@: ;if (..==.. || ..==..)
1394
			mov dword[edi+deflate_state.status],FINISH_STATE
1395
		.end18:
1396
		cmp edx,need_more
1397
		je @f
1398
		cmp edx,finish_started
6652 IgorA 1399
		jne .end19
6617 IgorA 1400
		@@: ;if (..==.. || ..==..)
1401
			cmp word[ebx+z_stream.avail_out],0
1402
			jne @f ;if (..==0)
1403
				mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR next call, see above
1404
			@@:
1405
			mov eax,Z_OK
1406
			jmp .end_f
1407
			; If flush != Z_NO_FLUSH && avail_out == 0, the next call
1408
			; of deflate should use the same flush parameter to make sure
1409
			; that the flush is complete. So we don't have to output an
1410
			; empty block here, this will be done at next call. This also
1411
			; ensures that for a very small output buffer, we emit at most
1412
			; one empty block.
1413
 
1414
		.end19:
1415
		cmp edx,block_done
1416
		jne .end11 ;if (..==..)
1417
			cmp dword[flush],Z_PARTIAL_FLUSH
1418
			jne @f ;if (..==..)
1419
				stdcall _tr_align, edi
1420
				jmp .end16
1421
			@@:
1422
			cmp dword[flush],Z_BLOCK
1423
			je .end16 ;else if (..!=..) ;FULL_FLUSH or SYNC_FLUSH
1424
				stdcall _tr_stored_block, edi, 0, 0, 0
1425
				; For a full flush, this empty block will be recognized
1426
				; as a special marker by inflate_sync().
1427
 
1428
			cmp dword[flush],Z_FULL_FLUSH
1429
			jne .end16 ;if (..==..)
1430
				CLEAR_HASH edi ;forget history
1431
				cmp dword[edi+deflate_state.lookahead],0
1432
				jne .end16 ;if (..==0)
1433
					mov dword[edi+deflate_state.strstart],0
1434
					mov dword[edi+deflate_state.block_start],0
1435
					mov dword[edi+deflate_state.insert],0
1436
		.end16:
1437
		stdcall flush_pending, ebx
1438
		cmp word[ebx+z_stream.avail_out],0
1439
		jne .end11 ;if (..==0)
1440
			mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR at next call, see above
1441
			mov eax,Z_OK
1442
			jmp .end_f
1443
	.end11:
1444
	cmp word[ebx+z_stream.avail_out],0
1445
	jg @f
6639 IgorA 1446
		zlib_assert 'bug2' ;Assert(..>0)
6617 IgorA 1447
	@@:
1448
 
1449
	cmp dword[flush],Z_FINISH
1450
	je @f ;if (..!=0)
1451
		mov eax,Z_OK
1452
		jmp .end_f
1453
	@@:
1454
	cmp dword[edi+deflate_state.wrap],0
1455
	jg @f ;if (..<=0)
1456
		mov eax,Z_STREAM_END
1457
		jmp .end_f
1458
	@@:
1459
 
1460
	; Write the trailer
1461
if GZIP eq 1
1462
	cmp dword[edi+deflate_state.wrap],2
1463
	jne @f ;if (..==..)
1464
		mov ecx,[ebx+z_stream.adler]
1465
		put_dword edi, ecx
1466
		mov ecx,[ebx+z_stream.total_in]
1467
		put_dword edi, ecx
1468
		jmp .end17
1469
	@@: ;else
1470
end if
1471
		mov ecx,[ebx+z_stream.adler]
1472
		bswap ecx
1473
		put_dword edi, ecx
1474
	.end17:
1475
	stdcall flush_pending, ebx
1476
	; If avail_out is zero, the application will call deflate again
1477
	; to flush the rest.
1478
 
6741 IgorA 1479
	cmp dword[edi+deflate_state.pending],0
6617 IgorA 1480
	jle @f ;if (..>0) ;write the trailer only once!
6741 IgorA 1481
		neg dword[edi+deflate_state.pending]
1482
		inc dword[edi+deflate_state.pending]
6617 IgorA 1483
	@@:
1484
	mov eax,Z_OK
6741 IgorA 1485
	cmp dword[edi+deflate_state.pending],0
6617 IgorA 1486
	je .end_f
1487
		mov eax,Z_STREAM_END
1488
.end_f:
1489
zlib_debug '  deflate.ret = %d',eax
1490
	ret
1491
endp
1492
 
1493
; =========================================================================
1494
;int (strm)
6639 IgorA 1495
;    z_streamp strm
6617 IgorA 1496
align 4
1497
proc deflateEnd uses ebx ecx edx, strm:dword
1498
	mov ebx,[strm]
1499
zlib_debug 'deflateEnd'
1500
	cmp ebx,Z_NULL
1501
	je @f
1502
	mov edx,[ebx+z_stream.state]
1503
	cmp edx,Z_NULL
1504
	jne .end0
1505
	@@: ;if (..==0 || ..==0) return ..
1506
		mov eax,Z_STREAM_ERROR
1507
		jmp .end_f
1508
	.end0:
1509
 
1510
	mov ecx,[edx+deflate_state.status]
1511
	cmp ecx,INIT_STATE
1512
	je @f
1513
	cmp ecx,EXTRA_STATE
1514
	je @f
1515
	cmp ecx,NAME_STATE
1516
	je @f
1517
	cmp ecx,COMMENT_STATE
1518
	je @f
1519
	cmp ecx,HCRC_STATE
1520
	je @f
1521
	cmp ecx,BUSY_STATE
1522
	je @f
1523
	cmp ecx,FINISH_STATE
1524
	je @f ;if (..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=..)
1525
		mov eax,Z_STREAM_ERROR
1526
		jmp .end_f
1527
	@@:
1528
 
1529
	; Deallocate in reverse order of allocations:
1530
	TRY_FREE ebx, dword[edx+deflate_state.pending_buf]
1531
	TRY_FREE ebx, dword[edx+deflate_state.head]
1532
	TRY_FREE ebx, dword[edx+deflate_state.prev]
1533
	TRY_FREE ebx, dword[edx+deflate_state.window]
1534
 
1535
	ZFREE ebx, dword[ebx+z_stream.state]
1536
	mov dword[ebx+z_stream.state],Z_NULL
1537
 
1538
	mov eax,Z_DATA_ERROR
1539
	cmp ecx,BUSY_STATE
1540
	je .end_f
1541
		mov eax,Z_OK
1542
.end_f:
1543
	ret
1544
endp
1545
 
1546
; =========================================================================
1547
; Copy the source state to the destination state.
1548
; To simplify the source, this is not supported for 16-bit MSDOS (which
1549
; doesn't have enough memory anyway to duplicate compression states).
1550
 
1551
;int (dest, source)
6639 IgorA 1552
;    z_streamp dest
1553
;    z_streamp source
6617 IgorA 1554
align 4
6639 IgorA 1555
proc deflateCopy uses ebx edx edi esi, dest:dword, source:dword
1556
;ebx = overlay ;uint_16p
1557
;edi = ds ;deflate_state*
1558
;esi = ss ;deflate_state*
6617 IgorA 1559
 
1560
	mov esi,[source]
1561
	cmp esi,Z_NULL
1562
	je @f
1563
	mov edx,[dest]
1564
	cmp edx,Z_NULL
1565
	je @f
1566
	mov esi,[esi+z_stream.state]
1567
	cmp esi,Z_NULL
1568
	jne .end0
1569
	@@: ;if (..==0 || ..==0 || ..==0)
1570
		mov eax,Z_STREAM_ERROR
1571
		jmp .end_f
1572
	.end0:
1573
 
1574
	stdcall zmemcpy, edx, [source], sizeof.z_stream
1575
 
1576
	ZALLOC edx, 1, sizeof.deflate_state
1577
	cmp eax,0
1578
	jne @f ;if (..==0) return ..
1579
		mov eax,Z_MEM_ERROR
1580
		jmp .end_f
1581
	@@:
1582
	mov edi,eax
1583
	mov [edx+z_stream.state],eax
1584
	stdcall zmemcpy, edi, esi, sizeof.deflate_state
1585
	mov dword[edi+deflate_state.strm],edx
1586
 
1587
	ZALLOC edx, [edi+deflate_state.w_size], 2 ;2*sizeof.db
1588
	mov dword[edi+deflate_state.window],eax
1589
	ZALLOC edx, [edi+deflate_state.w_size], 4 ;sizeof.dd
1590
	mov dword[edi+deflate_state.prev],eax
1591
	ZALLOC edx, [edi+deflate_state.hash_size], 4 ;sizeof.dd
1592
	mov dword[edi+deflate_state.head],eax
1593
	ZALLOC edx, [edi+deflate_state.lit_bufsize], 4 ;sizeof.dw+2
6639 IgorA 1594
	mov ebx,eax
6617 IgorA 1595
	mov dword[edi+deflate_state.pending_buf],eax
1596
 
1597
	cmp dword[edi+deflate_state.window],Z_NULL
1598
	je @f
1599
	cmp dword[edi+deflate_state.prev],Z_NULL
1600
	je @f
1601
	cmp dword[edi+deflate_state.head],Z_NULL
1602
	je @f
1603
	cmp dword[edi+deflate_state.pending_buf],Z_NULL
1604
	jne .end1
1605
	@@: ;if (..==0 || ..==0 || ..==0 || ..==0)
1606
		stdcall deflateEnd, edx
1607
		mov eax,Z_MEM_ERROR
1608
		jmp .end_f
1609
	.end1:
1610
 
1611
	; following zmemcpy do not work for 16-bit MSDOS
1612
	mov eax,[edi+deflate_state.w_size]
1613
	shl eax,1 ;*= 2*sizeof.db
1614
	stdcall zmemcpy, [edi+deflate_state.window], [esi+deflate_state.window], eax
6639 IgorA 1615
	mov eax,[edi+deflate_state.w_size]
1616
	shl eax,2 ;*= sizeof.dd
1617
	stdcall zmemcpy, [edi+deflate_state.prev], [esi+deflate_state.prev], eax
1618
	mov eax,[edi+deflate_state.hash_size]
1619
	shl eax,2 ;*= sizeof.dd
1620
	stdcall zmemcpy, [edi+deflate_state.head], [esi+deflate_state.head], eax
1621
	stdcall zmemcpy, [edi+deflate_state.pending_buf], [esi+deflate_state.pending_buf], [edi+deflate_state.pending_buf_size]
6617 IgorA 1622
 
6639 IgorA 1623
	mov eax,[edi+deflate_state.pending_buf]
1624
	add eax,[esi+deflate_state.pending_out]
1625
	sub eax,[esi+deflate_state.pending_buf]
1626
	mov [edi+deflate_state.pending_out],eax
1627
	mov eax,[edi+deflate_state.lit_bufsize]
1628
	shr eax,1 ;/=sizeof.uint_16
1629
	add eax,ebx
1630
	mov [edi+deflate_state.d_buf],eax
1631
	mov eax,[edi+deflate_state.lit_bufsize]
1632
	imul eax,3 ;*=1+sizeof.uint_16
1633
	add eax,[edi+deflate_state.pending_buf]
1634
	mov [edi+deflate_state.l_buf],eax
6617 IgorA 1635
 
1636
	mov eax,edi
1637
	add eax,deflate_state.dyn_ltree
1638
	mov [edi+deflate_state.l_desc.dyn_tree],eax
1639
	add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree
1640
	mov [edi+deflate_state.d_desc.dyn_tree],eax
1641
	add eax,deflate_state.bl_tree-deflate_state.dyn_dtree
1642
	mov [edi+deflate_state.bl_desc.dyn_tree],eax
1643
 
1644
	mov eax,Z_OK
1645
.end_f:
1646
	ret
1647
endp
1648
 
1649
; ===========================================================================
1650
; Read a new buffer from the current input stream, update the adler32
1651
; and total number of bytes read.  All deflate() input goes through
1652
; this function so some applications may wish to modify it to avoid
1653
; allocating a large strm->next_in buffer and copying from it.
1654
; (See also flush_pending()).
1655
 
1656
;int (strm, buf, size)
6639 IgorA 1657
;    z_streamp strm
1658
;    Bytef *buf
1659
;    unsigned size
6617 IgorA 1660
align 4
1661
proc read_buf uses ebx ecx, strm:dword, buf:dword, size:dword
1662
	mov ebx,[strm]
6704 IgorA 1663
	mov eax,[ebx+z_stream.avail_in]
6617 IgorA 1664
 
1665
	cmp eax,[size]
1666
	jle @f ;if (..>..)
1667
		mov eax,[size]
1668
	@@:
1669
	cmp eax,0
1670
	jg @f
1671
		xor eax,eax
1672
		jmp .end_f ;if (..==0) return 0
1673
	@@:
1674
 
6704 IgorA 1675
	sub [ebx+z_stream.avail_in],eax
6617 IgorA 1676
 
1677
	stdcall zmemcpy, [buf],[ebx+z_stream.next_in],eax
1678
	mov ecx,[ebx+z_stream.state]
1679
	cmp [ecx+deflate_state.wrap],1
1680
	jne @f ;if (..==..)
1681
		push eax
1682
		stdcall adler32, [ebx+z_stream.adler], [buf], eax
1683
		mov [ebx+z_stream.adler],eax
1684
		pop eax
1685
		jmp .end0
1686
	@@:
1687
if GZIP eq 1
1688
	cmp [ecx+deflate_state.wrap],2
1689
	jne .end0 ;else if (..==..)
1690
		push eax
1691
		stdcall calc_crc32, [ebx+z_stream.adler], [buf], eax
1692
		mov [ebx+z_stream.adler],eax
1693
		pop eax
1694
end if
1695
	.end0:
1696
	add [ebx+z_stream.next_in],eax
1697
	add [ebx+z_stream.total_in],eax
1698
 
1699
.end_f:
1700
;zlib_debug '  read_buf.ret = %d',eax
1701
	ret
1702
endp
1703
 
1704
; ===========================================================================
1705
; Initialize the "longest match" routines for a new zlib stream
1706
 
1707
;void (s)
1708
;    deflate_state *s
1709
align 4
1710
proc lm_init uses eax ebx edi, s:dword
1711
	mov edi,[s]
1712
	mov eax,[edi+deflate_state.w_size]
1713
	shl eax,1
1714
	mov [edi+deflate_state.window_size],eax
1715
 
1716
	CLEAR_HASH edi
1717
 
1718
	; Set the default configuration parameters:
1719
 
1720
	movzx eax,word[edi+deflate_state.level]
1721
	imul eax,sizeof.config_s
1722
	add eax,configuration_table
1723
	movzx ebx,word[eax+config_s.max_lazy]
1724
	mov [edi+deflate_state.max_lazy_match],ebx
1725
	movzx ebx,word[eax+config_s.good_length]
1726
	mov [edi+deflate_state.good_match],ebx
1727
	movzx ebx,word[eax+config_s.nice_length]
1728
	mov [edi+deflate_state.nice_match],ebx
1729
	movzx ebx,word[eax+config_s.max_chain]
1730
	mov [edi+deflate_state.max_chain_length],ebx
1731
 
1732
	mov dword[edi+deflate_state.strstart],0
1733
	mov dword[edi+deflate_state.block_start],0
1734
	mov dword[edi+deflate_state.lookahead],0
1735
	mov dword[edi+deflate_state.insert],0
1736
	mov dword[edi+deflate_state.prev_length],MIN_MATCH-1
1737
	mov dword[edi+deflate_state.match_length],MIN_MATCH-1
1738
	mov dword[edi+deflate_state.match_available],0
1739
	mov dword[edi+deflate_state.ins_h],0
1740
if FASTEST eq 0
1741
;if ASMV
1742
;    call match_init ;initialize the asm code
1743
;end if
1744
end if
1745
	ret
1746
endp
1747
 
1748
;uInt (s, cur_match)
6639 IgorA 1749
;    deflate_state *s
1750
;    IPos cur_match ;current match
6617 IgorA 1751
align 4
1752
proc longest_match uses ebx ecx edx edi esi, s:dword, cur_match:dword
1753
if FASTEST eq 0
1754
; ===========================================================================
1755
; Set match_start to the longest match starting at the given string and
1756
; return its length. Matches shorter or equal to prev_length are discarded,
1757
; in which case the result is equal to prev_length and match_start is
1758
; garbage.
1759
; IN assertions: cur_match is the head of the hash chain for the current
1760
;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
1761
; OUT assertion: the match length is not greater than s->lookahead.
1762
 
1763
;#ifndef ASMV
1764
; For 80x86 and 680x0, an optimized version will be provided in match.asm or
1765
; match.S. The code will be functionally equivalent.
1766
 
1767
;    unsigned chain_length = s->max_chain_length;/* max hash chain length */
1768
;    register Bytef *scan = s->window + s->strstart; /* current string */
1769
;    register Bytef *match;                       /* matched string */
1770
;    register int len;                           /* length of current match */
1771
;    int best_len = s->prev_length;              /* best match length so far */
1772
;    int nice_match = s->nice_match;             /* stop if match long enough */
1773
;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
1774
;        s->strstart - (IPos)MAX_DIST(s) : NIL;
1775
	; Stop when cur_match becomes <= limit. To simplify the code,
1776
	; we prevent matches with the string of window index 0.
1777
 
1778
;    Posf *prev = s->prev;
1779
;    uInt wmask = s->w_mask;
1780
 
1781
;    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
1782
;    register Byte scan_end1  = scan[best_len-1];
1783
;    register Byte scan_end   = scan[best_len];
1784
 
1785
	; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
1786
	; It is easy to get rid of this optimization if necessary.
1787
 
1788
;    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
1789
 
1790
	; Do not waste too much time if we already have a good match:
1791
;    if (s->prev_length >= s->good_match) {
1792
;        chain_length >>= 2;
1793
;    }
1794
	; Do not look for matches beyond the end of the input. This is necessary
1795
	; to make deflate deterministic.
1796
 
1797
;    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
1798
 
1799
;    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
1800
 
1801
;    do {
1802
;        Assert(cur_match < s->strstart, "no future");
1803
;        match = s->window + cur_match;
1804
 
1805
	; Skip to next match if the match length cannot increase
1806
	; or if the match length is less than 2.  Note that the checks below
1807
	; for insufficient lookahead only occur occasionally for performance
1808
	; reasons.  Therefore uninitialized memory will be accessed, and
1809
	; conditional jumps will be made that depend on those values.
1810
	; However the length of the match is limited to the lookahead, so
1811
	; the output of deflate is not affected by the uninitialized values.
1812
 
1813
;        if (match[best_len]   != scan_end  ||
1814
;            match[best_len-1] != scan_end1 ||
1815
;            *match            != *scan     ||
1816
;            *++match          != scan[1])      continue;
1817
 
1818
	; The check at best_len-1 can be removed because it will be made
1819
	; again later. (This heuristic is not always a win.)
1820
	; It is not necessary to compare scan[2] and match[2] since they
1821
	; are always equal when the other bytes match, given that
1822
	; the hash keys are equal and that HASH_BITS >= 8.
1823
 
1824
;        scan += 2, match++;
1825
;        Assert(*scan == *match, "match[2]?");
1826
 
1827
	; We check for insufficient lookahead only every 8th comparison;
1828
	; the 256th check will be made at strstart+258.
1829
 
1830
;        do {
1831
;        } while (*++scan == *++match && *++scan == *++match &&
1832
;                 *++scan == *++match && *++scan == *++match &&
1833
;                 *++scan == *++match && *++scan == *++match &&
1834
;                 *++scan == *++match && *++scan == *++match &&
1835
;                 scan < strend);
1836
 
1837
;        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
1838
 
1839
;        len = MAX_MATCH - (int)(strend - scan);
1840
;        scan = strend - MAX_MATCH;
1841
 
1842
;        if (len > best_len) {
1843
;            s->match_start = cur_match;
1844
;            best_len = len;
1845
;            if (len >= nice_match) break;
1846
;            scan_end1  = scan[best_len-1];
1847
;            scan_end   = scan[best_len];
1848
;        }
1849
;    } while ((cur_match = prev[cur_match & wmask]) > limit
1850
;             && --chain_length != 0);
1851
 
1852
;    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
1853
;    return s->lookahead;
1854
;end if /* ASMV */
1855
 
1856
else ;FASTEST
1857
 
1858
; ---------------------------------------------------------------------------
1859
; Optimized version for FASTEST only
1860
	mov edx,[s]
6639 IgorA 1861
	zlib_debug 'longest_match'
6617 IgorA 1862
 
1863
	; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
1864
	; It is easy to get rid of this optimization if necessary.
1865
 
1866
if MAX_MATCH <> 258
1867
	cmp dword[edx+deflate_state.hash_bits],8
1868
	jge @f
6639 IgorA 1869
		zlib_assert 'Code too clever' ;Assert(..>=.. && ..==..)
6617 IgorA 1870
	@@:
1871
end if
1872
	mov eax,[edx+deflate_state.window_size]
1873
	sub eax,MIN_LOOKAHEAD
1874
	cmp [edx+deflate_state.strstart],eax
1875
	jle @f
6639 IgorA 1876
		zlib_assert 'need lookahead' ;Assert(..<=..)
6617 IgorA 1877
	@@:
1878
	mov eax,[edx+deflate_state.strstart]
1879
	cmp [cur_match],eax
1880
	jl @f
6639 IgorA 1881
		zlib_assert 'no future' ;Assert(..<..)
6617 IgorA 1882
	@@:
1883
 
1884
	mov esi,[edx+deflate_state.window]
1885
	mov edi,esi
1886
	add esi,[cur_match]
1887
	add edi,[edx+deflate_state.strstart]
1888
	;edi = scan
1889
	;esi = match
1890
 
1891
	; Return failure if the match length is less than 2:
1892
 
1893
	lodsw
1894
	cmp ax,word[edi]
1895
	je @f ;if (word[edi] != word[esi]) return
1896
		mov eax,MIN_MATCH-1
1897
		jmp .end_f
1898
	@@:
1899
 
1900
	; The check at best_len-1 can be removed because it will be made
1901
	; again later. (This heuristic is not always a win.)
1902
	; It is not necessary to compare scan[2] and match[2] since they
1903
	; are always equal when the other bytes match, given that
1904
	; the hash keys are equal and that HASH_BITS >= 8.
1905
 
1906
	add edi,2
1907
	mov al,byte[edi]
1908
	cmp al,byte[esi]
1909
	je @f
6639 IgorA 1910
		zlib_assert 'match[2]?' ;Assert(..==..)
6617 IgorA 1911
	@@:
1912
 
1913
	; We check for insufficient lookahead only every 8th comparison;
1914
	; the 256th check will be made at strstart+258.
1915
 
1916
	mov ebx,edi
1917
	mov ecx,MAX_MATCH
1918
align 4
1919
	@@:
1920
		lodsb
1921
		scasb
1922
		loope @b
1923
 
1924
	mov eax,[edx+deflate_state.window_size]
1925
	dec eax
1926
	add eax,[edx+deflate_state.window]
1927
	cmp edi,eax
1928
	jle @f
6639 IgorA 1929
		zlib_assert 'wild scan' ;Assert(..<=..)
6617 IgorA 1930
	@@:
1931
	sub edi,ebx
1932
	;edi = len
1933
 
1934
	cmp edi,MIN_MATCH
1935
	jge @f ;if (..<..)
1936
		mov eax,MIN_MATCH-1
1937
		jmp .end_f
1938
	@@:
1939
	mov eax,[cur_match]
1940
	mov [edx+deflate_state.match_start],eax
1941
	mov eax,[edx+deflate_state.lookahead]
1942
	cmp edi,eax
1943
	jg @f ;if (len <= s.lookahead) ? len : s.lookahead
1944
		mov eax,edi
1945
	@@:
1946
end if ;FASTEST
1947
.end_f:
1948
;zlib_debug '  longest_match.ret = %d',eax
1949
	ret
1950
endp
1951
 
1952
 
1953
; ===========================================================================
1954
; Check that the match at match_start is indeed a match.
1955
 
1956
;void (s, start, match, length)
6639 IgorA 1957
;    deflate_state *s
1958
;    IPos start, match
1959
;    int length
6617 IgorA 1960
align 4
1961
proc check_match, s:dword, start:dword, p3match:dword, length:dword
1962
if DEBUG eq 1
1963
	; check that the match is indeed a match
1964
;    if (zmemcmp(s->window + match,
1965
;                s->window + start, length) != EQUAL) {
1966
;        fprintf(stderr, " start %u, match %u, length %d\n",
1967
;                start, match, length);
1968
;        do {
1969
;            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
1970
;        } while (--length != 0);
1971
;        z_error("invalid match");
1972
;    }
1973
;    if (z_verbose > 1) {
1974
;        fprintf(stderr,"\\[%d,%d]", start-match, length);
1975
;        do { putc(s->window[start++], stderr); } while (--length != 0);
1976
;    }
1977
end if ;DEBUG
1978
	ret
1979
endp
1980
 
1981
 
1982
; ===========================================================================
1983
; Fill the window when the lookahead becomes insufficient.
1984
; Updates strstart and lookahead.
1985
 
1986
; IN assertion: lookahead < MIN_LOOKAHEAD
1987
; OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
1988
;    At least one byte has been read, or avail_in == 0; reads are
1989
;    performed for at least two bytes (required for the zip translate_eol
1990
;    option -- not supported here).
1991
 
1992
;void (s)
1993
;    deflate_state *s
1994
align 4
1995
proc fill_window, s:dword
1996
pushad
1997
;esi = p, str, curr
1998
;ebx = more ;Amount of free space at the end of the window.
1999
	;Объем свободного пространства в конце окна.
2000
;ecx = wsize ;uInt
2001
;edx = s.strm
6639 IgorA 2002
	zlib_debug 'fill_window'
6617 IgorA 2003
	mov edi,[s]
2004
	cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2005
	jl @f
6639 IgorA 2006
		zlib_assert 'already enough lookahead' ;Assert(..<..)
6617 IgorA 2007
	@@:
2008
 
2009
	mov ecx,[edi+deflate_state.w_size]
2010
	mov edx,[edi+deflate_state.strm]
2011
	.cycle0: ;do
6639 IgorA 2012
	zlib_debug 'do'
6617 IgorA 2013
		mov ebx,[edi+deflate_state.window_size]
2014
		sub ebx,[edi+deflate_state.lookahead]
2015
		sub ebx,[edi+deflate_state.strstart]
2016
 
2017
		; If the window is almost full and there is insufficient lookahead,
2018
		; move the upper half to the lower one to make room in the upper half.
2019
 
2020
		MAX_DIST edi
2021
		add eax,ecx
2022
		cmp [edi+deflate_state.strstart],eax
2023
		jl .end0 ;if (..>=..)
2024
			push ecx
2025
			mov eax,[edi+deflate_state.window]
2026
			add eax,ecx
2027
			stdcall zmemcpy, [edi+deflate_state.window], eax
2028
			sub [edi+deflate_state.match_start],ecx
2029
			sub [edi+deflate_state.strstart],ecx ;we now have strstart >= MAX_DIST
2030
			sub [edi+deflate_state.block_start],ecx
2031
 
2032
			; Slide the hash table (could be avoided with 32 bit values
2033
			; at the expense of memory usage). We slide even when level == 0
2034
			; to keep the hash table consistent if we switch back to level > 0
2035
			; later. (Using level 0 permanently is not an optimal usage of
2036
			; zlib, so we don't care about this pathological case.)
2037
 
2038
			push ebx ecx
2039
			;ebx = wsize
2040
			;ecx = n
2041
			mov ebx,ecx
2042
			mov ecx,[edi+deflate_state.hash_size]
2043
			mov esi,ecx
2044
			shl esi,2
2045
			add esi,[edi+deflate_state.head]
2046
			.cycle1: ;do
2047
				sub esi,4
2048
				mov eax,[esi]
2049
				mov dword[esi],NIL
2050
				cmp eax,ebx
2051
				jl @f
2052
					sub eax,ebx
2053
					mov dword[esi],eax
2054
				@@:
2055
			loop .cycle1 ;while (..)
2056
 
2057
			mov ecx,ebx
2058
if FASTEST eq 0
2059
			mov esi,ecx
2060
			shl esi,2
2061
			add esi,[edi+deflate_state.prev]
2062
			.cycle2: ;do
2063
				sub esi,4
2064
				mov eax,[esi]
2065
				mov dword[esi],NIL
2066
				cmp eax,ebx
2067
				jl @f
2068
					sub eax,ebx
2069
					mov dword[esi],eax
2070
				@@:
2071
				; If n is not on any hash chain, prev[n] is garbage but
2072
				; its value will never be used.
2073
 
2074
			loop .cycle2 ;while (..)
2075
end if
2076
			pop ecx ebx
2077
			add ebx,ecx
2078
		.end0:
6704 IgorA 2079
		cmp dword[edx+z_stream.avail_in],0
6617 IgorA 2080
		je .cycle0end ;if (..==0) break
2081
 
2082
		; If there was no sliding:
2083
		;    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
2084
		;    more == window_size - lookahead - strstart
2085
		; => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
2086
		; => more >= window_size - 2*WSIZE + 2
2087
		; In the BIG_MEM or MMAP case (not yet supported),
2088
		;   window_size == input_size + MIN_LOOKAHEAD  &&
2089
		;   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
2090
		; Otherwise, window_size == 2*WSIZE so more >= 2.
2091
		; If there was sliding, more >= WSIZE. So in all cases, more >= 2.
2092
 
2093
		cmp ebx,2
2094
		jge @f
6639 IgorA 2095
			zlib_assert 'more < 2' ;Assert(..>=..)
6617 IgorA 2096
		@@:
2097
		mov eax,[edi+deflate_state.window]
2098
		add eax,[edi+deflate_state.strstart]
2099
		add eax,[edi+deflate_state.lookahead]
2100
		stdcall read_buf, edx, eax, ebx
2101
		add [edi+deflate_state.lookahead],eax
2102
 
2103
		; Initialize the hash value now that we have some input:
2104
		mov eax,[edi+deflate_state.lookahead]
2105
		add eax,[edi+deflate_state.insert]
2106
		cmp eax,MIN_MATCH
2107
		jl .end1 ;if (..>=..)
2108
			mov esi,[edi+deflate_state.strstart]
2109
			sub esi,[edi+deflate_state.insert]
2110
			;esi = str
2111
			mov eax,[edi+deflate_state.window]
2112
			add eax,esi
2113
			mov [edi+deflate_state.ins_h],eax
2114
			inc eax
2115
			movzx eax,byte[eax]
2116
            UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
2117
if MIN_MATCH <> 3
2118
;            Call UPDATE_HASH() MIN_MATCH-3 more times
2119
end if
2120
			.cycle3: ;while (..)
2121
			cmp dword[edi+deflate_state.insert],0
2122
			je .end1
2123
				mov eax,esi
2124
				add eax,MIN_MATCH-1
2125
				add eax,[edi+deflate_state.window]
2126
				movzx eax,byte[eax]
2127
				UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
2128
if FASTEST eq 0
2129
				mov eax,[edi+deflate_state.ins_h]
2130
				shl eax,2
2131
				add eax,[edi+deflate_state.head]
2132
				push ebx
2133
				mov ebx,[edi+deflate_state.w_mask]
2134
				and ebx,esi
2135
				shl ebx,2
2136
				add ebx,[edi+deflate_state.prev]
2137
				mov eax,[eax]
2138
				mov [ebx],eax
2139
				pop ebx
2140
end if
2141
				mov eax,[edi+deflate_state.ins_h]
2142
				shl eax,2
2143
				add eax,[edi+deflate_state.head]
2144
				mov [eax],esi
2145
				inc esi
2146
				dec dword[edi+deflate_state.insert]
2147
				mov eax,[edi+deflate_state.lookahead]
2148
				add eax,[edi+deflate_state.insert]
2149
				cmp eax,MIN_MATCH
2150
				jl .end1 ;if (..<..) break
2151
			jmp .cycle3
2152
		.end1:
2153
		; If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
2154
		; but this is not important since only literal bytes will be emitted.
2155
 
2156
		cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2157
		jge .cycle0end
6704 IgorA 2158
		cmp dword[edx+z_stream.avail_in],0
6617 IgorA 2159
		jne .cycle0
2160
	.cycle0end: ;while (..<.. && ..!=..)
2161
 
2162
	; If the WIN_INIT bytes after the end of the current data have never been
2163
	; written, then zero those bytes in order to avoid memory check reports of
2164
	; the use of uninitialized (or uninitialised as Julian writes) bytes by
2165
	; the longest match routines.  Update the high water mark for the next
2166
	; time through here.  WIN_INIT is set to MAX_MATCH since the longest match
2167
	; routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
2168
 
2169
	mov eax,[edi+deflate_state.window_size]
2170
	cmp [edi+deflate_state.high_water],eax
2171
	jge .end2 ;if (..<..)
2172
		mov esi,[edi+deflate_state.lookahead]
2173
		add esi,[edi+deflate_state.strstart]
2174
		;esi = curr
2175
 
2176
		cmp [edi+deflate_state.high_water],esi
2177
		jge .end3 ;if (..<..)
2178
			; Previous high water mark below current data -- zero WIN_INIT
2179
			; bytes or up to end of window, whichever is less.
2180
 
2181
			mov eax,[edi+deflate_state.window_size]
2182
			sub eax,esi
2183
			cmp eax,WIN_INIT
2184
			jle @f ;if (..>..)
2185
				mov eax,WIN_INIT
2186
			@@:
2187
			mov edx,[edi+deflate_state.window]
2188
			add edx,esi
2189
			stdcall zmemzero, edx, eax
2190
			add eax,esi
2191
			mov [edi+deflate_state.high_water],eax
2192
			jmp .end2
2193
		.end3: ;else if (..<..)
2194
		mov eax,esi
2195
		add eax,WIN_INIT
2196
		cmp [edi+deflate_state.high_water],eax
2197
		jge .end2
2198
			; High water mark at or above current data, but below current data
2199
			; plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
2200
			; to end of window, whichever is less.
2201
 
2202
			;eax = esi+WIN_INIT
2203
			sub eax,[edi+deflate_state.high_water]
2204
			mov edx,[edi+deflate_state.window_size]
2205
			sub edx,[edi+deflate_state.high_water]
2206
			cmp eax,edx ;if (..>..)
2207
			jle @f
2208
				mov eax,edx
2209
			@@:
2210
			mov edx,[edi+deflate_state.window]
2211
			add edx,[edi+deflate_state.high_water]
2212
			stdcall zmemzero, edx, eax
2213
			add [edi+deflate_state.high_water],eax
2214
	.end2:
2215
 
2216
	mov eax,[edi+deflate_state.window_size]
2217
	sub eax,MIN_LOOKAHEAD
2218
	cmp [edi+deflate_state.strstart],eax
2219
	jle @f
6639 IgorA 2220
		zlib_assert 'not enough room for search' ;Assert(..<=..)
6617 IgorA 2221
	@@:
2222
popad
2223
	ret
2224
endp
2225
 
2226
; ===========================================================================
2227
; Flush the current block, with given end-of-file flag.
2228
; IN assertion: strstart is set to the end of the current match.
2229
 
2230
macro FLUSH_BLOCK_ONLY s, last
2231
{
2232
local .end0
2233
	push dword last
2234
	mov eax,[s+deflate_state.strstart]
2235
	sub eax,[s+deflate_state.block_start]
2236
	push eax
2237
	xor eax,eax
2238
	cmp dword[s+deflate_state.block_start],0
2239
	jl .end0
2240
		mov eax,[s+deflate_state.block_start]
2241
		add eax,[s+deflate_state.window]
2242
	.end0:
2243
	stdcall _tr_flush_block, s, eax
2244
	mov eax,[s+deflate_state.strstart]
2245
	mov [s+deflate_state.block_start],eax
2246
	stdcall flush_pending, [s+deflate_state.strm]
2247
;   Tracev((stderr,"[FLUSH]"));
2248
}
2249
 
2250
; Same but force premature exit if necessary.
2251
macro FLUSH_BLOCK s, last
2252
{
2253
local .end0
2254
	FLUSH_BLOCK_ONLY s, last
2255
	mov eax,[s+deflate_state.strm]
2256
	cmp word[eax+z_stream.avail_out],0
2257
	jne .end0 ;if (..==0)
2258
if last eq 1
2259
		mov eax,finish_started
2260
else
2261
		mov eax,need_more
2262
end if
2263
		jmp .end_f
2264
	.end0:
2265
}
2266
 
2267
; ===========================================================================
2268
; Copy without compression as much as possible from the input stream, return
2269
; the current block state.
2270
; This function does not insert new strings in the dictionary since
2271
; uncompressible data is probably not useful. This function is used
2272
; only for the level=0 compression option.
2273
; NOTE: this function should be optimized to avoid extra copying from
2274
; window to pending_buf.
2275
 
2276
;block_state (s, flush)
6639 IgorA 2277
;    deflate_state *s
2278
;    int flush
6617 IgorA 2279
align 4
2280
proc deflate_stored uses ebx ecx edi, s:dword, flush:dword
2281
; Stored blocks are limited to 0xffff bytes, pending_buf is limited
2282
; to pending_buf_size, and each stored block has a 5 byte header:
2283
	mov edi,[s]
2284
zlib_debug 'deflate_stored'
2285
 
2286
	mov ecx,0xffff
2287
	mov eax,[edi+deflate_state.pending_buf_size]
2288
	sub eax,5
2289
	cmp ecx,eax
2290
	jle @f ;if (..>..)
2291
		mov ecx,eax
2292
	@@:
2293
	;ecx = max_block_size
2294
 
2295
	; Copy as much as possible from input to output:
2296
	.cycle0: ;for (;;) {
2297
		; Fill the window as much as possible:
2298
		cmp dword[edi+deflate_state.lookahead],1
2299
		jg .end0 ;if (..<=..)
2300
;            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
2301
;                   s->block_start >= (long)s->w_size, "slide too late");
2302
 
2303
			stdcall fill_window, edi
2304
			cmp dword[edi+deflate_state.lookahead],0
2305
			jne @f
2306
			cmp dword[flush],Z_NO_FLUSH
2307
			jne @f ;if (..==0 && ..==..)
2308
				mov eax,need_more
2309
				jmp .end_f
2310
			@@:
2311
			cmp dword[edi+deflate_state.lookahead],0
2312
			je .cycle0end ;if (..==0) break ;flush the current block
2313
		.end0:
2314
;        Assert(s->block_start >= 0, "block gone");
2315
 
2316
		mov eax,[edi+deflate_state.lookahead]
2317
		add [edi+deflate_state.strstart],eax
2318
		mov dword[edi+deflate_state.lookahead],0
2319
 
2320
		; Emit a stored block if pending_buf will be full:
2321
		mov ebx,[edi+deflate_state.block_start]
2322
		add ebx,ecx
2323
		cmp dword[edi+deflate_state.strstart],0
2324
		je @f
2325
		cmp [edi+deflate_state.strstart],ebx
2326
		jl .end1
2327
		@@: ;if (..==0 || ..>=..)
2328
			; strstart == 0 is possible when wraparound on 16-bit machine
2329
			mov eax,[edi+deflate_state.strstart]
2330
			sub eax,ebx
2331
			mov [edi+deflate_state.lookahead],eax
2332
			mov [edi+deflate_state.strstart],ebx
2333
			FLUSH_BLOCK edi, 0
2334
		.end1:
2335
		; Flush if we may have to slide, otherwise block_start may become
2336
		; negative and the data will be gone:
2337
 
2338
		MAX_DIST edi
2339
		mov ebx,[edi+deflate_state.strstart]
2340
		sub ebx,[edi+deflate_state.block_start]
2341
		cmp ebx,eax
2342
		jl .cycle0 ;if (..>=..)
2343
			FLUSH_BLOCK edi, 0
2344
		jmp .cycle0
2345
align 4
2346
	.cycle0end:
2347
	mov dword[edi+deflate_state.insert],0
2348
	cmp dword[flush],Z_FINISH
2349
	jne @f ;if (..==..)
2350
		FLUSH_BLOCK edi, 1
2351
		mov eax,finish_done
2352
		jmp .end_f
2353
	@@:
2354
	mov eax,[edi+deflate_state.block_start]
2355
	cmp [edi+deflate_state.strstart],eax
2356
	jle @f ;if (..>..)
2357
		FLUSH_BLOCK edi, 0
2358
	@@:
2359
	mov eax,block_done
2360
.end_f:
2361
	ret
2362
endp
2363
 
2364
; ===========================================================================
2365
; Compress as much as possible from the input stream, return the current
2366
; block state.
2367
; This function does not perform lazy evaluation of matches and inserts
2368
; new strings in the dictionary only for unmatched strings or for short
2369
; matches. It is used only for the fast compression options.
2370
 
2371
;block_state (s, flush)
2372
;    deflate_state *s
2373
;    int flush
2374
align 4
2375
proc deflate_fast uses ebx ecx edi, s:dword, flush:dword
2376
locals
2377
	bflush dd ? ;int  ;set if current block must be flushed
2378
endl
2379
;ecx = hash_head ;IPos ;head of the hash chain
2380
	mov edi,[s]
6652 IgorA 2381
	zlib_debug 'deflate_fast'
6617 IgorA 2382
 
2383
	.cycle0: ;for (..)
2384
	; Make sure that we always have enough lookahead, except
2385
	; at the end of the input file. We need MAX_MATCH bytes
2386
	; for the next match, plus MIN_MATCH bytes to insert the
2387
	; string following the next match.
2388
 
2389
		cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2390
		jge .end0 ;if (..<..)
2391
			stdcall fill_window, edi
2392
			cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2393
			jge @f ;if (..<.. && ..==..)
2394
			cmp dword[flush],Z_NO_FLUSH
2395
			jne @f
2396
				mov eax,need_more
2397
				jmp .end_f
2398
align 4
2399
			@@:
2400
			cmp dword[edi+deflate_state.lookahead],0
2401
			je .cycle0end ;if (..==0) break ;flush the current block
2402
align 4
2403
		.end0:
2404
 
2405
		; Insert the string window[strstart .. strstart+2] in the
2406
		; dictionary, and set hash_head to the head of the hash chain:
2407
 
2408
		mov ecx,NIL
2409
		cmp dword[edi+deflate_state.lookahead],MIN_MATCH
2410
		jl @f ;if (..>=..)
2411
			INSERT_STRING edi, [edi+deflate_state.strstart], ecx
2412
		@@:
2413
 
2414
		; Find the longest match, discarding those <= prev_length.
2415
		; At this point we have always match_length < MIN_MATCH
2416
 
2417
		cmp ecx,NIL
2418
		je @f
2419
		MAX_DIST edi
2420
		mov ebx,[edi+deflate_state.strstart]
2421
		sub ebx,ecx
2422
		cmp ebx,eax
2423
		jg @f ;if (..!=0 && ..<=..)
2424
			; To simplify the code, we prevent matches with the string
2425
			; of window index 0 (in particular we have to avoid a match
2426
			; of the string with itself at the start of the input file).
2427
 
2428
			stdcall longest_match, edi, ecx
2429
			mov [edi+deflate_state.match_length],eax
2430
			; longest_match() sets match_start
2431
		@@:
2432
		cmp dword[edi+deflate_state.match_length],MIN_MATCH
2433
		jl .end1 ;if (..>=..)
2434
			stdcall check_match, edi, [edi+deflate_state.strstart], [edi+deflate_state.match_start], [edi+deflate_state.match_length]
2435
 
2436
			mov eax,[edi+deflate_state.strstart]
2437
			sub eax,[edi+deflate_state.match_start]
2438
			mov ebx,[edi+deflate_state.match_length]
2439
			sub ebx,MIN_MATCH
2440
			_tr_tally_dist edi, eax, ebx, [bflush]
2441
 
2442
			mov eax,[edi+deflate_state.match_length]
2443
			sub [edi+deflate_state.lookahead],eax
2444
 
2445
			; Insert new strings in the hash table only if the match length
2446
			; is not too large. This saves time but degrades compression.
2447
 
2448
if FASTEST eq 0
2449
			;;mov eax,[edi+deflate_state.match_length]
2450
			cmp eax,[edi+deflate_state.max_insert_length]
2451
			jg .end3
2452
			cmp dword[edi+deflate_state.lookahead],MIN_MATCH
2453
			jl .end3 ;if (..<=.. && ..>=..)
2454
				dec dword[edi+deflate_state.match_length] ;string at strstart already in table
2455
				.cycle1: ;do {
2456
					inc dword[edi+deflate_state.strstart]
2457
					INSERT_STRING edi, [edi+deflate_state.strstart], ecx
2458
					; strstart never exceeds WSIZE-MAX_MATCH, so there are
2459
					; always MIN_MATCH bytes ahead.
2460
 
2461
					dec dword[edi+deflate_state.match_length]
2462
					cmp dword[edi+deflate_state.match_length],0
2463
					jne .cycle1 ;while (..!=0)
2464
				inc dword[edi+deflate_state.strstart]
2465
				jmp .end2
2466
			.end3: ;else
2467
end if
2468
 
2469
				mov eax,[edi+deflate_state.match_length]
2470
				add [edi+deflate_state.strstart],eax
2471
				mov dword[edi+deflate_state.match_length],0
2472
				mov eax,[edi+deflate_state.window]
2473
				add eax,[edi+deflate_state.strstart]
2474
				mov [edi+deflate_state.ins_h],eax
2475
				inc eax
2476
				movzx eax,byte[eax]
2477
				UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
2478
if MIN_MATCH <> 3
2479
;                Call UPDATE_HASH() MIN_MATCH-3 more times
2480
end if
2481
				; If lookahead < MIN_MATCH, ins_h is garbage, but it does not
2482
				; matter since it will be recomputed at next deflate call.
2483
			jmp .end2
2484
		.end1: ;else
2485
			; No match, output a literal byte
2486
			mov eax,[edi+deflate_state.window]
2487
			add eax,[edi+deflate_state.strstart]
2488
			movzx eax,byte[eax]
2489
			Tracevv eax,
2490
			_tr_tally_lit edi, eax, [bflush]
2491
			dec dword[edi+deflate_state.lookahead]
2492
			inc dword[edi+deflate_state.strstart]
2493
		.end2:
2494
		cmp dword[bflush],0
2495
		je .cycle0 ;if (..)
2496
			FLUSH_BLOCK edi, 0
2497
		jmp .cycle0
2498
align 4
2499
	.cycle0end:
2500
	mov eax,[edi+deflate_state.strstart]
2501
	cmp eax,MIN_MATCH-1
2502
	jl @f
2503
		mov eax,MIN_MATCH-1
2504
	@@:
2505
	mov [edi+deflate_state.insert],eax
2506
	cmp dword[flush],Z_FINISH
2507
	jne @f ;if (..==..)
2508
		FLUSH_BLOCK edi, 1
2509
		mov eax,finish_done
2510
		jmp .end_f
2511
	@@:
2512
	cmp dword[edi+deflate_state.last_lit],0
2513
	je @f ;if (..)
2514
		FLUSH_BLOCK edi, 0
2515
	@@:
2516
	mov eax,block_done
2517
.end_f:
2518
	ret
2519
endp
2520
 
2521
; ===========================================================================
2522
; Same as above, but achieves better compression. We use a lazy
2523
; evaluation for matches: a match is finally adopted only if there is
2524
; no better match at the next window position.
2525
 
2526
;block_state (s, flush)
2527
;    deflate_state *s
2528
;    int flush
2529
align 4
2530
proc deflate_slow uses ebx ecx edx edi, s:dword, flush:dword
2531
locals
2532
	bflush dd ? ;int  ;set if current block must be flushed
2533
endl
2534
;ecx = hash_head ;IPos ;head of the hash chain
2535
	mov edi,[s]
6652 IgorA 2536
	zlib_debug 'deflate_slow'
6617 IgorA 2537
 
2538
	; Process the input block.
2539
	.cycle0: ;for (;;)
2540
	; Make sure that we always have enough lookahead, except
2541
	; at the end of the input file. We need MAX_MATCH bytes
2542
	; for the next match, plus MIN_MATCH bytes to insert the
2543
	; string following the next match.
2544
 
2545
		cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2546
		jge .end0 ;if (..<..)
2547
			stdcall fill_window, edi
2548
			cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
2549
			jge @f ;if (..<.. && ..==..)
2550
			cmp dword[flush],Z_NO_FLUSH
2551
			jne @f
2552
				mov eax,need_more
2553
				jmp .end_f
2554
align 4
2555
			@@:
2556
			cmp dword[edi+deflate_state.lookahead],0
2557
			je .cycle0end ;if (..==0) break ;flush the current block
2558
align 4
2559
		.end0:
2560
 
2561
		; Insert the string window[strstart .. strstart+2] in the
2562
		; dictionary, and set hash_head to the head of the hash chain:
2563
 
2564
		mov ecx,NIL
2565
		cmp dword[edi+deflate_state.lookahead],MIN_MATCH
2566
		jl @f ;if (..>=..)
2567
			INSERT_STRING edi, [edi+deflate_state.strstart], ecx
2568
		@@:
2569
 
2570
		; Find the longest match, discarding those <= prev_length.
2571
 
2572
		mov eax,[edi+deflate_state.match_length]
2573
		mov [edi+deflate_state.prev_length],eax
2574
		mov eax,[edi+deflate_state.match_start]
2575
		mov [edi+deflate_state.prev_match],eax
2576
		mov dword[edi+deflate_state.match_length],MIN_MATCH-1
2577
 
2578
		cmp ecx,NIL
2579
		je @f
2580
		mov eax,[edi+deflate_state.prev_length]
2581
		cmp eax,[edi+deflate_state.max_lazy_match]
2582
		jge @f
2583
		MAX_DIST edi
2584
		mov ebx,[edi+deflate_state.strstart]
2585
		sub ebx,ecx
2586
		cmp ebx,eax
2587
		jg .end1 ;if (..!=0 && ..<.. && ..<=..)
2588
			; To simplify the code, we prevent matches with the string
2589
			; of window index 0 (in particular we have to avoid a match
2590
			; of the string with itself at the start of the input file).
2591
 
2592
			stdcall longest_match, edi, ecx
2593
			mov [edi+deflate_state.match_length],eax
2594
			; longest_match() sets match_start
2595
 
2596
			cmp dword[edi+deflate_state.match_length],5
2597
			jg .end1
2598
			cmp word[edi+deflate_state.strategy],Z_FILTERED
2599
			jne .end1
2600
;            if (..<=.. && (..==..
2601
;#if TOO_FAR <= 32767
2602
;                || (s->match_length == MIN_MATCH &&
2603
;                    s->strstart - s->match_start > TOO_FAR)
2604
;end if
2605
;                ))
2606
 
2607
				; If prev_match is also MIN_MATCH, match_start is garbage
2608
				; but we will ignore the current match anyway.
2609
 
2610
				mov dword[edi+deflate_state.match_length],MIN_MATCH-1
2611
		.end1:
2612
		; If there was a match at the previous step and the current
2613
		; match is not better, output the previous match:
2614
 
2615
 
2616
		mov eax,[edi+deflate_state.prev_length]
2617
		cmp eax,MIN_MATCH
2618
		jl .end2:
2619
		cmp [edi+deflate_state.match_length],eax
2620
		jg .end2: ;if (..>=.. && ..<=..)
2621
			mov edx,[edi+deflate_state.strstart]
2622
			add edx,[edi+deflate_state.lookahead]
2623
			sub edx,MIN_MATCH
2624
			;edx = max_insert
2625
			; Do not insert strings in hash table beyond this.
2626
 
2627
			mov eax,[edi+deflate_state.strstart]
2628
			dec eax
2629
			stdcall check_match, edi, eax, [edi+deflate_state.prev_match], [edi+deflate_state.prev_length]
2630
 
2631
			mov eax,[edi+deflate_state.strstart]
2632
			dec eax
2633
			sub eax,[edi+deflate_state.prev_match]
2634
			mov ebx,[edi+deflate_state.prev_length]
2635
			sub ebx,MIN_MATCH
2636
			_tr_tally_dist edi, eax, ebx, [bflush]
2637
 
2638
			; Insert in hash table all strings up to the end of the match.
2639
			; strstart-1 and strstart are already inserted. If there is not
2640
			; enough lookahead, the last two strings are not inserted in
2641
			; the hash table.
2642
 
2643
			mov eax,[edi+deflate_state.prev_length]
2644
			dec eax
2645
			sub [edi+deflate_state.lookahead],eax
2646
			sub dword[edi+deflate_state.prev_length],2
2647
			.cycle1: ;do
2648
				inc dword[edi+deflate_state.strstart]
2649
				cmp [edi+deflate_state.strstart],edx
2650
				jg @f ;if (..<=..)
2651
					INSERT_STRING edi, [edi+deflate_state.strstart], ecx
2652
				@@:
2653
				dec dword[edi+deflate_state.prev_length]
2654
				cmp dword[edi+deflate_state.prev_length],0
2655
				jne .cycle1 ;while (..!=0)
2656
			mov dword[edi+deflate_state.match_available],0
2657
			mov dword[edi+deflate_state.match_length],MIN_MATCH-1
2658
			inc dword[edi+deflate_state.strstart]
2659
 
2660
			cmp dword[bflush],0
2661
			je .cycle0 ;if (..)
2662
				FLUSH_BLOCK edi, 0
2663
			jmp .cycle0
2664
		.end2: ;else if (..)
2665
		cmp dword[edi+deflate_state.match_available],0
2666
		je .end3
2667
			; If there was no match at the previous position, output a
2668
			; single literal. If there was a match but the current match
2669
			; is longer, truncate the previous match to a single literal.
2670
 
2671
			mov eax,[edi+deflate_state.strstart]
2672
			dec eax
2673
			add eax,[edi+deflate_state.window]
2674
			movzx eax,byte[eax]
2675
			Tracevv eax,
2676
			_tr_tally_lit edi, eax, [bflush]
2677
			cmp dword[bflush],0
2678
			je @f ;if (..)
2679
				FLUSH_BLOCK_ONLY edi, 0
2680
			@@:
2681
			inc dword[edi+deflate_state.strstart]
2682
			dec dword[edi+deflate_state.lookahead]
2683
			mov eax,[edi+deflate_state.strm]
2684
			cmp word[eax+z_stream.avail_out],0
2685
			jne .cycle0 ;if (..==0) return ..
2686
				mov eax,need_more
2687
				jmp .end_f
2688
			jmp .cycle0 ;.end4
2689
		.end3: ;else
2690
			; There is no previous match to compare with, wait for
2691
			; the next step to decide.
2692
 
2693
			mov dword[edi+deflate_state.match_available],1
2694
			inc dword[edi+deflate_state.strstart]
2695
			dec dword[edi+deflate_state.lookahead]
2696
		;.end4:
2697
		jmp .cycle0
2698
	.cycle0end:
2699
	cmp dword[flush],Z_NO_FLUSH
2700
	jne @f
6639 IgorA 2701
		zlib_assert 'no flush?' ;Assert (..!=..)
6617 IgorA 2702
	@@:
2703
	cmp dword[edi+deflate_state.match_available],0
2704
	je @f ;if (..)
2705
		mov eax,[edi+deflate_state.strstart]
2706
		dec eax
2707
		add eax,[edi+deflate_state.window]
2708
		movzx eax,byte[eax]
2709
		Tracevv eax,
2710
		_tr_tally_lit edi, eax, [bflush]
2711
		mov dword[edi+deflate_state.match_available],0
2712
	@@:
2713
	mov eax,[edi+deflate_state.strstart]
2714
	cmp eax,MIN_MATCH-1
2715
	jl @f
2716
		mov eax,MIN_MATCH-1
2717
	@@:
2718
	mov [edi+deflate_state.insert],eax
2719
	cmp dword[flush],Z_FINISH
2720
	jne @f ;if (..==..)
2721
		FLUSH_BLOCK edi, 1
2722
		mov eax,finish_done
2723
		jmp .end_f
2724
	@@:
2725
	cmp dword[edi+deflate_state.last_lit],0
2726
	je @f ;if (..)
2727
		FLUSH_BLOCK edi, 0
2728
	@@:
2729
	mov eax,block_done
2730
.end_f:
2731
	ret
2732
endp
2733
 
2734
; ===========================================================================
2735
; For Z_RLE, simply look for runs of bytes, generate matches only of distance
2736
; one.  Do not maintain a hash table.  (It will be regenerated if this run of
2737
; deflate switches away from Z_RLE.)
2738
 
2739
;block_state (s, flush)
6639 IgorA 2740
;    deflate_state *s
2741
;    int flush
6617 IgorA 2742
align 4
2743
proc deflate_rle uses ecx edx edi esi, s:dword, flush:dword
2744
locals
2745
	bflush dd ? ;int ;set if current block must be flushed
2746
endl
2747
	mov edx,[s]
6652 IgorA 2748
	zlib_debug 'deflate_rle'
2749
align 4
6617 IgorA 2750
	.cycle0: ;for (;;)
2751
		; Make sure that we always have enough lookahead, except
2752
		; at the end of the input file. We need MAX_MATCH bytes
2753
		; for the longest run, plus one for the unrolled loop.
2754
		cmp dword[edx+deflate_state.lookahead],MAX_MATCH
2755
		jg .end0 ;if (..<=..)
2756
			stdcall fill_window, edx
2757
			cmp dword[edx+deflate_state.lookahead],MAX_MATCH
2758
			jg @f
2759
			cmp dword[flush],Z_NO_FLUSH
2760
			jne @f ;if (..<=.. && ..==..)
2761
				mov eax,need_more
2762
				jmp .end_f
2763
align 4
2764
			@@:
2765
			cmp dword[edx+deflate_state.lookahead],0
2766
			je .cycle0end ;flush the current block
2767
align 4
2768
		.end0:
2769
 
2770
		; See how many times the previous byte repeats
2771
		mov dword[edx+deflate_state.match_length],0
2772
		cmp dword[edx+deflate_state.lookahead],MIN_MATCH
2773
		jl .end1
2774
		cmp dword[edx+deflate_state.strstart],0
2775
		jle .end1 ;if (..>=.. && ..>..)
2776
			mov esi,[edx+deflate_state.window]
2777
			add esi,[edx+deflate_state.strstart]
2778
			dec esi
2779
			lodsb
2780
			mov edi,esi
2781
			scasb
2782
			jnz .end2
2783
			scasb
2784
			jnz .end2
2785
			scasb
2786
			jnz .end2 ;if (..==.. && ..==.. && ..==..)
6652 IgorA 2787
				;edi = scan ;scan goes up to strend for length of run
2788
				; al = prev ;byte at distance one to match
6617 IgorA 2789
				;ecx = strend-scan
2790
				mov ecx,MAX_MATCH-2
2791
				repz scasb
2792
				sub edi,[edx+deflate_state.window]
2793
				sub edi,[edx+deflate_state.strstart]
2794
				mov [edx+deflate_state.match_length],edi
2795
				mov eax,[edx+deflate_state.lookahead]
2796
				cmp [edx+deflate_state.match_length],eax
2797
				jle .end2
2798
					mov [edx+deflate_state.match_length],eax
2799
			.end2:
2800
			mov eax,[edx+deflate_state.window_size]
2801
			dec eax
2802
			add eax,[edx+deflate_state.window]
2803
			cmp edi,eax
2804
			jle .end1
6639 IgorA 2805
				zlib_assert 'wild scan' ;Assert(..<=..)
6617 IgorA 2806
		.end1:
2807
 
2808
		; Emit match if have run of MIN_MATCH or longer, else emit literal
2809
		cmp dword[edx+deflate_state.match_length],MIN_MATCH
2810
		jl @f ;if (..>=..)
2811
			push dword[edx+deflate_state.match_length]
2812
			mov eax,[edx+deflate_state.strstart]
2813
			dec eax
2814
			stdcall check_match, edx, [edx+deflate_state.strstart], eax
2815
 
2816
			mov eax,[edx+deflate_state.match_length]
2817
			sub eax,MIN_MATCH
2818
			_tr_tally_dist edx, 1, eax, [bflush]
2819
 
2820
			mov eax,[edx+deflate_state.match_length]
2821
			sub [edx+deflate_state.lookahead],eax
2822
			add [edx+deflate_state.strstart],eax
2823
			mov dword[edx+deflate_state.match_length],0
2824
			jmp .end3
2825
		@@: ;else
2826
			; No match, output a literal byte
2827
			mov eax,[edx+deflate_state.strstart]
2828
			add eax,[edx+deflate_state.window]
2829
			movzx eax,byte[eax]
2830
			Tracevv eax,
2831
			_tr_tally_lit edx, eax, [bflush]
2832
			dec dword[edx+deflate_state.lookahead]
2833
			inc dword[edx+deflate_state.strstart]
2834
		.end3:
2835
		cmp dword[bflush],0
2836
		je .cycle0 ;if (..)
2837
			FLUSH_BLOCK edx, 0
2838
		jmp .cycle0
2839
align 4
2840
	.cycle0end:
2841
	mov dword[edx+deflate_state.insert],0
2842
	cmp dword[flush],Z_FINISH
2843
	jne @f ;if (..==..)
2844
		FLUSH_BLOCK edx, 1
2845
		mov eax,finish_done
2846
		jmp .end_f
2847
	@@:
2848
	cmp dword[edx+deflate_state.last_lit],0
2849
	je @f ;if (..)
2850
		FLUSH_BLOCK edx, 0
2851
	@@:
2852
	mov eax,block_done
2853
.end_f:
2854
	ret
2855
endp
2856
 
2857
; ===========================================================================
2858
; For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
2859
; (It will be regenerated if this run of deflate switches away from Huffman.)
2860
 
2861
;block_state (s, flush)
6639 IgorA 2862
;    deflate_state *s
2863
;    int flush
6617 IgorA 2864
align 4
2865
proc deflate_huff uses ebx edi, s:dword, flush:dword
2866
locals
2867
	bflush dd ? ;int ;set if current block must be flushed
2868
endl
2869
	mov edi,[s]
6652 IgorA 2870
	zlib_debug 'deflate_huff'
2871
align 4
6617 IgorA 2872
	.cycle0: ;for (;;)
2873
		; Make sure that we have a literal to write.
2874
		cmp dword[edi+deflate_state.lookahead],0
2875
		jne .end0 ;if (..==0)
2876
			stdcall fill_window, edi
2877
			cmp dword[edi+deflate_state.lookahead],0
2878
			jne .end0 ;if (..==0)
2879
				cmp dword[flush],Z_NO_FLUSH
6652 IgorA 2880
				jne .cycle0end ;if (..==..)
6617 IgorA 2881
					mov eax,need_more
2882
					jmp .end_f
6652 IgorA 2883
				;flush the current block
6617 IgorA 2884
align 4
2885
		.end0:
2886
 
2887
		; Output a literal byte
2888
		mov dword[edi+deflate_state.match_length],0
2889
		mov eax,[edi+deflate_state.strstart]
2890
		add eax,[edi+deflate_state.window]
2891
		movzx eax,byte[eax]
2892
		Tracevv eax,
2893
		_tr_tally_lit edi, eax, [bflush]
2894
		dec dword[edi+deflate_state.lookahead]
2895
		inc dword[edi+deflate_state.strstart]
2896
		cmp dword[bflush],0
2897
		je @f ;if (..)
2898
			FLUSH_BLOCK edi, 0
2899
		@@:
2900
		jmp .cycle0
2901
align 4
2902
	.cycle0end:
2903
	mov dword[edi+deflate_state.insert],0
2904
	cmp dword[flush],Z_FINISH
2905
	jne @f ;if (..==..)
2906
		FLUSH_BLOCK edi, 1
2907
		mov eax,finish_done
2908
		jmp .end_f
2909
	@@:
2910
	cmp dword[edi+deflate_state.last_lit],0
2911
	je @f ;if (..)
2912
		FLUSH_BLOCK edi, 0
2913
	@@:
2914
	mov eax,block_done
2915
.end_f:
2916
	ret
2917
endp