Subversion Repositories Kolibri OS

Rev

Rev 6639 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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)
  201. ;    z_streamp strm;
  202. ;    int level;
  203. ;    const char *version;
  204. ;    int stream_size;
  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)
  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;
  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)
  436. ;    z_streamp strm;
  437. ;    const Bytef *dictionary;
  438. ;    uInt  dictLength;
  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)
  521. ;    z_streamp strm;
  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.  
  547.         mov word[edi+deflate_state.pending],0
  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
  566.                 stdcall calc_crc32, 0, Z_NULL, 0
  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)
  581. ;    z_streamp strm;
  582. align 4
  583. proc deflateReset uses ebx, strm:dword
  584.         mov ebx,[strm]
  585. ;zlib_debug 'deflateReset'
  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)
  596. ;    z_streamp strm;
  597. ;    gz_headerp head;
  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)
  624. ;    unsigned *pending;
  625. ;    int *bits;
  626. ;    z_streamp strm;
  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]
  642.                 movzx ebx,word[edi+deflate_state.pending]
  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)
  658. ;    z_streamp strm;
  659. ;    int bits;
  660. ;    int value;
  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)
  694. ;    z_streamp strm;
  695. ;    int level;
  696. ;    int strategy;
  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)
  751. ;    z_streamp strm;
  752. ;    int good_length;
  753. ;    int max_lazy;
  754. ;    int nice_length;
  755. ;    int max_chain;
  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)
  800. ;    z_streamp strm;
  801. ;    uLong sourceLen;
  802. align 4
  803. proc deflateBound, strm:dword, sourceLen:dword
  804. ;    deflate_state *s;
  805. ;    uLong complen, wraplen;
  806. ;    Bytef *str;
  807. ;zlib_debug 'deflateBound'
  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)
  866. ;    deflate_state *s;
  867. ;    uInt b;
  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)
  884. ;    z_streamp strm;
  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
  890. ;zlib_debug 'flush_pending'
  891.         mov ebx,[strm]
  892.         mov edx,[ebx+z_stream.state]
  893.  
  894.         stdcall _tr_flush_bits, edx
  895.         movzx ecx,word[edx+deflate_state.pending]
  896.         cmp cx,[ebx+z_stream.avail_out]
  897.         jle @f ;if (..>..)
  898.                 movzx ecx,word[ebx+z_stream.avail_out]
  899.         @@:
  900.         cmp ecx,0
  901.         je @f
  902.  
  903.         stdcall zmemcpy, [ebx+z_stream.next_out], [edx+deflate_state.pending_out], ecx
  904.         add [ebx+z_stream.next_out],ecx
  905.         add [edx+deflate_state.pending_out],ecx
  906.         add [ebx+z_stream.total_out],ecx
  907.         sub [ebx+z_stream.avail_out],cx
  908.         sub [edx+deflate_state.pending],cx
  909.         cmp word[edx+deflate_state.pending],0
  910.         jne @f ;if (..==0)
  911.                 mov eax,[edx+deflate_state.pending_buf]
  912.                 mov [edx+deflate_state.pending_out],eax
  913.         @@:
  914.         ret
  915. endp
  916.  
  917. ; =========================================================================
  918. ;int (strm, flush)
  919. ;    z_streamp strm;
  920. ;    int flush;
  921. align 4
  922. proc deflate uses ebx ecx edx edi esi, strm:dword, flush:dword
  923. locals
  924.         old_flush dd ? ;int ;value of flush param for previous deflate call
  925.         val dd ?
  926. endl
  927.         mov ebx,[strm]
  928. zlib_debug 'deflate strm = %d',ebx
  929.         cmp ebx,Z_NULL
  930.         je @f
  931.         mov edi,[ebx+z_stream.state] ;s = strm.state
  932.         cmp edi,Z_NULL
  933.         je @f
  934.         cmp dword[flush],Z_BLOCK
  935.         jg @f
  936.         cmp dword[flush],0
  937.         jl @f ;if (..==0 || ..==0 || ..>.. || ..<0)
  938.                 jmp .end10
  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
  947.         cmp word[ebx+z_stream.avail_in],0
  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
  954.         .beg0: ;if (..==0 || (..==0 && ..!=0) || (..=.. && ..!=..))
  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 (..==..)
  976.                         stdcall calc_crc32, 0, Z_NULL, 0
  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.                                         movzx eax,word[edi+deflate_state.pending]
  1053.                                         stdcall calc_crc32, [ebx+z_stream.adler],\
  1054.                                                 [edi+deflate_state.pending_buf], eax
  1055.                                         mov [ebx+z_stream.adler],eax
  1056.                                 @@:
  1057.                                 mov dword[edi+deflate_state.gzindex],0
  1058.                                 mov dword[edi+deflate_state.status],EXTRA_STATE
  1059.                         jmp .end2
  1060.                 .end1: ;else
  1061. end if
  1062.                         mov edx,[edi+deflate_state.w_bits]
  1063.                         sub edx,8
  1064.                         shl edx,4
  1065.                         add edx,Z_DEFLATED
  1066.                         shl edx,8 ;edx = header
  1067.                         ;esi = level_flags
  1068.  
  1069.                         mov esi,3
  1070.                         cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
  1071.                         jl @f
  1072.                         cmp word[edi+deflate_state.level],2
  1073.                         jge @f ;if (..>=.. || ..<..)
  1074.                                 xor esi,esi
  1075.                                 jmp .end4
  1076.                         @@:
  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.                         @@:
  1110.                         stdcall calc_crc32, 0, Z_NULL, 0
  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 (..!=..)
  1119.                         movzx esi,word[edi+deflate_state.pending]
  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
  1126.                                 movzx eax,word[edi+deflate_state.pending]
  1127.                                 cmp eax,[edi+deflate_state.pending_buf_size]
  1128.                                 jne .end24 ;if (..==..)
  1129.                                         mov dword[edx+gz_header.hcrc],0
  1130.                                         je @f
  1131.                                         cmp [edi+deflate_state.pending],si
  1132.                                         jle @f ;if (.. && ..>..)
  1133.                                                 movzx ecx,word[edi+deflate_state.pending]
  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
  1141.                                         movzx esi,word[edi+deflate_state.pending]
  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
  1156.                         cmp [edi+deflate_state.pending],si
  1157.                         jle @f ;if (.. && ..>..)
  1158.                                 movzx ecx,word[edi+deflate_state.pending]
  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 (..!=..)
  1178.                         movzx esi,word[edi+deflate_state.pending]
  1179.                         ;esi = beg ;start of bytes to update crc
  1180.  
  1181.                         .cycle1: ;do
  1182.                                 movzx eax,word[edi+deflate_state.pending]
  1183.                                 cmp eax,[edi+deflate_state.pending_buf_size]
  1184.                                 jne .end25 ;if (..==..)
  1185.                                         mov dword[edx+gz_header.hcrc],0
  1186.                                         je @f
  1187.                                         cmp [edi+deflate_state.pending],si
  1188.                                         jle @f ;if (.. && ..>..)
  1189.                                                 movzx ecx,word[edi+deflate_state.pending]
  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
  1197.                                         movzx esi,word[edi+deflate_state.pending]
  1198.                                         movzx eax,word[edi+deflate_state.pending]
  1199.                                         cmp eax,[edi+deflate_state.pending_buf_size]
  1200.                                         jne .end25 ;if (..==..)
  1201.                                                 mov dword[val],1
  1202.                                                 jmp .cycle1end
  1203.                                 .end25:
  1204.                                 push ebx
  1205.                                         mov ebx,[edi+deflate_state.gzindex]
  1206.                                         add ebx,[edx+gz_header.name]
  1207.                                         movzx ebx,byte[ebx]
  1208.                                         mov [val],ebx
  1209.                                         inc dword[edi+deflate_state.gzindex]
  1210.                                         put_byte edi, bl
  1211.                                 pop ebx
  1212.                                 cmp dword[val],0
  1213.                                 jne .cycle1 ;while (val != 0)
  1214.                         .cycle1end:
  1215.                         mov dword[edx+gz_header.hcrc],0
  1216.                         je @f
  1217.                         cmp [edi+deflate_state.pending],si
  1218.                         jle @f ;if (.. && ..>..)
  1219.                                 movzx ecx,word[edi+deflate_state.pending]
  1220.                                 sub ecx,esi
  1221.                                 mov eax,[edi+deflate_state.pending_buf]
  1222.                                 add eax,esi
  1223.                                 stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
  1224.                                 mov [ebx+z_stream.adler],eax
  1225.                         @@:
  1226.                         cmp dword[val],0
  1227.                         jne .end6 ;if (val == 0)
  1228.                                 mov dword[edi+deflate_state.gzindex],0
  1229.                                 mov dword[edi+deflate_state.status],COMMENT_STATE
  1230.                         jmp .end6
  1231.                 .end22: ;else
  1232.                         mov dword[edi+deflate_state.status],COMMENT_STATE;
  1233.         .end6:
  1234.         cmp dword[edi+deflate_state.status],COMMENT_STATE
  1235.         jne .end7 ;if (..==..)
  1236.                 cmp dword[edx+gz_header.comment],Z_NULL
  1237.                 je .end23 ;if (..!=..)
  1238.                         movzx esi,word[edi+deflate_state.pending]
  1239.                         ;esi = beg ;start of bytes to update crc
  1240.  
  1241.                         .cycle2: ;do
  1242.                                 movzx eax,word[edi+deflate_state.pending]
  1243.                                 cmp eax,[edi+deflate_state.pending_buf_size]
  1244.                                 jne .end26 ;if (..==..)
  1245.                                         mov dword[edx+gz_header.hcrc],0
  1246.                                         je @f
  1247.                                         cmp [edi+deflate_state.pending],si
  1248.                                         jle @f ;if (.. && ..>..)
  1249.                                                 movzx ecx,word[edi+deflate_state.pending]
  1250.                                                 sub ecx,esi
  1251.                                                 mov eax,[edi+deflate_state.pending_buf]
  1252.                                                 add eax,esi
  1253.                                                 stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
  1254.                                                 mov [ebx+z_stream.adler],eax
  1255.                                         @@:
  1256.                                         stdcall flush_pending, ebx
  1257.                                         movzx esi,word[edi+deflate_state.pending]
  1258.                                         movzx eax,word[edi+deflate_state.pending]
  1259.                                         cmp eax,[edi+deflate_state.pending_buf_size]
  1260.                                         jne .end26 ;if (..==..)
  1261.                                                 mov dword[val],1
  1262.                                                 jmp .cycle2end
  1263.                                 .end26:
  1264.                                 push ebx
  1265.                                         mov ebx,[edi+deflate_state.gzindex]
  1266.                                         add ebx,[edx+gz_header.comment]
  1267.                                         movzx ebx,byte[ebx]
  1268.                                         mov [val],ebx
  1269.                                         inc dword[edi+deflate_state.gzindex]
  1270.                                         put_byte edi, bl
  1271.                                 pop ebx
  1272.                                 cmp dword[val],0
  1273.                                 jne .cycle2 ;while (val != 0)
  1274.                         .cycle2end:
  1275.                         mov dword[edx+gz_header.hcrc],0
  1276.                         je @f
  1277.                         cmp [edi+deflate_state.pending],si
  1278.                         jle @f ;if (.. && ..>..)
  1279.                                 movzx ecx,word[edi+deflate_state.pending]
  1280.                                 sub ecx,esi
  1281.                                 mov eax,[edi+deflate_state.pending_buf]
  1282.                                 add eax,esi
  1283.                                 stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx
  1284.                                 mov [ebx+z_stream.adler],eax
  1285.                         @@:
  1286.                         cmp dword[val],0
  1287.                         jne .end7 ;if (val == 0)
  1288.                                 mov dword[edi+deflate_state.status],HCRC_STATE
  1289.                         jmp .end7
  1290.                 .end23: ;else
  1291.                         mov dword[edi+deflate_state.status],HCRC_STATE
  1292.         .end7:
  1293.         cmp dword[edi+deflate_state.status],HCRC_STATE
  1294.         jne .end8 ;if (..==..)
  1295.                 cmp dword[edx+gz_header.hcrc],0
  1296.                 je .end9 ;if (..)
  1297.                         movzx ecx,word[edi+deflate_state.pending]
  1298.                         add ecx,2
  1299.                         cmp ecx,[edi+deflate_state.pending_buf_size]
  1300.                         jle @f ;if (..>..)
  1301.                                 stdcall flush_pending, ebx
  1302.                         @@:
  1303.                         movzx ecx,word[edi+deflate_state.pending]
  1304.                         add ecx,2
  1305.                         cmp ecx,[edi+deflate_state.pending_buf_size]
  1306.                         jg @f ;if (..<=..)
  1307.                                 mov ecx,[ebx+z_stream.adler]
  1308.                                 put_byte edi, cl
  1309.                                 put_byte edi, ch
  1310.                                 stdcall calc_crc32, 0, Z_NULL, 0
  1311.                                 mov [ebx+z_stream.adler],eax
  1312.                                 mov dword[edi+deflate_state.status],BUSY_STATE
  1313.                         @@:
  1314.                         jmp .end8
  1315.                 .end9: ;else
  1316.                         mov dword[edi+deflate_state.status],BUSY_STATE
  1317.         .end8:
  1318. end if
  1319.  
  1320.         ; Flush as much pending output as possible
  1321.         cmp word[edi+deflate_state.pending],0
  1322.         je .end13 ;if (..!=0)
  1323.                 stdcall flush_pending, ebx
  1324.                 cmp word[ebx+z_stream.avail_out],0
  1325.                 jne @f ;if (..==0)
  1326.                         ; Since avail_out is 0, deflate will be called again with
  1327.                         ; more output space, but possibly with both pending and
  1328.                         ; avail_in equal to zero. There won't be anything to do,
  1329.                         ; but this is not an error situation so make sure we
  1330.                         ; return OK instead of BUF_ERROR at next call of deflate:
  1331.  
  1332.                         mov dword[edi+deflate_state.last_flush],-1
  1333.                         mov eax,Z_OK
  1334.                         jmp .end_f
  1335.                 @@:
  1336.                 ; Make sure there is something to do and avoid duplicate consecutive
  1337.                 ; flushes. For repeated and useless calls with Z_FINISH, we keep
  1338.                 ; returning Z_STREAM_END instead of Z_BUF_ERROR.
  1339.                 jmp @f
  1340.         .end13:
  1341.         cmp word[ebx+z_stream.avail_in],0
  1342.         jne @f
  1343.         RANK dword[old_flush],esi
  1344.         RANK dword[flush],eax
  1345.         cmp eax,esi
  1346.         jg @f
  1347.         cmp dword[flush],Z_FINISH
  1348.         je @f ;else if (..==0 && ..<=.. && ..!=..)
  1349.                 ERR_RETURN ebx, Z_BUF_ERROR
  1350.                 jmp .end_f
  1351.         @@:
  1352.  
  1353.         ; User must not provide more input after the first FINISH:
  1354.         cmp dword[edi+deflate_state.status],FINISH_STATE
  1355.         jne @f
  1356.         cmp word[ebx+z_stream.avail_in],0
  1357.         je @f ;if (..==.. && ..!=0)
  1358.                 ERR_RETURN ebx, Z_BUF_ERROR
  1359.                 jmp .end_f
  1360.         @@:
  1361.  
  1362.         ; Start a new block or continue the current one.
  1363.  
  1364.         cmp word[ebx+z_stream.avail_in],0
  1365.         jne @f
  1366.         cmp dword[edi+deflate_state.lookahead],0
  1367.         jne @f
  1368.         cmp dword[flush],Z_NO_FLUSH
  1369.         je .end11
  1370.         cmp dword[edi+deflate_state.status],FINISH_STATE
  1371.         je .end11
  1372.         @@: ;if (..!=0 || ..!=0 || (..!=.. && ..!=..))
  1373.                 ;edx = bstate
  1374.                 cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY
  1375.                 jne @f
  1376.                         stdcall deflate_huff, edi, [flush]
  1377.                         jmp .end20
  1378.                 @@:
  1379.                 cmp word[edi+deflate_state.strategy],Z_RLE
  1380.                 jne @f
  1381.                         stdcall deflate_rle, edi, [flush]
  1382.                         jmp .end20
  1383.                 @@:
  1384.                 movzx eax,word[edi+deflate_state.level]
  1385.                 imul eax,sizeof.config_s
  1386.                 add eax,configuration_table+config_s.co_func
  1387.                 stdcall dword[eax], edi, [flush]
  1388.                 .end20:
  1389.                 mov edx,eax
  1390.  
  1391.                 cmp edx,finish_started
  1392.                 je @f
  1393.                 cmp edx,finish_done
  1394.                 je @f
  1395.                         jmp .end18
  1396.                 @@: ;if (..==.. || ..==..)
  1397.                         mov dword[edi+deflate_state.status],FINISH_STATE
  1398.                 .end18:
  1399.                 cmp edx,need_more
  1400.                 je @f
  1401.                 cmp edx,finish_started
  1402.                 je @f
  1403.                         jmp .end19
  1404.                 @@: ;if (..==.. || ..==..)
  1405.                         cmp word[ebx+z_stream.avail_out],0
  1406.                         jne @f ;if (..==0)
  1407.                                 mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR next call, see above
  1408.                         @@:
  1409.                         mov eax,Z_OK
  1410.                         jmp .end_f
  1411.                         ; If flush != Z_NO_FLUSH && avail_out == 0, the next call
  1412.                         ; of deflate should use the same flush parameter to make sure
  1413.                         ; that the flush is complete. So we don't have to output an
  1414.                         ; empty block here, this will be done at next call. This also
  1415.                         ; ensures that for a very small output buffer, we emit at most
  1416.                         ; one empty block.
  1417.  
  1418.                 .end19:
  1419.                 cmp edx,block_done
  1420.                 jne .end11 ;if (..==..)
  1421.                         cmp dword[flush],Z_PARTIAL_FLUSH
  1422.                         jne @f ;if (..==..)
  1423.                                 stdcall _tr_align, edi
  1424.                                 jmp .end16
  1425.                         @@:
  1426.                         cmp dword[flush],Z_BLOCK
  1427.                         je .end16 ;else if (..!=..) ;FULL_FLUSH or SYNC_FLUSH
  1428.                                 stdcall _tr_stored_block, edi, 0, 0, 0
  1429.                                 ; For a full flush, this empty block will be recognized
  1430.                                 ; as a special marker by inflate_sync().
  1431.  
  1432.                         cmp dword[flush],Z_FULL_FLUSH
  1433.                         jne .end16 ;if (..==..)
  1434.                                 CLEAR_HASH edi ;forget history
  1435.                                 cmp dword[edi+deflate_state.lookahead],0
  1436.                                 jne .end16 ;if (..==0)
  1437.                                         mov dword[edi+deflate_state.strstart],0
  1438.                                         mov dword[edi+deflate_state.block_start],0
  1439.                                         mov dword[edi+deflate_state.insert],0
  1440.                 .end16:
  1441.                 stdcall flush_pending, ebx
  1442.                 cmp word[ebx+z_stream.avail_out],0
  1443.                 jne .end11 ;if (..==0)
  1444.                         mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR at next call, see above
  1445.                         mov eax,Z_OK
  1446.                         jmp .end_f
  1447.         .end11:
  1448.         cmp word[ebx+z_stream.avail_out],0
  1449.         jg @f
  1450.                 zlib_debug 'bug2' ;Assert(..>0)
  1451.         @@:
  1452.  
  1453.         cmp dword[flush],Z_FINISH
  1454.         je @f ;if (..!=0)
  1455.                 mov eax,Z_OK
  1456.                 jmp .end_f
  1457.         @@:
  1458.         cmp dword[edi+deflate_state.wrap],0
  1459.         jg @f ;if (..<=0)
  1460.                 mov eax,Z_STREAM_END
  1461.                 jmp .end_f
  1462.         @@:
  1463.  
  1464.         ; Write the trailer
  1465. if GZIP eq 1
  1466.         cmp dword[edi+deflate_state.wrap],2
  1467.         jne @f ;if (..==..)
  1468.                 mov ecx,[ebx+z_stream.adler]
  1469.                 put_dword edi, ecx
  1470.                 mov ecx,[ebx+z_stream.total_in]
  1471.                 put_dword edi, ecx
  1472.                 jmp .end17
  1473.         @@: ;else
  1474. end if
  1475.                 mov ecx,[ebx+z_stream.adler]
  1476.                 bswap ecx
  1477.                 put_dword edi, ecx
  1478.         .end17:
  1479.         stdcall flush_pending, ebx
  1480.         ; If avail_out is zero, the application will call deflate again
  1481.         ; to flush the rest.
  1482.  
  1483.         cmp word[edi+deflate_state.pending],0
  1484.         jle @f ;if (..>0) ;write the trailer only once!
  1485.                 neg word[edi+deflate_state.pending]
  1486.                 inc word[edi+deflate_state.pending]
  1487.         @@:
  1488.         mov eax,Z_OK
  1489.         cmp word[edi+deflate_state.pending],0
  1490.         je .end_f
  1491.                 mov eax,Z_STREAM_END
  1492. .end_f:
  1493. zlib_debug '  deflate.ret = %d',eax
  1494.         ret
  1495. endp
  1496.  
  1497. ; =========================================================================
  1498. ;int (strm)
  1499. ;    z_streamp strm;
  1500. align 4
  1501. proc deflateEnd uses ebx ecx edx, strm:dword
  1502.         mov ebx,[strm]
  1503. zlib_debug 'deflateEnd'
  1504.         cmp ebx,Z_NULL
  1505.         je @f
  1506.         mov edx,[ebx+z_stream.state]
  1507.         cmp edx,Z_NULL
  1508.         jne .end0
  1509.         @@: ;if (..==0 || ..==0) return ..
  1510.                 mov eax,Z_STREAM_ERROR
  1511.                 jmp .end_f
  1512.         .end0:
  1513.  
  1514.         mov ecx,[edx+deflate_state.status]
  1515.         cmp ecx,INIT_STATE
  1516.         je @f
  1517.         cmp ecx,EXTRA_STATE
  1518.         je @f
  1519.         cmp ecx,NAME_STATE
  1520.         je @f
  1521.         cmp ecx,COMMENT_STATE
  1522.         je @f
  1523.         cmp ecx,HCRC_STATE
  1524.         je @f
  1525.         cmp ecx,BUSY_STATE
  1526.         je @f
  1527.         cmp ecx,FINISH_STATE
  1528.         je @f ;if (..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=..)
  1529.                 mov eax,Z_STREAM_ERROR
  1530.                 jmp .end_f
  1531.         @@:
  1532.  
  1533.         ; Deallocate in reverse order of allocations:
  1534.         TRY_FREE ebx, dword[edx+deflate_state.pending_buf]
  1535.         TRY_FREE ebx, dword[edx+deflate_state.head]
  1536.         TRY_FREE ebx, dword[edx+deflate_state.prev]
  1537.         TRY_FREE ebx, dword[edx+deflate_state.window]
  1538.  
  1539.         ZFREE ebx, dword[ebx+z_stream.state]
  1540.         mov dword[ebx+z_stream.state],Z_NULL
  1541.  
  1542.         mov eax,Z_DATA_ERROR
  1543.         cmp ecx,BUSY_STATE
  1544.         je .end_f
  1545.                 mov eax,Z_OK
  1546. .end_f:
  1547.         ret
  1548. endp
  1549.  
  1550. ; =========================================================================
  1551. ; Copy the source state to the destination state.
  1552. ; To simplify the source, this is not supported for 16-bit MSDOS (which
  1553. ; doesn't have enough memory anyway to duplicate compression states).
  1554.  
  1555. ;int (dest, source)
  1556. ;    z_streamp dest;
  1557. ;    z_streamp source;
  1558. align 4
  1559. proc deflateCopy uses edx edi esi, dest:dword, source:dword
  1560. locals
  1561.         overlay dd ? ;uint_16p
  1562. endl
  1563. ;edi = ds; deflate_state*
  1564. ;esi = ss; deflate_state*
  1565.  
  1566.         mov esi,[source]
  1567.         cmp esi,Z_NULL
  1568.         je @f
  1569.         mov edx,[dest]
  1570.         cmp edx,Z_NULL
  1571.         je @f
  1572.         mov esi,[esi+z_stream.state]
  1573.         cmp esi,Z_NULL
  1574.         jne .end0
  1575.         @@: ;if (..==0 || ..==0 || ..==0)
  1576.                 mov eax,Z_STREAM_ERROR
  1577.                 jmp .end_f
  1578.         .end0:
  1579.  
  1580.         stdcall zmemcpy, edx, [source], sizeof.z_stream
  1581.  
  1582.         ZALLOC edx, 1, sizeof.deflate_state
  1583.         cmp eax,0
  1584.         jne @f ;if (..==0) return ..
  1585.                 mov eax,Z_MEM_ERROR
  1586.                 jmp .end_f
  1587.         @@:
  1588.         mov edi,eax
  1589.         mov [edx+z_stream.state],eax
  1590.         stdcall zmemcpy, edi, esi, sizeof.deflate_state
  1591.         mov dword[edi+deflate_state.strm],edx
  1592.  
  1593.         ZALLOC edx, [edi+deflate_state.w_size], 2 ;2*sizeof.db
  1594.         mov dword[edi+deflate_state.window],eax
  1595.         ZALLOC edx, [edi+deflate_state.w_size], 4 ;sizeof.dd
  1596.         mov dword[edi+deflate_state.prev],eax
  1597.         ZALLOC edx, [edi+deflate_state.hash_size], 4 ;sizeof.dd
  1598.         mov dword[edi+deflate_state.head],eax
  1599.         ZALLOC edx, [edi+deflate_state.lit_bufsize], 4 ;sizeof.dw+2
  1600.         mov [overlay],eax
  1601.         mov dword[edi+deflate_state.pending_buf],eax
  1602.  
  1603.         cmp dword[edi+deflate_state.window],Z_NULL
  1604.         je @f
  1605.         cmp dword[edi+deflate_state.prev],Z_NULL
  1606.         je @f
  1607.         cmp dword[edi+deflate_state.head],Z_NULL
  1608.         je @f
  1609.         cmp dword[edi+deflate_state.pending_buf],Z_NULL
  1610.         jne .end1
  1611.         @@: ;if (..==0 || ..==0 || ..==0 || ..==0)
  1612.                 stdcall deflateEnd, edx
  1613.                 mov eax,Z_MEM_ERROR
  1614.                 jmp .end_f
  1615.         .end1:
  1616.  
  1617.         ; following zmemcpy do not work for 16-bit MSDOS
  1618.         mov eax,[edi+deflate_state.w_size]
  1619.         shl eax,1 ;*= 2*sizeof.db
  1620.         stdcall zmemcpy, [edi+deflate_state.window], [esi+deflate_state.window], eax
  1621. ;    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
  1622. ;    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
  1623. ;    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
  1624.  
  1625. ;    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
  1626. ;    ds->d_buf = overlay + ds->lit_bufsize/sizeof(uint_16);
  1627. ;    ds->l_buf = ds->pending_buf + (1+sizeof(uint_16))*ds->lit_bufsize;
  1628.  
  1629.         mov eax,edi
  1630.         add eax,deflate_state.dyn_ltree
  1631.         mov [edi+deflate_state.l_desc.dyn_tree],eax
  1632.         add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree
  1633.         mov [edi+deflate_state.d_desc.dyn_tree],eax
  1634.         add eax,deflate_state.bl_tree-deflate_state.dyn_dtree
  1635.         mov [edi+deflate_state.bl_desc.dyn_tree],eax
  1636.  
  1637.         mov eax,Z_OK
  1638. .end_f:
  1639.         ret
  1640. endp
  1641.  
  1642. ; ===========================================================================
  1643. ; Read a new buffer from the current input stream, update the adler32
  1644. ; and total number of bytes read.  All deflate() input goes through
  1645. ; this function so some applications may wish to modify it to avoid
  1646. ; allocating a large strm->next_in buffer and copying from it.
  1647. ; (See also flush_pending()).
  1648.  
  1649. ;int (strm, buf, size)
  1650. ;    z_streamp strm;
  1651. ;    Bytef *buf;
  1652. ;    unsigned size;
  1653. align 4
  1654. proc read_buf uses ebx ecx, strm:dword, buf:dword, size:dword
  1655.         mov ebx,[strm]
  1656.         movzx eax,word[ebx+z_stream.avail_in]
  1657.  
  1658.         cmp eax,[size]
  1659.         jle @f ;if (..>..)
  1660.                 mov eax,[size]
  1661.         @@:
  1662.         cmp eax,0
  1663.         jg @f
  1664.                 xor eax,eax
  1665.                 jmp .end_f ;if (..==0) return 0
  1666.         @@:
  1667.  
  1668.         sub [ebx+z_stream.avail_in],ax
  1669.  
  1670.         stdcall zmemcpy, [buf],[ebx+z_stream.next_in],eax
  1671.         mov ecx,[ebx+z_stream.state]
  1672.         cmp [ecx+deflate_state.wrap],1
  1673.         jne @f ;if (..==..)
  1674.                 push eax
  1675.                 stdcall adler32, [ebx+z_stream.adler], [buf], eax
  1676.                 mov [ebx+z_stream.adler],eax
  1677.                 pop eax
  1678.                 jmp .end0
  1679.         @@:
  1680. if GZIP eq 1
  1681.         cmp [ecx+deflate_state.wrap],2
  1682.         jne .end0 ;else if (..==..)
  1683.                 push eax
  1684.                 stdcall calc_crc32, [ebx+z_stream.adler], [buf], eax
  1685.                 mov [ebx+z_stream.adler],eax
  1686.                 pop eax
  1687. end if
  1688.         .end0:
  1689.         add [ebx+z_stream.next_in],eax
  1690.         add [ebx+z_stream.total_in],eax
  1691.  
  1692. .end_f:
  1693. ;zlib_debug '  read_buf.ret = %d',eax
  1694.         ret
  1695. endp
  1696.  
  1697. ; ===========================================================================
  1698. ; Initialize the "longest match" routines for a new zlib stream
  1699.  
  1700. ;void (s)
  1701. ;    deflate_state *s
  1702. align 4
  1703. proc lm_init uses eax ebx edi, s:dword
  1704.         mov edi,[s]
  1705.         mov eax,[edi+deflate_state.w_size]
  1706.         shl eax,1
  1707.         mov [edi+deflate_state.window_size],eax
  1708.  
  1709.         CLEAR_HASH edi
  1710.  
  1711.         ; Set the default configuration parameters:
  1712.  
  1713.         movzx eax,word[edi+deflate_state.level]
  1714.         imul eax,sizeof.config_s
  1715.         add eax,configuration_table
  1716.         movzx ebx,word[eax+config_s.max_lazy]
  1717.         mov [edi+deflate_state.max_lazy_match],ebx
  1718.         movzx ebx,word[eax+config_s.good_length]
  1719.         mov [edi+deflate_state.good_match],ebx
  1720.         movzx ebx,word[eax+config_s.nice_length]
  1721.         mov [edi+deflate_state.nice_match],ebx
  1722.         movzx ebx,word[eax+config_s.max_chain]
  1723.         mov [edi+deflate_state.max_chain_length],ebx
  1724.  
  1725.         mov dword[edi+deflate_state.strstart],0
  1726.         mov dword[edi+deflate_state.block_start],0
  1727.         mov dword[edi+deflate_state.lookahead],0
  1728.         mov dword[edi+deflate_state.insert],0
  1729.         mov dword[edi+deflate_state.prev_length],MIN_MATCH-1
  1730.         mov dword[edi+deflate_state.match_length],MIN_MATCH-1
  1731.         mov dword[edi+deflate_state.match_available],0
  1732.         mov dword[edi+deflate_state.ins_h],0
  1733. if FASTEST eq 0
  1734. ;if ASMV
  1735. ;    call match_init ;initialize the asm code
  1736. ;end if
  1737. end if
  1738.         ret
  1739. endp
  1740.  
  1741. ;uInt (s, cur_match)
  1742. ;    deflate_state *s;
  1743. ;    IPos cur_match;                             /* current match */
  1744. align 4
  1745. proc longest_match uses ebx ecx edx edi esi, s:dword, cur_match:dword
  1746. if FASTEST eq 0
  1747. ; ===========================================================================
  1748. ; Set match_start to the longest match starting at the given string and
  1749. ; return its length. Matches shorter or equal to prev_length are discarded,
  1750. ; in which case the result is equal to prev_length and match_start is
  1751. ; garbage.
  1752. ; IN assertions: cur_match is the head of the hash chain for the current
  1753. ;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
  1754. ; OUT assertion: the match length is not greater than s->lookahead.
  1755.  
  1756. ;#ifndef ASMV
  1757. ; For 80x86 and 680x0, an optimized version will be provided in match.asm or
  1758. ; match.S. The code will be functionally equivalent.
  1759.  
  1760. ;    unsigned chain_length = s->max_chain_length;/* max hash chain length */
  1761. ;    register Bytef *scan = s->window + s->strstart; /* current string */
  1762. ;    register Bytef *match;                       /* matched string */
  1763. ;    register int len;                           /* length of current match */
  1764. ;    int best_len = s->prev_length;              /* best match length so far */
  1765. ;    int nice_match = s->nice_match;             /* stop if match long enough */
  1766. ;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
  1767. ;        s->strstart - (IPos)MAX_DIST(s) : NIL;
  1768.         ; Stop when cur_match becomes <= limit. To simplify the code,
  1769.         ; we prevent matches with the string of window index 0.
  1770.  
  1771. ;    Posf *prev = s->prev;
  1772. ;    uInt wmask = s->w_mask;
  1773.  
  1774. if UNALIGNED_OK eq 1
  1775.         ; Compare two bytes at a time. Note: this is not always beneficial.
  1776.         ; Try with and without -DUNALIGNED_OK to check.
  1777.  
  1778. ;    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
  1779. ;    register uint_16 scan_start = *(uint_16p*)scan;
  1780. ;    register uint_16 scan_end   = *(uint_16p*)(scan+best_len-1);
  1781. else
  1782. ;    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
  1783. ;    register Byte scan_end1  = scan[best_len-1];
  1784. ;    register Byte scan_end   = scan[best_len];
  1785. end if
  1786.  
  1787.         ; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
  1788.         ; It is easy to get rid of this optimization if necessary.
  1789.  
  1790. ;    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
  1791.  
  1792.         ; Do not waste too much time if we already have a good match:
  1793. ;    if (s->prev_length >= s->good_match) {
  1794. ;        chain_length >>= 2;
  1795. ;    }
  1796.         ; Do not look for matches beyond the end of the input. This is necessary
  1797.         ; to make deflate deterministic.
  1798.  
  1799. ;    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
  1800.  
  1801. ;    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
  1802.  
  1803. ;    do {
  1804. ;        Assert(cur_match < s->strstart, "no future");
  1805. ;        match = s->window + cur_match;
  1806.  
  1807.         ; Skip to next match if the match length cannot increase
  1808.         ; or if the match length is less than 2.  Note that the checks below
  1809.         ; for insufficient lookahead only occur occasionally for performance
  1810.         ; reasons.  Therefore uninitialized memory will be accessed, and
  1811.         ; conditional jumps will be made that depend on those values.
  1812.         ; However the length of the match is limited to the lookahead, so
  1813.         ; the output of deflate is not affected by the uninitialized values.
  1814.  
  1815. if ((UNALIGNED_OK eq 1) & MAX_MATCH == 258)
  1816.         ; This code assumes sizeof(unsigned short) == 2. Do not use
  1817.         ; UNALIGNED_OK if your compiler uses a different size.
  1818.  
  1819. ;        if (*(uint_16p*)(match+best_len-1) != scan_end ||
  1820. ;            *(uint_16p*)match != scan_start) continue;
  1821.  
  1822.         ; It is not necessary to compare scan[2] and match[2] since they are
  1823.         ; always equal when the other bytes match, given that the hash keys
  1824.         ; are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
  1825.         ; strstart+3, +5, ... up to strstart+257. We check for insufficient
  1826.         ; lookahead only every 4th comparison; the 128th check will be made
  1827.         ; at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
  1828.         ; necessary to put more guard bytes at the end of the window, or
  1829.         ; to check more often for insufficient lookahead.
  1830.  
  1831. ;        Assert(scan[2] == match[2], "scan[2]?");
  1832. ;        scan++, match++;
  1833. ;        do {
  1834. ;        } while (*(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) &&
  1835. ;                 *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) &&
  1836. ;                 *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) &&
  1837. ;                 *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) &&
  1838. ;                 scan < strend);
  1839.         ; The funny "do {}" generates better code on most compilers
  1840.  
  1841.         ; Here, scan <= window+strstart+257
  1842. ;        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
  1843. ;        if (*scan == *match) scan++;
  1844.  
  1845. ;        len = (MAX_MATCH - 1) - (int)(strend-scan);
  1846. ;        scan = strend - (MAX_MATCH-1);
  1847.  
  1848. else ;UNALIGNED_OK
  1849.  
  1850. ;        if (match[best_len]   != scan_end  ||
  1851. ;            match[best_len-1] != scan_end1 ||
  1852. ;            *match            != *scan     ||
  1853. ;            *++match          != scan[1])      continue;
  1854.  
  1855.         ; The check at best_len-1 can be removed because it will be made
  1856.         ; again later. (This heuristic is not always a win.)
  1857.         ; It is not necessary to compare scan[2] and match[2] since they
  1858.         ; are always equal when the other bytes match, given that
  1859.         ; the hash keys are equal and that HASH_BITS >= 8.
  1860.  
  1861. ;        scan += 2, match++;
  1862. ;        Assert(*scan == *match, "match[2]?");
  1863.  
  1864.         ; We check for insufficient lookahead only every 8th comparison;
  1865.         ; the 256th check will be made at strstart+258.
  1866.  
  1867. ;        do {
  1868. ;        } while (*++scan == *++match && *++scan == *++match &&
  1869. ;                 *++scan == *++match && *++scan == *++match &&
  1870. ;                 *++scan == *++match && *++scan == *++match &&
  1871. ;                 *++scan == *++match && *++scan == *++match &&
  1872. ;                 scan < strend);
  1873.  
  1874. ;        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
  1875.  
  1876. ;        len = MAX_MATCH - (int)(strend - scan);
  1877. ;        scan = strend - MAX_MATCH;
  1878.  
  1879. end if ;UNALIGNED_OK
  1880.  
  1881. ;        if (len > best_len) {
  1882. ;            s->match_start = cur_match;
  1883. ;            best_len = len;
  1884. ;            if (len >= nice_match) break;
  1885. if UNALIGNED_OK eq 1
  1886. ;            scan_end = *(uint_16p*)(scan+best_len-1);
  1887. else
  1888. ;            scan_end1  = scan[best_len-1];
  1889. ;            scan_end   = scan[best_len];
  1890. end if
  1891. ;        }
  1892. ;    } while ((cur_match = prev[cur_match & wmask]) > limit
  1893. ;             && --chain_length != 0);
  1894.  
  1895. ;    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
  1896. ;    return s->lookahead;
  1897. ;end if /* ASMV */
  1898.  
  1899. else ;FASTEST
  1900.  
  1901. ; ---------------------------------------------------------------------------
  1902. ; Optimized version for FASTEST only
  1903.         mov edx,[s]
  1904. ;zlib_debug 'longest_match'
  1905.  
  1906.         ; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
  1907.         ; It is easy to get rid of this optimization if necessary.
  1908.  
  1909. if MAX_MATCH <> 258
  1910.         cmp dword[edx+deflate_state.hash_bits],8
  1911.         jge @f
  1912.                 zlib_debug 'Code too clever' ;Assert(..>=.. && ..==..)
  1913.         @@:
  1914. end if
  1915.         mov eax,[edx+deflate_state.window_size]
  1916.         sub eax,MIN_LOOKAHEAD
  1917.         cmp [edx+deflate_state.strstart],eax
  1918.         jle @f
  1919.                 zlib_debug 'need lookahead' ;Assert(..<=..)
  1920.         @@:
  1921.         mov eax,[edx+deflate_state.strstart]
  1922.         cmp [cur_match],eax
  1923.         jl @f
  1924.                 zlib_debug 'no future' ;Assert(..<..)
  1925.         @@:
  1926.  
  1927.         mov esi,[edx+deflate_state.window]
  1928.         mov edi,esi
  1929.         add esi,[cur_match]
  1930.         add edi,[edx+deflate_state.strstart]
  1931.         ;edi = scan
  1932.         ;esi = match
  1933.  
  1934.         ; Return failure if the match length is less than 2:
  1935.  
  1936.         lodsw
  1937.         cmp ax,word[edi]
  1938.         je @f ;if (word[edi] != word[esi]) return
  1939.                 mov eax,MIN_MATCH-1
  1940.                 jmp .end_f
  1941.         @@:
  1942.  
  1943.         ; The check at best_len-1 can be removed because it will be made
  1944.         ; again later. (This heuristic is not always a win.)
  1945.         ; It is not necessary to compare scan[2] and match[2] since they
  1946.         ; are always equal when the other bytes match, given that
  1947.         ; the hash keys are equal and that HASH_BITS >= 8.
  1948.  
  1949.         add edi,2
  1950.         mov al,byte[edi]
  1951.         cmp al,byte[esi]
  1952.         je @f
  1953.                 zlib_debug 'match[2]?' ;Assert(..==..)
  1954.         @@:
  1955.  
  1956.         ; We check for insufficient lookahead only every 8th comparison;
  1957.         ; the 256th check will be made at strstart+258.
  1958.  
  1959.         mov ebx,edi
  1960.         mov ecx,MAX_MATCH
  1961. align 4
  1962.         @@:
  1963.                 lodsb
  1964.                 scasb
  1965.                 loope @b
  1966.  
  1967.         mov eax,[edx+deflate_state.window_size]
  1968.         dec eax
  1969.         add eax,[edx+deflate_state.window]
  1970.         cmp edi,eax
  1971.         jle @f
  1972.                 zlib_debug 'wild scan' ;Assert(..<=..)
  1973.         @@:
  1974.         sub edi,ebx
  1975.         ;edi = len
  1976.  
  1977.         cmp edi,MIN_MATCH
  1978.         jge @f ;if (..<..)
  1979.                 mov eax,MIN_MATCH-1
  1980.                 jmp .end_f
  1981.         @@:
  1982.         mov eax,[cur_match]
  1983.         mov [edx+deflate_state.match_start],eax
  1984.         mov eax,[edx+deflate_state.lookahead]
  1985.         cmp edi,eax
  1986.         jg @f ;if (len <= s.lookahead) ? len : s.lookahead
  1987.                 mov eax,edi
  1988.         @@:
  1989. end if ;FASTEST
  1990. .end_f:
  1991. ;zlib_debug '  longest_match.ret = %d',eax
  1992.         ret
  1993. endp
  1994.  
  1995.  
  1996. ; ===========================================================================
  1997. ; Check that the match at match_start is indeed a match.
  1998.  
  1999. ;void (s, start, match, length)
  2000. ;    deflate_state *s;
  2001. ;    IPos start, match;
  2002. ;    int length;
  2003. align 4
  2004. proc check_match, s:dword, start:dword, p3match:dword, length:dword
  2005. if DEBUG eq 1
  2006.         ; check that the match is indeed a match
  2007. ;    if (zmemcmp(s->window + match,
  2008. ;                s->window + start, length) != EQUAL) {
  2009. ;        fprintf(stderr, " start %u, match %u, length %d\n",
  2010. ;                start, match, length);
  2011. ;        do {
  2012. ;            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
  2013. ;        } while (--length != 0);
  2014. ;        z_error("invalid match");
  2015. ;    }
  2016. ;    if (z_verbose > 1) {
  2017. ;        fprintf(stderr,"\\[%d,%d]", start-match, length);
  2018. ;        do { putc(s->window[start++], stderr); } while (--length != 0);
  2019. ;    }
  2020. end if ;DEBUG
  2021.         ret
  2022. endp
  2023.  
  2024.  
  2025. ; ===========================================================================
  2026. ; Fill the window when the lookahead becomes insufficient.
  2027. ; Updates strstart and lookahead.
  2028.  
  2029. ; IN assertion: lookahead < MIN_LOOKAHEAD
  2030. ; OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
  2031. ;    At least one byte has been read, or avail_in == 0; reads are
  2032. ;    performed for at least two bytes (required for the zip translate_eol
  2033. ;    option -- not supported here).
  2034.  
  2035. ;void (s)
  2036. ;    deflate_state *s
  2037. align 4
  2038. proc fill_window, s:dword
  2039. pushad
  2040. ;esi = p, str, curr
  2041. ;ebx = more ;Amount of free space at the end of the window.
  2042.         ;Объем свободного пространства в конце окна.
  2043. ;ecx = wsize ;uInt
  2044. ;edx = s.strm
  2045. ;zlib_debug 'fill_window'
  2046.         mov edi,[s]
  2047.         cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2048.         jl @f
  2049.                 zlib_debug 'already enough lookahead' ;Assert(..<..)
  2050.         @@:
  2051.  
  2052.         mov ecx,[edi+deflate_state.w_size]
  2053.         mov edx,[edi+deflate_state.strm]
  2054.         .cycle0: ;do
  2055. ;zlib_debug 'do'
  2056.                 mov ebx,[edi+deflate_state.window_size]
  2057.                 sub ebx,[edi+deflate_state.lookahead]
  2058.                 sub ebx,[edi+deflate_state.strstart]
  2059.  
  2060.                 ; If the window is almost full and there is insufficient lookahead,
  2061.                 ; move the upper half to the lower one to make room in the upper half.
  2062.  
  2063.                 MAX_DIST edi
  2064.                 add eax,ecx
  2065.                 cmp [edi+deflate_state.strstart],eax
  2066.                 jl .end0 ;if (..>=..)
  2067.                         push ecx
  2068.                         mov eax,[edi+deflate_state.window]
  2069.                         add eax,ecx
  2070.                         stdcall zmemcpy, [edi+deflate_state.window], eax
  2071.                         sub [edi+deflate_state.match_start],ecx
  2072.                         sub [edi+deflate_state.strstart],ecx ;we now have strstart >= MAX_DIST
  2073.                         sub [edi+deflate_state.block_start],ecx
  2074.  
  2075.                         ; Slide the hash table (could be avoided with 32 bit values
  2076.                         ; at the expense of memory usage). We slide even when level == 0
  2077.                         ; to keep the hash table consistent if we switch back to level > 0
  2078.                         ; later. (Using level 0 permanently is not an optimal usage of
  2079.                         ; zlib, so we don't care about this pathological case.)
  2080.  
  2081.                         push ebx ecx
  2082.                         ;ebx = wsize
  2083.                         ;ecx = n
  2084.                         mov ebx,ecx
  2085.                         mov ecx,[edi+deflate_state.hash_size]
  2086.                         mov esi,ecx
  2087.                         shl esi,2
  2088.                         add esi,[edi+deflate_state.head]
  2089.                         .cycle1: ;do
  2090.                                 sub esi,4
  2091.                                 mov eax,[esi]
  2092.                                 mov dword[esi],NIL
  2093.                                 cmp eax,ebx
  2094.                                 jl @f
  2095.                                         sub eax,ebx
  2096.                                         mov dword[esi],eax
  2097.                                 @@:
  2098.                         loop .cycle1 ;while (..)
  2099.  
  2100.                         mov ecx,ebx
  2101. if FASTEST eq 0
  2102.                         mov esi,ecx
  2103.                         shl esi,2
  2104.                         add esi,[edi+deflate_state.prev]
  2105.                         .cycle2: ;do
  2106.                                 sub esi,4
  2107.                                 mov eax,[esi]
  2108.                                 mov dword[esi],NIL
  2109.                                 cmp eax,ebx
  2110.                                 jl @f
  2111.                                         sub eax,ebx
  2112.                                         mov dword[esi],eax
  2113.                                 @@:
  2114.                                 ; If n is not on any hash chain, prev[n] is garbage but
  2115.                                 ; its value will never be used.
  2116.  
  2117.                         loop .cycle2 ;while (..)
  2118. end if
  2119.                         pop ecx ebx
  2120.                         add ebx,ecx
  2121.                 .end0:
  2122.                 cmp word[edx+z_stream.avail_in],0
  2123.                 je .cycle0end ;if (..==0) break
  2124.  
  2125.                 ; If there was no sliding:
  2126.                 ;    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
  2127.                 ;    more == window_size - lookahead - strstart
  2128.                 ; => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
  2129.                 ; => more >= window_size - 2*WSIZE + 2
  2130.                 ; In the BIG_MEM or MMAP case (not yet supported),
  2131.                 ;   window_size == input_size + MIN_LOOKAHEAD  &&
  2132.                 ;   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
  2133.                 ; Otherwise, window_size == 2*WSIZE so more >= 2.
  2134.                 ; If there was sliding, more >= WSIZE. So in all cases, more >= 2.
  2135.  
  2136.                 cmp ebx,2
  2137.                 jge @f
  2138.                         zlib_debug 'more < 2' ;Assert(..>=..)
  2139.                 @@:
  2140.                 mov eax,[edi+deflate_state.window]
  2141.                 add eax,[edi+deflate_state.strstart]
  2142.                 add eax,[edi+deflate_state.lookahead]
  2143.                 stdcall read_buf, edx, eax, ebx
  2144.                 add [edi+deflate_state.lookahead],eax
  2145.  
  2146.                 ; Initialize the hash value now that we have some input:
  2147.                 mov eax,[edi+deflate_state.lookahead]
  2148.                 add eax,[edi+deflate_state.insert]
  2149.                 cmp eax,MIN_MATCH
  2150.                 jl .end1 ;if (..>=..)
  2151.                         mov esi,[edi+deflate_state.strstart]
  2152.                         sub esi,[edi+deflate_state.insert]
  2153.                         ;esi = str
  2154.                         mov eax,[edi+deflate_state.window]
  2155.                         add eax,esi
  2156.                         mov [edi+deflate_state.ins_h],eax
  2157.                         inc eax
  2158.                         movzx eax,byte[eax]
  2159.             UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
  2160. if MIN_MATCH <> 3
  2161. ;            Call UPDATE_HASH() MIN_MATCH-3 more times
  2162. end if
  2163.                         .cycle3: ;while (..)
  2164.                         cmp dword[edi+deflate_state.insert],0
  2165.                         je .end1
  2166.                                 mov eax,esi
  2167.                                 add eax,MIN_MATCH-1
  2168.                                 add eax,[edi+deflate_state.window]
  2169.                                 movzx eax,byte[eax]
  2170.                                 UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
  2171. if FASTEST eq 0
  2172.                                 mov eax,[edi+deflate_state.ins_h]
  2173.                                 shl eax,2
  2174.                                 add eax,[edi+deflate_state.head]
  2175.                                 push ebx
  2176.                                 mov ebx,[edi+deflate_state.w_mask]
  2177.                                 and ebx,esi
  2178.                                 shl ebx,2
  2179.                                 add ebx,[edi+deflate_state.prev]
  2180.                                 mov eax,[eax]
  2181.                                 mov [ebx],eax
  2182.                                 pop ebx
  2183. end if
  2184.                                 mov eax,[edi+deflate_state.ins_h]
  2185.                                 shl eax,2
  2186.                                 add eax,[edi+deflate_state.head]
  2187.                                 mov [eax],esi
  2188.                                 inc esi
  2189.                                 dec dword[edi+deflate_state.insert]
  2190.                                 mov eax,[edi+deflate_state.lookahead]
  2191.                                 add eax,[edi+deflate_state.insert]
  2192.                                 cmp eax,MIN_MATCH
  2193.                                 jl .end1 ;if (..<..) break
  2194.                         jmp .cycle3
  2195.                 .end1:
  2196.                 ; If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
  2197.                 ; but this is not important since only literal bytes will be emitted.
  2198.  
  2199.                 cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2200.                 jge .cycle0end
  2201.                 cmp word[edx+z_stream.avail_in],0
  2202.                 jne .cycle0
  2203.         .cycle0end: ;while (..<.. && ..!=..)
  2204.  
  2205.         ; If the WIN_INIT bytes after the end of the current data have never been
  2206.         ; written, then zero those bytes in order to avoid memory check reports of
  2207.         ; the use of uninitialized (or uninitialised as Julian writes) bytes by
  2208.         ; the longest match routines.  Update the high water mark for the next
  2209.         ; time through here.  WIN_INIT is set to MAX_MATCH since the longest match
  2210.         ; routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
  2211.  
  2212.         mov eax,[edi+deflate_state.window_size]
  2213.         cmp [edi+deflate_state.high_water],eax
  2214.         jge .end2 ;if (..<..)
  2215.                 mov esi,[edi+deflate_state.lookahead]
  2216.                 add esi,[edi+deflate_state.strstart]
  2217.                 ;esi = curr
  2218.  
  2219.                 cmp [edi+deflate_state.high_water],esi
  2220.                 jge .end3 ;if (..<..)
  2221.                         ; Previous high water mark below current data -- zero WIN_INIT
  2222.                         ; bytes or up to end of window, whichever is less.
  2223.  
  2224.                         mov eax,[edi+deflate_state.window_size]
  2225.                         sub eax,esi
  2226.                         cmp eax,WIN_INIT
  2227.                         jle @f ;if (..>..)
  2228.                                 mov eax,WIN_INIT
  2229.                         @@:
  2230.                         mov edx,[edi+deflate_state.window]
  2231.                         add edx,esi
  2232.                         stdcall zmemzero, edx, eax
  2233.                         add eax,esi
  2234.                         mov [edi+deflate_state.high_water],eax
  2235.                         jmp .end2
  2236.                 .end3: ;else if (..<..)
  2237.                 mov eax,esi
  2238.                 add eax,WIN_INIT
  2239.                 cmp [edi+deflate_state.high_water],eax
  2240.                 jge .end2
  2241.                         ; High water mark at or above current data, but below current data
  2242.                         ; plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
  2243.                         ; to end of window, whichever is less.
  2244.  
  2245.                         ;eax = esi+WIN_INIT
  2246.                         sub eax,[edi+deflate_state.high_water]
  2247.                         mov edx,[edi+deflate_state.window_size]
  2248.                         sub edx,[edi+deflate_state.high_water]
  2249.                         cmp eax,edx ;if (..>..)
  2250.                         jle @f
  2251.                                 mov eax,edx
  2252.                         @@:
  2253.                         mov edx,[edi+deflate_state.window]
  2254.                         add edx,[edi+deflate_state.high_water]
  2255.                         stdcall zmemzero, edx, eax
  2256.                         add [edi+deflate_state.high_water],eax
  2257.         .end2:
  2258.  
  2259.         mov eax,[edi+deflate_state.window_size]
  2260.         sub eax,MIN_LOOKAHEAD
  2261.         cmp [edi+deflate_state.strstart],eax
  2262.         jle @f
  2263.                 zlib_debug 'not enough room for search' ;Assert(..<=..)
  2264.         @@:
  2265. popad
  2266.         ret
  2267. endp
  2268.  
  2269. ; ===========================================================================
  2270. ; Flush the current block, with given end-of-file flag.
  2271. ; IN assertion: strstart is set to the end of the current match.
  2272.  
  2273. macro FLUSH_BLOCK_ONLY s, last
  2274. {
  2275. local .end0
  2276.         push dword last
  2277.         mov eax,[s+deflate_state.strstart]
  2278.         sub eax,[s+deflate_state.block_start]
  2279.         push eax
  2280.         xor eax,eax
  2281.         cmp dword[s+deflate_state.block_start],0
  2282.         jl .end0
  2283.                 mov eax,[s+deflate_state.block_start]
  2284.                 add eax,[s+deflate_state.window]
  2285.         .end0:
  2286.         stdcall _tr_flush_block, s, eax
  2287.         mov eax,[s+deflate_state.strstart]
  2288.         mov [s+deflate_state.block_start],eax
  2289.         stdcall flush_pending, [s+deflate_state.strm]
  2290. ;   Tracev((stderr,"[FLUSH]"));
  2291. }
  2292.  
  2293. ; Same but force premature exit if necessary.
  2294. macro FLUSH_BLOCK s, last
  2295. {
  2296. local .end0
  2297.         FLUSH_BLOCK_ONLY s, last
  2298.         mov eax,[s+deflate_state.strm]
  2299.         cmp word[eax+z_stream.avail_out],0
  2300.         jne .end0 ;if (..==0)
  2301. if last eq 1
  2302.                 mov eax,finish_started
  2303. else
  2304.                 mov eax,need_more
  2305. end if
  2306.                 jmp .end_f
  2307.         .end0:
  2308. }
  2309.  
  2310. ; ===========================================================================
  2311. ; Copy without compression as much as possible from the input stream, return
  2312. ; the current block state.
  2313. ; This function does not insert new strings in the dictionary since
  2314. ; uncompressible data is probably not useful. This function is used
  2315. ; only for the level=0 compression option.
  2316. ; NOTE: this function should be optimized to avoid extra copying from
  2317. ; window to pending_buf.
  2318.  
  2319. ;block_state (s, flush)
  2320. ;    deflate_state *s;
  2321. ;    int flush;
  2322. align 4
  2323. proc deflate_stored uses ebx ecx edi, s:dword, flush:dword
  2324. ; Stored blocks are limited to 0xffff bytes, pending_buf is limited
  2325. ; to pending_buf_size, and each stored block has a 5 byte header:
  2326.         mov edi,[s]
  2327. zlib_debug 'deflate_stored'
  2328.  
  2329.         mov ecx,0xffff
  2330.         mov eax,[edi+deflate_state.pending_buf_size]
  2331.         sub eax,5
  2332.         cmp ecx,eax
  2333.         jle @f ;if (..>..)
  2334.                 mov ecx,eax
  2335.         @@:
  2336.         ;ecx = max_block_size
  2337.  
  2338.         ; Copy as much as possible from input to output:
  2339.         .cycle0: ;for (;;) {
  2340.                 ; Fill the window as much as possible:
  2341.                 cmp dword[edi+deflate_state.lookahead],1
  2342.                 jg .end0 ;if (..<=..)
  2343. ;            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
  2344. ;                   s->block_start >= (long)s->w_size, "slide too late");
  2345.  
  2346.                         stdcall fill_window, edi
  2347.                         cmp dword[edi+deflate_state.lookahead],0
  2348.                         jne @f
  2349.                         cmp dword[flush],Z_NO_FLUSH
  2350.                         jne @f ;if (..==0 && ..==..)
  2351.                                 mov eax,need_more
  2352.                                 jmp .end_f
  2353.                         @@:
  2354.                         cmp dword[edi+deflate_state.lookahead],0
  2355.                         je .cycle0end ;if (..==0) break ;flush the current block
  2356.                 .end0:
  2357. ;        Assert(s->block_start >= 0, "block gone");
  2358.  
  2359.                 mov eax,[edi+deflate_state.lookahead]
  2360.                 add [edi+deflate_state.strstart],eax
  2361.                 mov dword[edi+deflate_state.lookahead],0
  2362.  
  2363.                 ; Emit a stored block if pending_buf will be full:
  2364.                 mov ebx,[edi+deflate_state.block_start]
  2365.                 add ebx,ecx
  2366.                 cmp dword[edi+deflate_state.strstart],0
  2367.                 je @f
  2368.                 cmp [edi+deflate_state.strstart],ebx
  2369.                 jl .end1
  2370.                 @@: ;if (..==0 || ..>=..)
  2371.                         ; strstart == 0 is possible when wraparound on 16-bit machine
  2372.                         mov eax,[edi+deflate_state.strstart]
  2373.                         sub eax,ebx
  2374.                         mov [edi+deflate_state.lookahead],eax
  2375.                         mov [edi+deflate_state.strstart],ebx
  2376.                         FLUSH_BLOCK edi, 0
  2377.                 .end1:
  2378.                 ; Flush if we may have to slide, otherwise block_start may become
  2379.                 ; negative and the data will be gone:
  2380.  
  2381.                 MAX_DIST edi
  2382.                 mov ebx,[edi+deflate_state.strstart]
  2383.                 sub ebx,[edi+deflate_state.block_start]
  2384.                 cmp ebx,eax
  2385.                 jl .cycle0 ;if (..>=..)
  2386.                         FLUSH_BLOCK edi, 0
  2387.                 jmp .cycle0
  2388. align 4
  2389.         .cycle0end:
  2390.         mov dword[edi+deflate_state.insert],0
  2391.         cmp dword[flush],Z_FINISH
  2392.         jne @f ;if (..==..)
  2393.                 FLUSH_BLOCK edi, 1
  2394.                 mov eax,finish_done
  2395.                 jmp .end_f
  2396.         @@:
  2397.         mov eax,[edi+deflate_state.block_start]
  2398.         cmp [edi+deflate_state.strstart],eax
  2399.         jle @f ;if (..>..)
  2400.                 FLUSH_BLOCK edi, 0
  2401.         @@:
  2402.         mov eax,block_done
  2403. .end_f:
  2404.         ret
  2405. endp
  2406.  
  2407. ; ===========================================================================
  2408. ; Compress as much as possible from the input stream, return the current
  2409. ; block state.
  2410. ; This function does not perform lazy evaluation of matches and inserts
  2411. ; new strings in the dictionary only for unmatched strings or for short
  2412. ; matches. It is used only for the fast compression options.
  2413.  
  2414. ;block_state (s, flush)
  2415. ;    deflate_state *s
  2416. ;    int flush
  2417. align 4
  2418. proc deflate_fast uses ebx ecx edi, s:dword, flush:dword
  2419. locals
  2420.         bflush dd ? ;int  ;set if current block must be flushed
  2421. endl
  2422. ;ecx = hash_head ;IPos ;head of the hash chain
  2423.         mov edi,[s]
  2424. zlib_debug 'deflate_fast'
  2425.  
  2426.         .cycle0: ;for (..)
  2427.         ; Make sure that we always have enough lookahead, except
  2428.         ; at the end of the input file. We need MAX_MATCH bytes
  2429.         ; for the next match, plus MIN_MATCH bytes to insert the
  2430.         ; string following the next match.
  2431.  
  2432.                 cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2433.                 jge .end0 ;if (..<..)
  2434.                         stdcall fill_window, edi
  2435.                         cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2436.                         jge @f ;if (..<.. && ..==..)
  2437.                         cmp dword[flush],Z_NO_FLUSH
  2438.                         jne @f
  2439.                                 mov eax,need_more
  2440.                                 jmp .end_f
  2441. align 4
  2442.                         @@:
  2443.                         cmp dword[edi+deflate_state.lookahead],0
  2444.                         je .cycle0end ;if (..==0) break ;flush the current block
  2445. align 4
  2446.                 .end0:
  2447.  
  2448.                 ; Insert the string window[strstart .. strstart+2] in the
  2449.                 ; dictionary, and set hash_head to the head of the hash chain:
  2450.  
  2451.                 mov ecx,NIL
  2452.                 cmp dword[edi+deflate_state.lookahead],MIN_MATCH
  2453.                 jl @f ;if (..>=..)
  2454.                         INSERT_STRING edi, [edi+deflate_state.strstart], ecx
  2455.                 @@:
  2456.  
  2457.                 ; Find the longest match, discarding those <= prev_length.
  2458.                 ; At this point we have always match_length < MIN_MATCH
  2459.  
  2460.                 cmp ecx,NIL
  2461.                 je @f
  2462.                 MAX_DIST edi
  2463.                 mov ebx,[edi+deflate_state.strstart]
  2464.                 sub ebx,ecx
  2465.                 cmp ebx,eax
  2466.                 jg @f ;if (..!=0 && ..<=..)
  2467.                         ; To simplify the code, we prevent matches with the string
  2468.                         ; of window index 0 (in particular we have to avoid a match
  2469.                         ; of the string with itself at the start of the input file).
  2470.  
  2471.                         stdcall longest_match, edi, ecx
  2472.                         mov [edi+deflate_state.match_length],eax
  2473.                         ; longest_match() sets match_start
  2474.                 @@:
  2475.                 cmp dword[edi+deflate_state.match_length],MIN_MATCH
  2476.                 jl .end1 ;if (..>=..)
  2477.                         stdcall check_match, edi, [edi+deflate_state.strstart], [edi+deflate_state.match_start], [edi+deflate_state.match_length]
  2478.  
  2479.                         mov eax,[edi+deflate_state.strstart]
  2480.                         sub eax,[edi+deflate_state.match_start]
  2481.                         mov ebx,[edi+deflate_state.match_length]
  2482.                         sub ebx,MIN_MATCH
  2483.                         _tr_tally_dist edi, eax, ebx, [bflush]
  2484.  
  2485.                         mov eax,[edi+deflate_state.match_length]
  2486.                         sub [edi+deflate_state.lookahead],eax
  2487.  
  2488.                         ; Insert new strings in the hash table only if the match length
  2489.                         ; is not too large. This saves time but degrades compression.
  2490.  
  2491. if FASTEST eq 0
  2492.                         ;;mov eax,[edi+deflate_state.match_length]
  2493.                         cmp eax,[edi+deflate_state.max_insert_length]
  2494.                         jg .end3
  2495.                         cmp dword[edi+deflate_state.lookahead],MIN_MATCH
  2496.                         jl .end3 ;if (..<=.. && ..>=..)
  2497.                                 dec dword[edi+deflate_state.match_length] ;string at strstart already in table
  2498.                                 .cycle1: ;do {
  2499.                                         inc dword[edi+deflate_state.strstart]
  2500.                                         INSERT_STRING edi, [edi+deflate_state.strstart], ecx
  2501.                                         ; strstart never exceeds WSIZE-MAX_MATCH, so there are
  2502.                                         ; always MIN_MATCH bytes ahead.
  2503.  
  2504.                                         dec dword[edi+deflate_state.match_length]
  2505.                                         cmp dword[edi+deflate_state.match_length],0
  2506.                                         jne .cycle1 ;while (..!=0)
  2507.                                 inc dword[edi+deflate_state.strstart]
  2508.                                 jmp .end2
  2509.                         .end3: ;else
  2510. end if
  2511.  
  2512.                                 mov eax,[edi+deflate_state.match_length]
  2513.                                 add [edi+deflate_state.strstart],eax
  2514.                                 mov dword[edi+deflate_state.match_length],0
  2515.                                 mov eax,[edi+deflate_state.window]
  2516.                                 add eax,[edi+deflate_state.strstart]
  2517.                                 mov [edi+deflate_state.ins_h],eax
  2518.                                 inc eax
  2519.                                 movzx eax,byte[eax]
  2520.                                 UPDATE_HASH edi, [edi+deflate_state.ins_h], eax
  2521. if MIN_MATCH <> 3
  2522. ;                Call UPDATE_HASH() MIN_MATCH-3 more times
  2523. end if
  2524.                                 ; If lookahead < MIN_MATCH, ins_h is garbage, but it does not
  2525.                                 ; matter since it will be recomputed at next deflate call.
  2526.                         jmp .end2
  2527.                 .end1: ;else
  2528.                         ; No match, output a literal byte
  2529.                         mov eax,[edi+deflate_state.window]
  2530.                         add eax,[edi+deflate_state.strstart]
  2531.                         movzx eax,byte[eax]
  2532.                         Tracevv eax,
  2533.                         _tr_tally_lit edi, eax, [bflush]
  2534.                         dec dword[edi+deflate_state.lookahead]
  2535.                         inc dword[edi+deflate_state.strstart]
  2536.                 .end2:
  2537.                 cmp dword[bflush],0
  2538.                 je .cycle0 ;if (..)
  2539.                         FLUSH_BLOCK edi, 0
  2540.                 jmp .cycle0
  2541. align 4
  2542.         .cycle0end:
  2543.         mov eax,[edi+deflate_state.strstart]
  2544.         cmp eax,MIN_MATCH-1
  2545.         jl @f
  2546.                 mov eax,MIN_MATCH-1
  2547.         @@:
  2548.         mov [edi+deflate_state.insert],eax
  2549.         cmp dword[flush],Z_FINISH
  2550.         jne @f ;if (..==..)
  2551.                 FLUSH_BLOCK edi, 1
  2552.                 mov eax,finish_done
  2553.                 jmp .end_f
  2554.         @@:
  2555.         cmp dword[edi+deflate_state.last_lit],0
  2556.         je @f ;if (..)
  2557.                 FLUSH_BLOCK edi, 0
  2558.         @@:
  2559.         mov eax,block_done
  2560. .end_f:
  2561.         ret
  2562. endp
  2563.  
  2564. ; ===========================================================================
  2565. ; Same as above, but achieves better compression. We use a lazy
  2566. ; evaluation for matches: a match is finally adopted only if there is
  2567. ; no better match at the next window position.
  2568.  
  2569. ;block_state (s, flush)
  2570. ;    deflate_state *s
  2571. ;    int flush
  2572. align 4
  2573. proc deflate_slow uses ebx ecx edx edi, s:dword, flush:dword
  2574. locals
  2575.         bflush dd ? ;int  ;set if current block must be flushed
  2576. endl
  2577. ;ecx = hash_head ;IPos ;head of the hash chain
  2578.         mov edi,[s]
  2579. zlib_debug 'deflate_slow'
  2580.  
  2581.         ; Process the input block.
  2582.         .cycle0: ;for (;;)
  2583.         ; Make sure that we always have enough lookahead, except
  2584.         ; at the end of the input file. We need MAX_MATCH bytes
  2585.         ; for the next match, plus MIN_MATCH bytes to insert the
  2586.         ; string following the next match.
  2587.  
  2588.                 cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2589.                 jge .end0 ;if (..<..)
  2590.                         stdcall fill_window, edi
  2591.                         cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD
  2592.                         jge @f ;if (..<.. && ..==..)
  2593.                         cmp dword[flush],Z_NO_FLUSH
  2594.                         jne @f
  2595.                                 mov eax,need_more
  2596.                                 jmp .end_f
  2597. align 4
  2598.                         @@:
  2599.                         cmp dword[edi+deflate_state.lookahead],0
  2600.                         je .cycle0end ;if (..==0) break ;flush the current block
  2601. align 4
  2602.                 .end0:
  2603.  
  2604.                 ; Insert the string window[strstart .. strstart+2] in the
  2605.                 ; dictionary, and set hash_head to the head of the hash chain:
  2606.  
  2607.                 mov ecx,NIL
  2608.                 cmp dword[edi+deflate_state.lookahead],MIN_MATCH
  2609.                 jl @f ;if (..>=..)
  2610.                         INSERT_STRING edi, [edi+deflate_state.strstart], ecx
  2611.                 @@:
  2612.  
  2613.                 ; Find the longest match, discarding those <= prev_length.
  2614.  
  2615.                 mov eax,[edi+deflate_state.match_length]
  2616.                 mov [edi+deflate_state.prev_length],eax
  2617.                 mov eax,[edi+deflate_state.match_start]
  2618.                 mov [edi+deflate_state.prev_match],eax
  2619.                 mov dword[edi+deflate_state.match_length],MIN_MATCH-1
  2620.  
  2621.                 cmp ecx,NIL
  2622.                 je @f
  2623.                 mov eax,[edi+deflate_state.prev_length]
  2624.                 cmp eax,[edi+deflate_state.max_lazy_match]
  2625.                 jge @f
  2626.                 MAX_DIST edi
  2627.                 mov ebx,[edi+deflate_state.strstart]
  2628.                 sub ebx,ecx
  2629.                 cmp ebx,eax
  2630.                 jg .end1 ;if (..!=0 && ..<.. && ..<=..)
  2631.                         ; To simplify the code, we prevent matches with the string
  2632.                         ; of window index 0 (in particular we have to avoid a match
  2633.                         ; of the string with itself at the start of the input file).
  2634.  
  2635.                         stdcall longest_match, edi, ecx
  2636.                         mov [edi+deflate_state.match_length],eax
  2637.                         ; longest_match() sets match_start
  2638.  
  2639.                         cmp dword[edi+deflate_state.match_length],5
  2640.                         jg .end1
  2641.                         cmp word[edi+deflate_state.strategy],Z_FILTERED
  2642.                         jne .end1
  2643. ;            if (..<=.. && (..==..
  2644. ;#if TOO_FAR <= 32767
  2645. ;                || (s->match_length == MIN_MATCH &&
  2646. ;                    s->strstart - s->match_start > TOO_FAR)
  2647. ;end if
  2648. ;                ))
  2649.  
  2650.                                 ; If prev_match is also MIN_MATCH, match_start is garbage
  2651.                                 ; but we will ignore the current match anyway.
  2652.  
  2653.                                 mov dword[edi+deflate_state.match_length],MIN_MATCH-1
  2654.                 .end1:
  2655.                 ; If there was a match at the previous step and the current
  2656.                 ; match is not better, output the previous match:
  2657.  
  2658.  
  2659.                 mov eax,[edi+deflate_state.prev_length]
  2660.                 cmp eax,MIN_MATCH
  2661.                 jl .end2:
  2662.                 cmp [edi+deflate_state.match_length],eax
  2663.                 jg .end2: ;if (..>=.. && ..<=..)
  2664.                         mov edx,[edi+deflate_state.strstart]
  2665.                         add edx,[edi+deflate_state.lookahead]
  2666.                         sub edx,MIN_MATCH
  2667.                         ;edx = max_insert
  2668.                         ; Do not insert strings in hash table beyond this.
  2669.  
  2670.                         mov eax,[edi+deflate_state.strstart]
  2671.                         dec eax
  2672.                         stdcall check_match, edi, eax, [edi+deflate_state.prev_match], [edi+deflate_state.prev_length]
  2673.  
  2674.                         mov eax,[edi+deflate_state.strstart]
  2675.                         dec eax
  2676.                         sub eax,[edi+deflate_state.prev_match]
  2677.                         mov ebx,[edi+deflate_state.prev_length]
  2678.                         sub ebx,MIN_MATCH
  2679.                         _tr_tally_dist edi, eax, ebx, [bflush]
  2680.  
  2681.                         ; Insert in hash table all strings up to the end of the match.
  2682.                         ; strstart-1 and strstart are already inserted. If there is not
  2683.                         ; enough lookahead, the last two strings are not inserted in
  2684.                         ; the hash table.
  2685.  
  2686.                         mov eax,[edi+deflate_state.prev_length]
  2687.                         dec eax
  2688.                         sub [edi+deflate_state.lookahead],eax
  2689.                         sub dword[edi+deflate_state.prev_length],2
  2690.                         .cycle1: ;do
  2691.                                 inc dword[edi+deflate_state.strstart]
  2692.                                 cmp [edi+deflate_state.strstart],edx
  2693.                                 jg @f ;if (..<=..)
  2694.                                         INSERT_STRING edi, [edi+deflate_state.strstart], ecx
  2695.                                 @@:
  2696.                                 dec dword[edi+deflate_state.prev_length]
  2697.                                 cmp dword[edi+deflate_state.prev_length],0
  2698.                                 jne .cycle1 ;while (..!=0)
  2699.                         mov dword[edi+deflate_state.match_available],0
  2700.                         mov dword[edi+deflate_state.match_length],MIN_MATCH-1
  2701.                         inc dword[edi+deflate_state.strstart]
  2702.  
  2703.                         cmp dword[bflush],0
  2704.                         je .cycle0 ;if (..)
  2705.                                 FLUSH_BLOCK edi, 0
  2706.                         jmp .cycle0
  2707.                 .end2: ;else if (..)
  2708.                 cmp dword[edi+deflate_state.match_available],0
  2709.                 je .end3
  2710.                         ; If there was no match at the previous position, output a
  2711.                         ; single literal. If there was a match but the current match
  2712.                         ; is longer, truncate the previous match to a single literal.
  2713.  
  2714.                         mov eax,[edi+deflate_state.strstart]
  2715.                         dec eax
  2716.                         add eax,[edi+deflate_state.window]
  2717.                         movzx eax,byte[eax]
  2718.                         Tracevv eax,
  2719.                         _tr_tally_lit edi, eax, [bflush]
  2720.                         cmp dword[bflush],0
  2721.                         je @f ;if (..)
  2722.                                 FLUSH_BLOCK_ONLY edi, 0
  2723.                         @@:
  2724.                         inc dword[edi+deflate_state.strstart]
  2725.                         dec dword[edi+deflate_state.lookahead]
  2726.                         mov eax,[edi+deflate_state.strm]
  2727.                         cmp word[eax+z_stream.avail_out],0
  2728.                         jne .cycle0 ;if (..==0) return ..
  2729.                                 mov eax,need_more
  2730.                                 jmp .end_f
  2731.                         jmp .cycle0 ;.end4
  2732.                 .end3: ;else
  2733.                         ; There is no previous match to compare with, wait for
  2734.                         ; the next step to decide.
  2735.  
  2736.                         mov dword[edi+deflate_state.match_available],1
  2737.                         inc dword[edi+deflate_state.strstart]
  2738.                         dec dword[edi+deflate_state.lookahead]
  2739.                 ;.end4:
  2740.                 jmp .cycle0
  2741.         .cycle0end:
  2742.         cmp dword[flush],Z_NO_FLUSH
  2743.         jne @f
  2744.                 zlib_debug 'no flush?' ;Assert (..!=..)
  2745.         @@:
  2746.         cmp dword[edi+deflate_state.match_available],0
  2747.         je @f ;if (..)
  2748.                 mov eax,[edi+deflate_state.strstart]
  2749.                 dec eax
  2750.                 add eax,[edi+deflate_state.window]
  2751.                 movzx eax,byte[eax]
  2752.                 Tracevv eax,
  2753.                 _tr_tally_lit edi, eax, [bflush]
  2754.                 mov dword[edi+deflate_state.match_available],0
  2755.         @@:
  2756.         mov eax,[edi+deflate_state.strstart]
  2757.         cmp eax,MIN_MATCH-1
  2758.         jl @f
  2759.                 mov eax,MIN_MATCH-1
  2760.         @@:
  2761.         mov [edi+deflate_state.insert],eax
  2762.         cmp dword[flush],Z_FINISH
  2763.         jne @f ;if (..==..)
  2764.                 FLUSH_BLOCK edi, 1
  2765.                 mov eax,finish_done
  2766.                 jmp .end_f
  2767.         @@:
  2768.         cmp dword[edi+deflate_state.last_lit],0
  2769.         je @f ;if (..)
  2770.                 FLUSH_BLOCK edi, 0
  2771.         @@:
  2772.         mov eax,block_done
  2773. .end_f:
  2774.         ret
  2775. endp
  2776.  
  2777. ; ===========================================================================
  2778. ; For Z_RLE, simply look for runs of bytes, generate matches only of distance
  2779. ; one.  Do not maintain a hash table.  (It will be regenerated if this run of
  2780. ; deflate switches away from Z_RLE.)
  2781.  
  2782. ;block_state (s, flush)
  2783. ;    deflate_state *s;
  2784. ;    int flush;
  2785. align 4
  2786. proc deflate_rle uses ecx edx edi esi, s:dword, flush:dword
  2787. locals
  2788.         bflush dd ? ;int ;set if current block must be flushed
  2789. ;    uInt prev;              /* byte at distance one to match */
  2790. ;    Bytef *scan, *strend;   /* scan goes up to strend for length of run */    
  2791. endl
  2792.         mov edx,[s]
  2793. zlib_debug 'deflate_rle'
  2794.         .cycle0: ;for (;;)
  2795.                 ; Make sure that we always have enough lookahead, except
  2796.                 ; at the end of the input file. We need MAX_MATCH bytes
  2797.                 ; for the longest run, plus one for the unrolled loop.
  2798.                 cmp dword[edx+deflate_state.lookahead],MAX_MATCH
  2799.                 jg .end0 ;if (..<=..)
  2800.                         stdcall fill_window, edx
  2801.                         cmp dword[edx+deflate_state.lookahead],MAX_MATCH
  2802.                         jg @f
  2803.                         cmp dword[flush],Z_NO_FLUSH
  2804.                         jne @f ;if (..<=.. && ..==..)
  2805.                                 mov eax,need_more
  2806.                                 jmp .end_f
  2807. align 4
  2808.                         @@:
  2809.                         cmp dword[edx+deflate_state.lookahead],0
  2810.                         je .cycle0end ;flush the current block
  2811. align 4
  2812.                 .end0:
  2813.  
  2814.                 ; See how many times the previous byte repeats
  2815.                 mov dword[edx+deflate_state.match_length],0
  2816.                 cmp dword[edx+deflate_state.lookahead],MIN_MATCH
  2817.                 jl .end1
  2818.                 cmp dword[edx+deflate_state.strstart],0
  2819.                 jle .end1 ;if (..>=.. && ..>..)
  2820.                         mov esi,[edx+deflate_state.window]
  2821.                         add esi,[edx+deflate_state.strstart]
  2822.                         dec esi
  2823.                         lodsb
  2824.                         mov edi,esi
  2825.                         scasb
  2826.                         jnz .end2
  2827.                         scasb
  2828.                         jnz .end2
  2829.                         scasb
  2830.                         jnz .end2 ;if (..==.. && ..==.. && ..==..)
  2831.                                 ;edi = scan
  2832.                                 ; al = prev
  2833.                                 ;ecx = strend-scan
  2834.                                 mov ecx,MAX_MATCH-2
  2835.                                 repz scasb
  2836.                                 sub edi,[edx+deflate_state.window]
  2837.                                 sub edi,[edx+deflate_state.strstart]
  2838.                                 mov [edx+deflate_state.match_length],edi
  2839.                                 mov eax,[edx+deflate_state.lookahead]
  2840.                                 cmp [edx+deflate_state.match_length],eax
  2841.                                 jle .end2
  2842.                                         mov [edx+deflate_state.match_length],eax
  2843.                         .end2:
  2844.                         mov eax,[edx+deflate_state.window_size]
  2845.                         dec eax
  2846.                         add eax,[edx+deflate_state.window]
  2847.                         cmp edi,eax
  2848.                         jle .end1
  2849.                                 zlib_debug 'wild scan' ;Assert(..<=..)
  2850.                 .end1:
  2851.  
  2852.                 ; Emit match if have run of MIN_MATCH or longer, else emit literal
  2853.                 cmp dword[edx+deflate_state.match_length],MIN_MATCH
  2854.                 jl @f ;if (..>=..)
  2855.                         push dword[edx+deflate_state.match_length]
  2856.                         mov eax,[edx+deflate_state.strstart]
  2857.                         dec eax
  2858.                         stdcall check_match, edx, [edx+deflate_state.strstart], eax
  2859.  
  2860.                         mov eax,[edx+deflate_state.match_length]
  2861.                         sub eax,MIN_MATCH
  2862.                         _tr_tally_dist edx, 1, eax, [bflush]
  2863.  
  2864.                         mov eax,[edx+deflate_state.match_length]
  2865.                         sub [edx+deflate_state.lookahead],eax
  2866.                         add [edx+deflate_state.strstart],eax
  2867.                         mov dword[edx+deflate_state.match_length],0
  2868.                         jmp .end3
  2869.                 @@: ;else
  2870.                         ; No match, output a literal byte
  2871.                         mov eax,[edx+deflate_state.strstart]
  2872.                         add eax,[edx+deflate_state.window]
  2873.                         movzx eax,byte[eax]
  2874.                         Tracevv eax,
  2875.                         _tr_tally_lit edx, eax, [bflush]
  2876.                         dec dword[edx+deflate_state.lookahead]
  2877.                         inc dword[edx+deflate_state.strstart]
  2878.                 .end3:
  2879.                 cmp dword[bflush],0
  2880.                 je .cycle0 ;if (..)
  2881.                         FLUSH_BLOCK edx, 0
  2882.                 jmp .cycle0
  2883. align 4
  2884.         .cycle0end:
  2885.         mov dword[edx+deflate_state.insert],0
  2886.         cmp dword[flush],Z_FINISH
  2887.         jne @f ;if (..==..)
  2888.                 FLUSH_BLOCK edx, 1
  2889.                 mov eax,finish_done
  2890.                 jmp .end_f
  2891.         @@:
  2892.         cmp dword[edx+deflate_state.last_lit],0
  2893.         je @f ;if (..)
  2894.                 FLUSH_BLOCK edx, 0
  2895.         @@:
  2896.         mov eax,block_done
  2897. .end_f:
  2898.         ret
  2899. endp
  2900.  
  2901. ; ===========================================================================
  2902. ; For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
  2903. ; (It will be regenerated if this run of deflate switches away from Huffman.)
  2904.  
  2905. ;block_state (s, flush)
  2906. ;    deflate_state *s;
  2907. ;    int flush;
  2908. align 4
  2909. proc deflate_huff uses ebx edi, s:dword, flush:dword
  2910. locals
  2911.         bflush dd ? ;int ;set if current block must be flushed
  2912. endl
  2913.         mov edi,[s]
  2914. zlib_debug 'deflate_huff'
  2915.         .cycle0: ;for (;;)
  2916.                 ; Make sure that we have a literal to write.
  2917.                 cmp dword[edi+deflate_state.lookahead],0
  2918.                 jne .end0 ;if (..==0)
  2919.                         stdcall fill_window, edi
  2920.                         cmp dword[edi+deflate_state.lookahead],0
  2921.                         jne .end0 ;if (..==0)
  2922.                                 cmp dword[flush],Z_NO_FLUSH
  2923.                                 jne @f ;if (..==..)
  2924.                                         mov eax,need_more
  2925.                                         jmp .end_f
  2926. align 4
  2927.                                 @@:
  2928.                         jmp .cycle0end ;flush the current block
  2929. align 4
  2930.                 .end0:
  2931.  
  2932.                 ; Output a literal byte
  2933.                 mov dword[edi+deflate_state.match_length],0
  2934.                 mov eax,[edi+deflate_state.strstart]
  2935.                 add eax,[edi+deflate_state.window]
  2936.                 movzx eax,byte[eax]
  2937.                 Tracevv eax,
  2938.                 _tr_tally_lit edi, eax, [bflush]
  2939.                 dec dword[edi+deflate_state.lookahead]
  2940.                 inc dword[edi+deflate_state.strstart]
  2941.                 cmp dword[bflush],0
  2942.                 je @f ;if (..)
  2943.                         FLUSH_BLOCK edi, 0
  2944.                 @@:
  2945.                 jmp .cycle0
  2946. align 4
  2947.         .cycle0end:
  2948.         mov dword[edi+deflate_state.insert],0
  2949.         cmp dword[flush],Z_FINISH
  2950.         jne @f ;if (..==..)
  2951.                 FLUSH_BLOCK edi, 1
  2952.                 mov eax,finish_done
  2953.                 jmp .end_f
  2954.         @@:
  2955.         cmp dword[edi+deflate_state.last_lit],0
  2956.         je @f ;if (..)
  2957.                 FLUSH_BLOCK edi, 0
  2958.         @@:
  2959.         mov eax,block_done
  2960. .end_f:
  2961.         ret
  2962. endp
  2963.