Subversion Repositories Kolibri OS

Rev

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