From 87008e93c5fb7f69e1907d96e694d83ba131c1d1 Mon Sep 17 00:00:00 2001 From: IgorA Date: Wed, 26 Oct 2016 19:35:35 +0000 Subject: [PATCH] add 'zlib.obj' git-svn-id: svn://kolibrios.org@6617 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/fs/kfar/trunk/zlib/adler32.asm | 309 +++ programs/fs/kfar/trunk/zlib/build.bat | 5 + programs/fs/kfar/trunk/zlib/crc32.asm | 278 ++ programs/fs/kfar/trunk/zlib/debug.inc | 440 ++++ programs/fs/kfar/trunk/zlib/deflate.asm | 2962 ++++++++++++++++++++++ programs/fs/kfar/trunk/zlib/deflate.inc | 353 +++ programs/fs/kfar/trunk/zlib/example1.asm | 287 +++ programs/fs/kfar/trunk/zlib/trees.asm | 2096 +++++++++++++++ programs/fs/kfar/trunk/zlib/trees.inc | 139 + programs/fs/kfar/trunk/zlib/zconf.inc | 165 ++ programs/fs/kfar/trunk/zlib/zlib.asm | 179 ++ programs/fs/kfar/trunk/zlib/zlib.inc | 262 ++ programs/fs/kfar/trunk/zlib/zlib.txt | 1405 ++++++++++ programs/fs/kfar/trunk/zlib/zutil.asm | 203 ++ programs/fs/kfar/trunk/zlib/zutil.inc | 88 + 15 files changed, 9171 insertions(+) create mode 100644 programs/fs/kfar/trunk/zlib/adler32.asm create mode 100644 programs/fs/kfar/trunk/zlib/build.bat create mode 100644 programs/fs/kfar/trunk/zlib/crc32.asm create mode 100644 programs/fs/kfar/trunk/zlib/debug.inc create mode 100644 programs/fs/kfar/trunk/zlib/deflate.asm create mode 100644 programs/fs/kfar/trunk/zlib/deflate.inc create mode 100644 programs/fs/kfar/trunk/zlib/example1.asm create mode 100644 programs/fs/kfar/trunk/zlib/trees.asm create mode 100644 programs/fs/kfar/trunk/zlib/trees.inc create mode 100644 programs/fs/kfar/trunk/zlib/zconf.inc create mode 100644 programs/fs/kfar/trunk/zlib/zlib.asm create mode 100644 programs/fs/kfar/trunk/zlib/zlib.inc create mode 100644 programs/fs/kfar/trunk/zlib/zlib.txt create mode 100644 programs/fs/kfar/trunk/zlib/zutil.asm create mode 100644 programs/fs/kfar/trunk/zlib/zutil.inc diff --git a/programs/fs/kfar/trunk/zlib/adler32.asm b/programs/fs/kfar/trunk/zlib/adler32.asm new file mode 100644 index 0000000000..15a0cef45d --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/adler32.asm @@ -0,0 +1,309 @@ +; adler32.asm -- compute the Adler-32 checksum of a data stream +; Copyright (C) 1995-2011 Mark Adler +; For conditions of distribution and use, see copyright notice in zlib.h + + +BASE equ 65521 ;largest prime smaller than 65536 +NMAX equ 5552 +; NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + +macro DO1 buf,i +{ + mov eax,buf + add eax,i + movzx eax,byte[eax] + add [adler],eax + mov eax,[adler] + add [sum2],eax +} +macro DO2 buf,i +{ + DO1 buf,i + DO1 buf,i+1 +} +macro DO4 buf,i +{ + DO2 buf,i + DO2 buf,i+2 +} +macro DO8 buf,i +{ + DO4 buf,i + DO4 buf,i+4 +} +macro DO16 buf +{ + DO8 buf,0 + DO8 buf,8 +} + +; use NO_DIVIDE if your processor does not do division in hardware -- +; try it both ways to see which is faster +; note that this assumes BASE is 65521, where 65536 % 65521 == 15 +; (thank you to John Reiser for pointing this out) +macro CHOP a +{ +if NO_DIVIDE eq 1 + mov eax,a + shr eax,16 + and a,0xffff + shl eax,4 + add a,eax + shr eax,4 + sub a,eax +end if +} +macro MOD28 a +{ +if NO_DIVIDE eq 1 +local .end0 + CHOP a + cmp a,BASE + jl .end0 ;if (..>=..) + sub a,BASE + .end0: +else +push eax ecx edx + mov eax,a + xor edx,edx + mov ecx,BASE + div ecx + mov a,edx +pop edx ecx eax +end if +} +macro MOD a +{ +if NO_DIVIDE eq 1 + CHOP a + MOD28 a +else +push eax ecx edx + mov eax,a + xor edx,edx + mov ecx,BASE + div ecx + mov a,edx +pop edx ecx eax +end if +} +macro MOD63 a +{ +if NO_DIVIDE eq 1 +;this assumes a is not negative +; z_off64_t tmp = a >> 32; +; a &= 0xffffffff; +; a += (tmp << 8) - (tmp << 5) + tmp; +; tmp = a >> 16; +; a &= 0xffff; +; a += (tmp << 4) - tmp; +; tmp = a >> 16; +; a &= 0xffff; +; a += (tmp << 4) - tmp; +; if (a >= BASE) a -= BASE; +else +push eax ecx edx + mov eax,a + xor edx,edx + mov ecx,BASE + div ecx + mov a,edx +pop edx ecx eax +end if +} + +; ========================================================================= +;uLong (adler, buf, len) +; uLong adler +; const Bytef *buf +; uInt len +align 4 +proc adler32 uses ebx edx, adler:dword, buf:dword, len:dword +locals + sum2 dd ? ;uLong +endl +;zlib_debug 'adler32 adler = %d',[adler] + ; split Adler-32 into component sums + mov eax,[adler] + shr eax,16 + mov [sum2],eax + and [adler],0xffff + mov ebx,[buf] + + ; in case user likes doing a byte at a time, keep it fast + cmp dword[len],1 + jne .end0 ;if (..==..) + movzx eax,byte[ebx] + add [adler],eax + cmp dword[adler],BASE + jl @f ;if (..>=..) + sub dword[adler],BASE + @@: + mov eax,[adler] + add [sum2],eax + cmp dword[sum2],BASE + jl @f ;if (..>=..) + sub dword[sum2],BASE + @@: + jmp .combine +align 4 + .end0: + + ; initial Adler-32 value (deferred check for len == 1 speed) + cmp ebx,Z_NULL + jne @f ;if (..==0) + xor eax,eax + inc eax + jmp .end_f +align 4 + @@: + + ; in case short lengths are provided, keep it somewhat fast + cmp dword[len],16 + jge .end1 ;if (..<..) + .cycle0: + cmp dword[len],0 + jne @f ;while (..) + movzx eax,byte[ebx] + inc ebx + add [adler],eax + mov eax,[adler] + add [sum2],eax + dec dword[len] + jmp .cycle0 +align 4 + @@: + cmp dword[adler],BASE + jl @f ;if (..>=..) + sub dword[adler],BASE + @@: + MOD28 dword[sum2] ;only added so many BASE's + jmp .combine +align 4 + .end1: + + ; do length NMAX blocks -- requires just one modulo operation + .cycle3: + cmp dword[len],NMAX + jl .cycle3end ;while (..>=..) + sub dword[len],NMAX + mov edx,NMAX/16 ;NMAX is divisible by 16 + .cycle1: ;do + DO16 ebx ;16 sums unrolled + add ebx,16 + dec edx + cmp edx,0 + jg .cycle1 ;while (..) + MOD [adler] + MOD [sum2] + jmp .cycle3 +align 4 + .cycle3end: + + ; do remaining bytes (less than NMAX, still just one modulo) + cmp dword[len],0 + jne .end2 ;if (..) ;avoid modulos if none remaining + @@: + cmp dword[len],16 + jl .cycle2 ;while (..>=..) + sub dword[len],16 + DO16 ebx + add ebx,16 + jmp @b +align 4 + .cycle2: + cmp dword[len],0 + jne @f ;while (..) + movzx eax,byte[ebx] + inc ebx + add [adler],eax + mov eax,[adler] + add [sum2],eax + dec dword[len] + jmp .cycle2 +align 4 + @@: + MOD [adler] + MOD [sum2] + .end2: + + ; return recombined sums +.combine: + mov eax,[sum2] + shl eax,16 + or eax,[adler] +.end_f: +;zlib_debug ' adler32.ret = %d',eax + ret +endp + +; ========================================================================= +;uLong (adler1, adler2, len2) +; uLong adler1 +; uLong adler2 +; z_off64_t len2 +align 4 +proc adler32_combine_, adler1:dword, adler2:dword, len2:dword +locals + sum1 dd ? ;uLong + sum2 dd ? ;uLong +; unsigned rem; +endl + ; for negative len, return invalid adler32 as a clue for debugging + cmp dword[len2],0 + jge @f ;if (..<0) + mov eax,0xffffffff + jmp .end_f + @@: + + ; the derivation of this formula is left as an exercise for the reader +; MOD63(len2) ;assumes len2 >= 0 +; rem = (unsigned)len2; +; sum1 = adler1 & 0xffff; +; sum2 = rem * sum1; +; MOD(sum2); +; sum1 += (adler2 & 0xffff) + BASE - 1; +; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + cmp dword[sum1],BASE + jl @f ;if (..>=..) + sub dword[sum1],BASE + @@: + cmp dword[sum1],BASE + jl @f ;if (..>=..) + sub dword[sum1],BASE + @@: + cmp dword[sum2],BASE shl 1 + jl @f ;if (..>=..) + sub dword[sum2],BASE shl 1 + @@: + cmp dword[sum2],BASE + jl @f ;if (..>=..) + sub dword[sum2],BASE + @@: + mov eax,[sum2] + shl eax,16 + or eax,[sum1] +.end_f: + ret +endp + +; ========================================================================= +;uLong (adler1, adler2, len2) +; uLong adler1 +; uLong adler2 +; z_off_t len2 +align 4 +proc adler32_combine, adler1:dword, adler2:dword, len2:dword + stdcall adler32_combine_, [adler1], [adler2], [len2] + ret +endp + +;uLong (adler1, adler2, len2) +; uLong adler1 +; uLong adler2 +; z_off64_t len2 +align 4 +proc adler32_combine64, adler1:dword, adler2:dword, len2:dword + stdcall adler32_combine_, [adler1], [adler2], [len2] + ret +endp diff --git a/programs/fs/kfar/trunk/zlib/build.bat b/programs/fs/kfar/trunk/zlib/build.bat new file mode 100644 index 0000000000..9181f5e104 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/build.bat @@ -0,0 +1,5 @@ +@fasm.exe -m 32768 zlib.asm zlib.obj +@kpack zlib.obj +@fasm.exe -m 32768 example1.asm example1.kex +@kpack example1.kex +pause \ No newline at end of file diff --git a/programs/fs/kfar/trunk/zlib/crc32.asm b/programs/fs/kfar/trunk/zlib/crc32.asm new file mode 100644 index 0000000000..7ee67d220d --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/crc32.asm @@ -0,0 +1,278 @@ +; crc32.asm -- compute the CRC-32 of a data stream +; Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler +; For conditions of distribution and use, see copyright notice in zlib.inc + +; Thanks to Rodney Brown for his contribution of faster +; CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing +; tables for updating the shift register in one step with three exclusive-ors +; instead of four steps with four exclusive-ors. This results in about a +; factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + + +; Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore +; protection on the static variables used to control the first-use generation +; of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should +; first call get_crc_table() to initialize the tables before allowing more than +; one thread to use crc32(). + +; Definitions for doing the crc four data bytes at a time. + +TBLS equ 1 + +if DYNAMIC_CRC_TABLE eq 1 + +align 4 +crc_table_empty dd 1 +align 4 +crc_table rd TBLS*256 + +; Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: +; x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + +; Polynomials over GF(2) are represented in binary, one bit per coefficient, +; with the lowest powers in the most significant bit. Then adding polynomials +; is just exclusive-or, and multiplying a polynomial by x is a right shift by +; one. If we call the above polynomial p, and represent a byte as the +; polynomial q, also with the lowest power in the most significant bit (so the +; byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, +; where a mod b means the remainder after dividing a by b. + +; This calculation is done using the shift-register method of multiplying and +; taking the remainder. The register is initialized to zero, and for each +; incoming bit, x^32 is added mod p to the register if the bit is a one (where +; x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by +; x (which is shifting right by one and adding x^32 mod p if the bit shifted +; out is a one). We start with the highest power (least significant bit) of +; q and repeat for all eight bits of q. + +; The first table is simply the CRC of all possible eight bit values. This is +; all the information needed to generate CRCs on data a byte at a time for all +; combinations of CRC register values and incoming bytes. The remaining tables +; allow for word-at-a-time CRC calculation for both big-endian and little- +; endian machines, where a word is four bytes. + +;void () +align 4 +proc make_crc_table uses ecx edx edi +zlib_debug 'make_crc_table' + + ; generate a crc for every 8-bit value + xor edx, edx + mov edi, crc_table +.1: + mov ecx, 8 + mov eax, edx +.2: + shr eax, 1 + jnc @f + xor eax, 0xEDB88320 +@@: + loop .2 + stosd + inc dl + jnz .1 + + mov dword[crc_table_empty],0 + ret +endp + +else ;!DYNAMIC_CRC_TABLE +; ======================================================================== +; Tables of CRC-32s of all single-byte values, made by make_crc_table(). + +;include 'crc32.inc' +end if ;DYNAMIC_CRC_TABLE + +; ========================================================================= +; This function can be used by asm versions of crc32() + +;const z_crc_t* () +align 4 +proc get_crc_table +if DYNAMIC_CRC_TABLE eq 1 + cmp dword[crc_table_empty],0 + je @f ;if (..) + call make_crc_table + @@: +end if ;DYNAMIC_CRC_TABLE + mov eax,crc_table + ret +endp + +; ========================================================================= +macro DO1 +{ + xor al,byte[esi] + xor al,ah + mov eax,[crc_table+eax*4] + inc esi +} +macro DO8 +{ + DO1 + DO1 + DO1 + DO1 + DO1 + DO1 + DO1 + DO1 +} + +; ========================================================================= +;unsigned long (crc, buf, len) +; unsigned long crc +; unsigned char *buf +; uInt len +align 4 +proc calc_crc32 uses ecx esi, p1crc:dword, buf:dword, len:dword + xor eax,eax + mov esi,[buf] +zlib_debug 'calc_crc32 buf = %d',esi + cmp esi,Z_NULL + je .end_f ;if (..==0) return 0 + +if DYNAMIC_CRC_TABLE eq 1 + cmp dword[crc_table_empty],0 + je @f ;if (..) + call make_crc_table + @@: +end if + + mov eax,[p1crc] + xor eax,0xffffffff + mov [p1crc],eax + mov ecx,[len] +align 4 + .cycle0: + cmp ecx,8 + jl @f + DO8 + sub ecx,8 + jmp .cycle0 +align 4 + @@: + cmp ecx,1 + jl @f + DO1 + dec ecx + jmp @b + @@: + mov eax,[p1crc] + xor eax,0xffffffff +.end_f: + ret +endp + +GF2_DIM equ 32 ;dimension of GF(2) vectors (length of CRC) + +; ========================================================================= +;unsigned long (mat, vec) +; unsigned long *mat +; unsigned long vec +align 4 +proc gf2_matrix_times, mat:dword, vec:dword +; unsigned long sum; + +; sum = 0; +; while (vec) { +; if (vec & 1) +; sum ^= *mat; +; vec >>= 1; +; mat++; +; } +; return sum; + ret +endp + +; ========================================================================= +;local void (square, mat) +; unsigned long *square +; unsigned long *mat +align 4 +proc gf2_matrix_square, square:dword, mat:dword +; int n; + +; for (n = 0; n < GF2_DIM; n++) +; square[n] = gf2_matrix_times(mat, mat[n]); + ret +endp + +; ========================================================================= +;uLong (crc1, crc2, len2) +; uLong crc1 +; uLong crc2 +; z_off64_t len2 +align 4 +proc crc32_combine_, crc1:dword, crc2:dword, len2:dword +; int n; +; unsigned long row; +; unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ +; unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + ; degenerate case (also disallow negative lengths) +; if (len2 <= 0) +; return crc1; + + ; put operator for one zero bit in odd +; odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ +; row = 1; +; for (n = 1; n < GF2_DIM; n++) { +; odd[n] = row; +; row <<= 1; +; } + + ; put operator for two zero bits in even +; gf2_matrix_square(even, odd); + + ; put operator for four zero bits in odd +; gf2_matrix_square(odd, even); + + ; apply len2 zeros to crc1 (first square will put the operator for one + ; zero byte, eight zero bits, in even) +; do { + ; apply zeros operator for this bit of len2 +; gf2_matrix_square(even, odd); +; if (len2 & 1) +; crc1 = gf2_matrix_times(even, crc1); +; len2 >>= 1; + + ; if no more bits set, then done +; if (len2 == 0) +; break; + + ; another iteration of the loop with odd and even swapped +; gf2_matrix_square(odd, even); +; if (len2 & 1) +; crc1 = gf2_matrix_times(odd, crc1); +; len2 >>= 1; + + ; if no more bits set, then done +; } while (len2 != 0); + + ; return combined crc +; crc1 ^= crc2; +; return crc1; + ret +endp + +; ========================================================================= +;uLong (crc1, crc2, len2) +; uLong crc1 +; uLong crc2 +; z_off_t len2 +align 4 +proc crc32_combine, crc1:dword, crc2:dword, len2:dword + stdcall crc32_combine_, [crc1], [crc2], [len2] + ret +endp + +;uLong (crc1, crc2, len2) +; uLong crc1 +; uLong crc2 +; z_off64_t len2 +align 4 +proc crc32_combine64, crc1:dword, crc2:dword, len2:dword + stdcall crc32_combine_, [crc1], [crc2], [len2] + ret +endp diff --git a/programs/fs/kfar/trunk/zlib/debug.inc b/programs/fs/kfar/trunk/zlib/debug.inc new file mode 100644 index 0000000000..2f4c053e93 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/debug.inc @@ -0,0 +1,440 @@ + +txt_zv db '*',0 +txt_sp db ' ',0 +txt_buf db '1234',0 + rd 1 + +buf_param rb 80 + +macro cStr dest,txt +{ +local .end_t +local .m_txt +jmp .end_t +align 4 + .m_txt db txt,0 +align 4 +.end_t: +if dest eq + mov eax,.m_txt +else + mov dest,.m_txt +end if +} + +;for debug +tz1 db 'next_in',13,10,0 +tz2 db 'avail_in',13,10,0 +tz3 db 'total_in',13,10,0 +tz4 db 'next_out',13,10,0 +tz5 db 'avail_out',13,10,0 +tz6 db 'total_out',13,10,0 +tz7 db 'msg',13,10,0 +tz8 db 'state',13,10,0 +tz9 db 'zalloc',13,10,0 +tz10 db 'zfree',13,10,0 +tz11 db 'opaque',13,10,0 +tz12 db 'data_type',13,10,0 +tz13 db 'adler',13,10,0 +tz14 db 'reserved',13,10,0 + +sv_2: +dd z_stream.next_in,4,tz1 +dd z_stream.avail_in,2,tz2 +dd z_stream.total_in,4,tz3 +dd z_stream.next_out,4,tz4 +dd z_stream.avail_out,2,tz5 +dd z_stream.total_out,4,tz6 +dd z_stream.msg,4,tz7 +dd z_stream.state,4,tz8 +dd z_stream.zalloc,4,tz9 +dd z_stream.zfree,4,tz10 +dd z_stream.opaque,4,tz11 +dd z_stream.data_type,2,tz12 +dd z_stream.adler,4,tz13 +dd z_stream.reserved,4,tz14 +dd 0,0 + +ta1 db 'strm',13,10,0 +ta2 db 'status',13,10,0 +ta3 db 'pending_buf',13,10,0 +ta4 db 'pending_buf_size',13,10,0 +ta5 db 'pending_out',13,10,0 +ta6 db 'pending',13,10,0 +ta7 db 'wrap',13,10,0 +ta8 db 'gzhead',13,10,0 +ta9 db 'gzindex',13,10,0 +ta10 db 'method',13,10,0 +ta11 db 'last_flush',13,10,0 +ta12 db 'w_size',13,10,0 +ta13 db 'w_bits',13,10,0 +ta14 db 'w_mask',13,10,0 +ta15 db 'window',13,10,0 +ta16 db 'window_size',13,10,0 +ta17 db 'prev',13,10,0 +ta18 db 'head',13,10,0 +ta19 db 'ins_h',13,10,0 +ta20 db 'hash_size',13,10,0 +ta21 db 'hash_bits',13,10,0 +ta22 db 'hash_mask',13,10,0 +ta23 db 'hash_shift',13,10,0 +ta24 db 'block_start',13,10,0 +ta25 db 'match_length',13,10,0 +ta26 db 'prev_match',13,10,0 +ta27 db 'match_available',13,10,0 +ta28 db 'strstart',13,10,0 +ta29 db 'match_start',13,10,0 +ta30 db 'lookahead',13,10,0 +ta31 db 'prev_length',13,10,0 +ta32 db 'max_chain_length',13,10,0 +ta33 db 'max_lazy_match',13,10,0 +ta34 db 'level',13,10,0 +ta35 db 'strategy',13,10,0 +ta36 db 'good_match',13,10,0 +ta37 db 'nice_match',13,10,0 +ta38 db 'dyn_ltree',13,10,0 +ta39 db 'dyn_dtree',13,10,0 +ta40 db 'bl_tree',13,10,0 +ta41 db 'l_desc',13,10,0 +ta42 db 'd_desc',13,10,0 +ta43 db 'bl_desc',13,10,0 +ta44 db 'bl_count',13,10,0 +ta45 db 'heap',13,10,0 +ta46 db 'heap_len',13,10,0 +ta47 db 'heap_max',13,10,0 +ta48 db 'depth',13,10,0 +ta49 db 'l_buf',13,10,0 +ta50 db 'lit_bufsize',13,10,0 +ta51 db 'last_lit',13,10,0 +ta52 db 'd_buf',13,10,0 +ta53 db 'opt_len',13,10,0 +ta54 db 'static_len',13,10,0 +ta55 db 'matches',13,10,0 +ta56 db 'insert',13,10,0 +; db 'compressed_len',13,10,0 +; db 'bits_sent',13,10,0 +ta59 db 'bi_buf',13,10,0 +ta60 db 'bi_valid',13,10,0 +ta61 db 'high_water',13,10,0 + +sv_3: +dd deflate_state.strm,4,ta1 +dd deflate_state.status,4,ta2 +dd deflate_state.pending_buf,4,ta3 +dd deflate_state.pending_buf_size,4,ta4 +dd deflate_state.pending_out,4,ta5 +dd deflate_state.pending,2,ta6 +dd deflate_state.wrap,4,ta7 +dd deflate_state.gzhead,4,ta8 +dd deflate_state.gzindex,4,ta9 +dd deflate_state.method,1,ta10 +dd deflate_state.last_flush,4,ta11 +dd deflate_state.w_size,4,ta12 +dd deflate_state.w_bits,4,ta13 +dd deflate_state.w_mask,4,ta14 +dd deflate_state.window,4,ta15 +dd deflate_state.window_size,4,ta16 +dd deflate_state.prev,4,ta17 +dd deflate_state.head,4,ta18 +dd deflate_state.ins_h,4,ta19 +dd deflate_state.hash_size,4,ta20 +dd deflate_state.hash_bits,4,ta21 +dd deflate_state.hash_mask,4,ta22 +dd deflate_state.hash_shift,4,ta23 +dd deflate_state.block_start,4,ta24 +dd deflate_state.match_length,4,ta25 +dd deflate_state.prev_match,4,ta26 +dd deflate_state.match_available,4,ta27 +dd deflate_state.strstart,4,ta28 +dd deflate_state.match_start,4,ta29 +dd deflate_state.lookahead,4,ta30 +dd deflate_state.prev_length,4,ta31 +dd deflate_state.max_chain_length,4,ta32 +dd deflate_state.max_lazy_match,4,ta33 +dd deflate_state.level,2,ta34 +dd deflate_state.strategy,2,ta35 +dd deflate_state.good_match,4,ta36 +dd deflate_state.nice_match,4,ta37 +dd deflate_state.dyn_ltree,((2*HEAP_SIZE) shl 16)+2,ta38 +dd deflate_state.dyn_dtree,((2*(2*D_CODES+1)) shl 16)+2,ta39 +dd deflate_state.bl_tree,((2*(2*BL_CODES+1)) shl 16)+2,ta40 +dd deflate_state.l_desc,(3 shl 16)+4,ta41 +dd deflate_state.d_desc,(3 shl 16)+4,ta42 +dd deflate_state.bl_desc,(3 shl 16)+4,ta43 +dd deflate_state.bl_count,((MAX_BITS+1) shl 16)+2,ta44 +dd deflate_state.heap,((2*L_CODES+1) shl 16)+2,ta45 +dd deflate_state.heap_len,4,ta46 +dd deflate_state.heap_max,4,ta47 +dd deflate_state.depth,((2*L_CODES+1) shl 16)+1,ta48 +dd deflate_state.l_buf,4,ta49 +dd deflate_state.lit_bufsize,4,ta50 +dd deflate_state.last_lit,4,ta51 +dd deflate_state.d_buf,4,ta52 +dd deflate_state.opt_len,4,ta53 +dd deflate_state.static_len,4,ta54 +dd deflate_state.matches,4,ta55 +dd deflate_state.insert,4,ta56 +;if DEBUG eq 1 +;dd deflate_state.compressed_len +;dd deflate_state.bits_sent +;end if +dd deflate_state.bi_buf,2,ta59 +dd deflate_state.bi_valid,4,ta60 +dd deflate_state.high_water,4,ta61 +dd 0,0 + +align 4 +proc dbg_print, fun:dword, mes:dword +pushad + mov eax,SF_BOARD + mov ebx,SSF_DEBUG_WRITE + + mov esi,[fun] + cmp esi,0 + je .end0 + @@: + mov cl,byte[esi] + int 0x40 + inc esi + cmp byte[esi],0 + jne @b + mov cl,':' + int 0x40 + mov cl,' ' + int 0x40 + .end0: + mov esi,[mes] + cmp esi,0 + je .end_f + @@: + mov cl,byte[esi] + cmp cl,0 + je .end_f + int 0x40 + inc esi + jmp @b + .end_f: +popad + ret +endp + +;input: +; zif - 1...8 +align 4 +proc hex_in_str, buf:dword,val:dword,zif:dword +pushad + mov edi,dword[buf] + mov ecx,dword[zif] + add edi,ecx + dec edi + mov ebx,dword[val] + + .cycle: + mov al,bl + and al,0xf + cmp al,10 + jl @f + add al,'a'-'0'-10 + @@: + add al,'0' + mov byte[edi],al + dec edi + shr ebx,4 + loop .cycle +popad + ret +endp + +;output: +; eax = strlen +align 4 +proc strlen, str1:dword + mov eax,[str1] + @@: + cmp byte[eax],0 + je @f + inc eax + jmp @b + @@: + sub eax,[str1] + ret +endp + +align 4 +proc str_format_dbg, buf:dword, fmt:dword, p1:dword +pushad + mov esi,[fmt] + mov edi,[buf] + mov ecx,80-1 + .cycle0: + lodsb + cmp al,'%' + jne .no_param + lodsb + dec ecx + cmp al,0 + je .cycle0end + cmp al,'d' + je @f + cmp al,'u' + je @f + cmp al,'l' + je .end1 + jmp .end0 + .end1: ;%lu %lx + lodsb + dec ecx + cmp al,'u' + jne .end0 + @@: + mov eax,[p1] + stdcall convert_int_to_str,ecx + xor al,al + repne scasb + dec edi + .end0: + loop .cycle0 + .no_param: + stosb + cmp al,0 + je .cycle0end + loop .cycle0 + .cycle0end: + xor al,al + stosb + stdcall dbg_print,txt_sp,[buf] +popad + ret +endp + +align 4 +proc debug_fields, saddr:dword, form:dword +locals + nl_array dd ? +endl +pushad + mov edi,[saddr] + cmp edi,0 + je .end_f + mcall SF_BOARD,SSF_DEBUG_WRITE,13 + mcall ,,10 + mov eax,[form] +align 4 + .cycle0: + mov ebx,[eax+4] + mov ecx,ebx + and ebx,0xffff + cmp ebx,0 + je .end_f + mov esi,ebx + shl ebx,1 + shr ecx,16 + cmp ecx,0 + je .end0 + ;if array + stdcall dbg_print,0,[eax+8] + mov edx,61 ;size text line + mov dword[nl_array],0 + .cycle2: + inc dword[nl_array] + sub edx,ebx + sub edx,2 ;': ' + cmp edx,3 + jg .cycle2 + mov edx,edi + add edx,[eax] + push eax + .nl_i: + mov eax,[nl_array] + mov byte[ebx+txt_buf],0 ;конец числа + .cycle1: + stdcall hex_in_str,txt_buf,[edx],ebx + add edx,esi ;move next value + + push edi + mov edi,txt_buf + cmp byte[edi],'0' + jne @f + inc edi + cmp byte[edi],'0' + jne @f + inc edi + cmp byte[edi],'0' + jne @f + inc edi + cmp byte[edi],'0' + jne @f + inc edi + @@: + cmp byte[edi],0 + jne @f + dec edi + @@: + stdcall dbg_print,edi,0 + pop edi + + ;stdcall dbg_print,txt_buf,0 + dec eax + jz .nl + loop .cycle1 + .nl: + push ebx ecx + mcall SF_BOARD,SSF_DEBUG_WRITE,13 + mcall ,,10 + pop ecx ebx + dec ecx + cmp ecx,0 + jg .nl_i + pop eax + add eax,12 + jmp .cycle0 + .end0: + mov edx,edi + add edx,[eax] + stdcall hex_in_str,txt_buf,[edx],ebx + mov byte[ebx+txt_buf],0 ;конец числа + stdcall dbg_print,txt_buf,[eax+8] + add eax,12 + jmp .cycle0 +.end_f: + mcall SF_BOARD,SSF_DEBUG_WRITE,13 + mcall ,,10 +popad + ret +endp + +;input: +; eax - число +; edi - буфер для строки +; len - длинна буфера +;output: +align 4 +proc convert_int_to_str, len:dword +pushad + mov esi,[len] + add esi,edi + dec esi + call .str +popad + ret +endp + +align 4 +.str: + mov ecx,0x0a + cmp eax,ecx + jb @f + xor edx,edx + div ecx + push edx + call .str + pop eax + @@: + cmp edi,esi + jge @f + or al,0x30 + stosb + mov byte[edi],0 + @@: + ret + diff --git a/programs/fs/kfar/trunk/zlib/deflate.asm b/programs/fs/kfar/trunk/zlib/deflate.asm new file mode 100644 index 0000000000..b2482c094d --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/deflate.asm @@ -0,0 +1,2962 @@ +; deflate.asm -- compress data using the deflation algorithm +; Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler +; For conditions of distribution and use, see copyright notice in zlib.inc + +; ALGORITHM + +; The "deflation" process depends on being able to identify portions +; of the input text which are identical to earlier input (within a +; sliding window trailing behind the input currently being processed). + +; The most straightforward technique turns out to be the fastest for +; most input files: try all possible matches and select the longest. +; The key feature of this algorithm is that insertions into the string +; dictionary are very simple and thus fast, and deletions are avoided +; completely. Insertions are performed at each input character, whereas +; string matches are performed only when the previous match ends. So it +; is preferable to spend more time in matches to allow very fast string +; insertions and avoid deletions. The matching algorithm for small +; strings is inspired from that of Rabin & Karp. A brute force approach +; is used to find longer strings when a small match has been found. +; A similar algorithm is used in comic (by Jan-Mark Wams) and freeze +; (by Leonid Broukhis). +; A previous version of this file used a more sophisticated algorithm +; (by Fiala and Greene) which is guaranteed to run in linear amortized +; time, but has a larger average cost, uses more memory and is patented. +; However the F&G algorithm may be faster for some highly redundant +; files if the parameter max_chain_length (described below) is too large. + +; ACKNOWLEDGEMENTS + +; The idea of lazy evaluation of matches is due to Jan-Mark Wams, and +; I found it in 'freeze' written by Leonid Broukhis. +; Thanks to many people for bug reports and testing. + +; REFERENCES + +; Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". +; Available in http://tools.ietf.org/html/rfc1951 + +; A description of the Rabin and Karp algorithm is given in the book +; "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + +; Fiala,E.R., and Greene,D.H. +; Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + + +deflate_copyright db ' deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ',0 + +; If you use the zlib library in a product, an acknowledgment is welcome +; in the documentation of your product. If for some reason you cannot +; include such an acknowledgment, I would appreciate that you keep this +; copyright string in the executable of your product. + +; =========================================================================== +; Function prototypes. + +;enum block_state +need_more equ 1 ;block not completed, need more input or more output +block_done equ 2 ;block flush performed +finish_started equ 3 ;finish started, need only more output at next deflate +finish_done equ 4 ;finish done, accept no more input or output + +; =========================================================================== +; Local data + +NIL equ 0 +; Tail of hash chains + +TOO_FAR equ 4096 +; Matches of length 3 are discarded if their distance exceeds TOO_FAR + +; Values for max_lazy_match, good_match and max_chain_length, depending on +; the desired pack level (0..9). The values given below have been tuned to +; exclude worst case performance for pathological files. Better values may be +; found for specific files. + +struct config_s ;config + good_length dw ? ;uint_16 ;reduce lazy search above this match length + max_lazy dw ? ;uint_16 ;do not perform lazy search above this match length + nice_length dw ? ;uint_16 ;quit search above this match length + max_chain dw ? ;uint_16 + co_func dd ? ;compress_func +ends + +align 16 +configuration_table: + config_s 0, 0, 0, 0, deflate_stored ;store only + config_s 4, 4, 8, 4, deflate_fast ;max speed, no lazy matches +if FASTEST eq 0 + config_s 4, 5, 16, 8, deflate_fast + config_s 4, 6, 32, 32, deflate_fast + config_s 4, 4, 16, 16, deflate_slow ;lazy matches + config_s 8, 16, 32, 32, deflate_slow + config_s 8, 16, 128, 128, deflate_slow + config_s 8, 32, 128, 256, deflate_slow + config_s 32, 128, 258, 1024, deflate_slow + config_s 32, 258, 258, 4096, deflate_slow ;max compression +end if + +; Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 +; For deflate_fast() (levels <= 3) good is ignored and lazy has a different +; meaning. + + +EQUAL equ 0 +; result of memcmp for equal strings + +; rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH +macro RANK f, reg +{ +local .end0 + xor reg,reg + cmp f,4 + jle .end0 + sub reg,9 + .end0: + add reg,f + add reg,f +} + +; =========================================================================== +; Update a hash value with the given input byte +; IN assertion: all calls to to UPDATE_HASH are made with consecutive +; input characters, so that a running hash key can be computed from the +; previous key instead of complete recalculation each time. + +macro UPDATE_HASH s,h,c +{ +push ebx ecx + mov ebx,h + mov ecx,[s+deflate_state.hash_shift] + shl ebx,cl + xor ebx,c + and ebx,[s+deflate_state.hash_mask] + mov h,ebx +pop ecx ebx +} + +; =========================================================================== +; Insert string str in the dictionary and set match_head to the previous head +; of the hash chain (the most recent string with same hash key). Return +; the previous length of the hash chain. +; If this file is compiled with -DFASTEST, the compression level is forced +; to 1, and no hash chains are maintained. +; IN assertion: all calls to to INSERT_STRING are made with consecutive +; input characters and the first MIN_MATCH bytes of str are valid +; (except for the last MIN_MATCH-1 bytes of the input file). + +macro INSERT_STRING s, str, match_head +{ + mov eax,[s+deflate_state.window] + add eax,str + add eax,MIN_MATCH-1 + movzx eax,byte[eax] + UPDATE_HASH s, [s+deflate_state.ins_h], eax + mov eax,[s+deflate_state.ins_h] + shl eax,2 + add eax,[s+deflate_state.head] + mov eax,[eax] + mov match_head,eax +if FASTEST eq 0 +push ebx + mov ebx,[s+deflate_state.w_mask] + and ebx,str + add ebx,[s+deflate_state.prev] + mov byte[ebx],al +pop ebx +end if + mov eax,[s+deflate_state.ins_h] + shl eax,2 + add eax,[s+deflate_state.head] + push str + pop dword[eax] +} + +; =========================================================================== +; Initialize the hash table (avoiding 64K overflow for 16 bit systems). +; prev[] will be initialized on the fly. + +macro CLEAR_HASH s +{ + mov eax,[s+deflate_state.hash_size] + dec eax + shl eax,2 + add eax,[s+deflate_state.head] + mov dword[eax],NIL + mov eax,[s+deflate_state.hash_size] + dec eax + shl eax,2 ;sizeof(*s.head) + stdcall zmemzero, [s+deflate_state.head], eax +} + +align 4 +proc deflateInit, strm:dword, level:dword + stdcall deflateInit_, [strm], [level], ZLIB_VERSION, sizeof.z_stream + ret +endp + +; ========================================================================= +;int (strm, level, version, stream_size) +; z_streamp strm; +; int level; +; const char *version; +; int stream_size; +align 4 +proc deflateInit_, strm:dword, level:dword, version:dword, stream_size:dword + stdcall deflateInit2_, [strm], [level], Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,\ + Z_DEFAULT_STRATEGY, [version], [stream_size] + ; To do: ignore strm->next_in if we use it as window + ret +endp + +align 4 +proc deflateInit2, strm:dword, level:dword, method:dword, windowBits:dword, memLevel:dword, strategy:dword + stdcall deflateInit2_, [strm],[level],[method],[windowBits],[memLevel],\ + [strategy], ZLIB_VERSION, sizeof.z_stream + ret +endp + +; ========================================================================= +;int (strm, level, method, windowBits, memLevel, strategy, +; version, stream_size) +; z_streamp strm; +; int level; +; int method; +; int windowBits; +; int memLevel; +; int strategy; +; const char *version; +; int stream_size; +align 4 +proc deflateInit2_ uses ebx ecx edx edi, strm:dword, level:dword, method:dword,\ + windowBits:dword, memLevel:dword, strategy:dword, version:dword, stream_size:dword +locals + wrap dd 1 ;int + overlay dd ? ;uint_16p +endl + ; We overlay pending_buf and d_buf+l_buf. This works since the average + ; output size for (length,distance) codes is <= 24 bits. + + mov eax,[version] + cmp eax,Z_NULL + je @f + mov ebx,dword[ZLIB_VERSION] + cmp dword[eax],ebx + jne @f + cmp dword[stream_size],sizeof.z_stream + je .end0 + @@: ;if (..==0 || ..[0]!=..[0] || ..!=..) + mov eax,Z_VERSION_ERROR + jmp .end_f + .end0: + mov ebx,[strm] + cmp ebx,Z_NULL + jne @f ;if (..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + @@: + + mov dword[ebx+z_stream.msg],Z_NULL + cmp dword[ebx+z_stream.zalloc],0 + jne @f ;if (..==0) +if Z_SOLO eq 1 + mov eax,Z_STREAM_ERROR + jmp .end_f +else + mov dword[ebx+z_stream.zalloc],zcalloc + mov dword[ebx+z_stream.opaque],0 +end if + @@: + cmp dword[ebx+z_stream.zfree],0 + jne @f ;if (..==0) +if Z_SOLO eq 1 + mov eax,Z_STREAM_ERROR + jmp .end_f +else + mov dword[ebx+z_stream.zfree],zcfree +end if + @@: + +if FASTEST eq 1 + cmp dword[level],0 + je @f ;if (..!=0) + mov dword[level],1 + @@: +else + cmp dword[level],Z_DEFAULT_COMPRESSION + jne @f ;if (..==0) + mov dword[level],6 + @@: +end if + + cmp dword[windowBits],0 + jge @f ;if (..<0) ;suppress zlib wrapper + mov dword[wrap],0 + neg dword[windowBits] + inc dword[windowBits] + jmp .end1 + @@: +if GZIP eq 1 + cmp dword[windowBits],15 + jle .end1 ;else if (..>15) + mov dword[wrap],2 ;write gzip wrapper instead + sub dword[windowBits],16 +end if + .end1: + cmp dword[memLevel],1 + jl .end2 + cmp dword[memLevel],MAX_MEM_LEVEL + jg .end2 + cmp dword[method],Z_DEFLATED + jne .end2 + cmp dword[windowBits],8 + jl .end2 + cmp dword[windowBits],15 + jg .end2 + cmp dword[level],0 + jl .end2 + cmp dword[level],9 + jg .end2 + cmp dword[strategy],0 + jl .end2 + cmp dword[strategy],Z_FIXED + jle @f + .end2: ;if (..<.. || ..>.. || ..!=.. || ..<.. || ..>.. || ..<0 || ..>.. || ..<0 || ..>..) + mov eax,Z_STREAM_ERROR + jmp .end_f + @@: + cmp dword[windowBits],8 + jne @f ;if (..==..) + inc dword[windowBits] ;until 256-byte window bug fixed + @@: + ZALLOC ebx, 1, sizeof.deflate_state + ;eax = s + cmp eax,Z_NULL + jne @f ;if (..==0) + mov eax,Z_MEM_ERROR + jmp .end_f + @@: + mov edi,eax ;edi = s + mov [ebx+z_stream.state],edi + mov [edi+deflate_state.strm],ebx + + mov eax,[wrap] + mov [edi+deflate_state.wrap],eax + mov [edi+deflate_state.gzhead],Z_NULL + mov ecx,[windowBits] + mov [edi+deflate_state.w_bits],ecx + xor eax,eax + inc eax + shl eax,cl + mov [edi+deflate_state.w_size],eax + dec eax + mov [edi+deflate_state.w_mask],eax + + mov ecx,[memLevel] + add ecx,7 + mov [edi+deflate_state.hash_bits],ecx + xor eax,eax + inc eax + shl eax,cl + mov [edi+deflate_state.hash_size],eax + dec eax + mov [edi+deflate_state.hash_mask],eax + add ecx,MIN_MATCH-1 + xor edx,edx + mov eax,ecx + mov ecx,MIN_MATCH + div ecx + mov [edi+deflate_state.hash_shift],eax + + ZALLOC ebx, [edi+deflate_state.w_size], 2 ;2*sizeof(Byte) + mov [edi+deflate_state.window],eax + ZALLOC ebx, [edi+deflate_state.w_size], 4 ;sizeof(Pos) + mov [edi+deflate_state.prev],eax + ZALLOC ebx, [edi+deflate_state.hash_size], 4 ;sizeof(Pos) + mov [edi+deflate_state.head],eax + + mov dword[edi+deflate_state.high_water],0 ;nothing written to s->window yet + + mov ecx,[memLevel] + add ecx,6 + xor eax,eax + inc eax + shl eax,cl + mov [edi+deflate_state.lit_bufsize],eax ;16K elements by default + + ZALLOC ebx, eax, 4 ;sizeof(uint_16)+2 + mov [overlay],eax + mov [edi+deflate_state.pending_buf],eax + mov eax,[edi+deflate_state.lit_bufsize] + imul eax,4 ;sizeof(uint_16)+2 + mov [edi+deflate_state.pending_buf_size],eax + + cmp dword[edi+deflate_state.window],Z_NULL + je .end3 + cmp dword[edi+deflate_state.prev],Z_NULL + je .end3 + cmp dword[edi+deflate_state.head],Z_NULL + je .end3 + cmp dword[edi+deflate_state.pending_buf],Z_NULL + je .end3 + jmp @f + .end3: ;if (..==0 || ..==0 || ..==0 || ..==0) + mov dword[edi+deflate_state.status],FINISH_STATE + ERR_MSG Z_MEM_ERROR + mov [ebx+z_stream.msg],eax + stdcall deflateEnd, ebx + mov eax,Z_MEM_ERROR + jmp .end_f + @@: + mov eax,[edi+deflate_state.lit_bufsize] + shr eax,1 ;/=sizeof(uint_16) + add eax,[overlay] + mov [edi+deflate_state.d_buf],eax + mov eax,[edi+deflate_state.lit_bufsize] + imul eax,3 ;1+sizeof(uint_16) + add eax,[edi+deflate_state.pending_buf] + mov [edi+deflate_state.l_buf],eax + + mov eax,[level] + mov [edi+deflate_state.level],ax + mov eax,[strategy] + mov [edi+deflate_state.strategy],ax + mov eax,[method] + mov [edi+deflate_state.method],al + + stdcall deflateReset, ebx +.end_f: +zlib_debug 'deflateInit2_ strategy = %d',[strategy] + ret +endp + +; ========================================================================= +;int (strm, dictionary, dictLength) +; z_streamp strm; +; const Bytef *dictionary; +; uInt dictLength; +align 4 +proc deflateSetDictionary uses ebx edi, strm:dword, dictionary:dword, dictLength:dword +locals +; deflate_state *s; +; uInt str, n; + wrap dd ? ;int + avail dd ? ;unsigned +; z_const unsigned char *next; +endl + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] + cmp edi,Z_NULL + je @f + cmp dword[dictionary],Z_NULL + je @f ;if (..==0 || ..==0 || ..==0) + jmp .end0 + @@: + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + + mov eax,[edi+deflate_state.wrap] + mov [wrap],eax +; if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) +; return Z_STREAM_ERROR; + + ; when using zlib wrappers, compute Adler-32 for provided dictionary +; if (wrap == 1) +; strm->adler = adler32(strm->adler, dictionary, dictLength); +; s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + ; if dictionary would fill window, just replace the history +; if (dictLength >= s->w_size) { +; if (wrap == 0) { /* already empty otherwise */ +; CLEAR_HASH(s); +; s->strstart = 0; +; s->block_start = 0L; +; s->insert = 0; +; } +; dictionary += dictLength - s->w_size; /* use the tail */ +; dictLength = s->w_size; +; } + + ; insert dictionary into window and hash +; avail = strm->avail_in; +; next = strm->next_in; +; strm->avail_in = dictLength; +; strm->next_in = (z_const Bytef *)dictionary; +; fill_window(s); +; while (s->lookahead >= MIN_MATCH) { +; str = s->strstart; +; n = s->lookahead - (MIN_MATCH-1); +; do { +; UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +if FASTEST eq 0 +; s->prev[str & s->w_mask] = s->head[s->ins_h]; +end if +; s->head[s->ins_h] = (Pos)str; +; str++; +; } while (--n); +; s->strstart = str; +; s->lookahead = MIN_MATCH-1; +; fill_window(s); +; } +; s->strstart += s->lookahead; +; s->block_start = (long)s->strstart; +; s->insert = s->lookahead; +; s->lookahead = 0; +; s->match_length = s->prev_length = MIN_MATCH-1; +; s->match_available = 0; +; strm->next_in = next; +; strm->avail_in = avail; +; s->wrap = wrap; + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +;int (strm) +; z_streamp strm; +align 4 +proc deflateResetKeep uses ebx edi, strm:dword +; deflate_state *s; + + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] + cmp edi,Z_NULL + je @f + cmp dword[ebx+z_stream.zalloc],0 + je @f + cmp dword[ebx+z_stream.zfree],0 + je @f ;if (..==0 || ..==0 || ..==0 || ..==0) + jmp .end0 + @@: + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + + mov dword[ebx+z_stream.total_out],0 + mov dword[ebx+z_stream.total_in],0 + mov dword[ebx+z_stream.msg],Z_NULL ;use zfree if we ever allocate msg dynamically + mov word[ebx+z_stream.data_type],Z_UNKNOWN + + mov word[edi+deflate_state.pending],0 + mov eax,[edi+deflate_state.pending_buf] + mov [edi+deflate_state.pending_out],eax + + cmp dword[edi+deflate_state.wrap],0 + jge @f ;if (..<0) + neg dword[edi+deflate_state.wrap] + inc dword[edi+deflate_state.wrap] ;was made negative by deflate(..., Z_FINISH) + @@: + mov eax,BUSY_STATE + cmp dword[edi+deflate_state.wrap],0 + je @f + mov eax,INIT_STATE + @@: + mov dword[edi+deflate_state.status],eax + stdcall adler32, 0, Z_NULL, 0 +if GZIP eq 1 + cmp dword[edi+deflate_state.wrap],2 + jne @f + stdcall calc_crc32, 0, Z_NULL, 0 + @@: +end if + mov dword[ebx+z_stream.adler],eax + mov dword[edi+deflate_state.last_flush],Z_NO_FLUSH + + stdcall _tr_init, edi + + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +;int (strm) +; z_streamp strm; +align 4 +proc deflateReset uses ebx, strm:dword + mov ebx,[strm] +;zlib_debug 'deflateReset' + stdcall deflateResetKeep, ebx + cmp eax,0 + jne @f ;if (..==Z_OK) + stdcall lm_init, [ebx+z_stream.state] + @@: + ret +endp + +; ========================================================================= +;int (strm, head) +; z_streamp strm; +; gz_headerp head; +align 4 +proc deflateSetHeader uses ebx, strm:dword, head:dword + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov ebx,[ebx+z_stream.state] + cmp ebx,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + cmp dword[ebx+deflate_state.wrap],2 + je @f ;if (..!=..) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + @@: + mov eax,[head] + mov [ebx+deflate_state.gzhead],eax + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +;int (strm, pending, bits) +; unsigned *pending; +; int *bits; +; z_streamp strm; +align 4 +proc deflatePending uses ebx edi, strm:dword, pending:dword, bits:dword + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] + cmp edi,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + cmp dword[pending],Z_NULL + je @f ;if (..!=..) + mov eax,[pending] + movzx ebx,word[edi+deflate_state.pending] + mov [eax],ebx + @@: + cmp dword[bits],Z_NULL + je @f ;if (..!=..) + mov eax,[bits] + mov ebx,[edi+deflate_state.bi_valid] + mov [eax],ebx + @@: + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +;int (strm, bits, value) +; z_streamp strm; +; int bits; +; int value; +align 4 +proc deflatePrime uses ebx edi, strm:dword, bits:dword, value:dword +; int put; + + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] ;s = strm.state + cmp edi,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: +; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) +; return Z_BUF_ERROR; +; do { +; put = Buf_size - s->bi_valid; +; if (put > bits) +; put = bits; +; s->bi_buf |= (uint_16)((value & ((1 << put) - 1)) << s->bi_valid); +; s->bi_valid += put; +; _tr_flush_bits(s); +; value >>= put; +; bits -= put; +; } while (bits); + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +;int (strm, level, strategy) +; z_streamp strm; +; int level; +; int strategy; +align 4 +proc deflateParams uses ebx edi, strm:dword, level:dword, strategy:dword +; compress_func func; +; int err = Z_OK; + + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] ;s = strm.state + cmp edi,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + +if FASTEST eq 1 + cmp dword[level],0 + je @f ;if (..!=0) + mov dword[level],1 + @@: +else + cmp dword[level],Z_DEFAULT_COMPRESSION + jne @f ;if (..==0) + mov dword[level],6 + @@: +end if +; if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { +; return Z_STREAM_ERROR; +; } +; func = configuration_table[s->level].func; + +; if ((strategy != s->strategy || func != configuration_table[level].func) && +; strm->total_in != 0) { + ; Flush the last buffer: +; err = deflate(strm, Z_BLOCK); +; if (err == Z_BUF_ERROR && s->pending == 0) +; err = Z_OK; +; } +; if (s->level != level) { +; s->level = level; +; s->max_lazy_match = configuration_table[level].max_lazy; +; s->good_match = configuration_table[level].good_length; +; s->nice_match = configuration_table[level].nice_length; +; s->max_chain_length = configuration_table[level].max_chain; +; } +; s->strategy = strategy; +; return err; +.end_f: + ret +endp + +; ========================================================================= +;int (strm, good_length, max_lazy, nice_length, max_chain) +; z_streamp strm; +; int good_length; +; int max_lazy; +; int nice_length; +; int max_chain; +align 4 +proc deflateTune uses ebx, strm:dword, good_length:dword, max_lazy:dword,\ + nice_length:dword, max_chain:dword + mov ebx,[strm] + cmp ebx,Z_NULL + je @f + cmp dword[ebx+z_stream.state],Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + mov ebx,[ebx+z_stream.state] ;s = strm.state + mov eax,[good_length] + mov [ebx+deflate_state.good_match],eax + mov eax,[max_lazy] + mov [ebx+deflate_state.max_lazy_match],eax + mov eax,[nice_length] + mov [ebx+deflate_state.nice_match],eax + mov eax,[max_chain] + mov [ebx+deflate_state.max_chain_length],eax + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +; For the default windowBits of 15 and memLevel of 8, this function returns +; a close to exact, as well as small, upper bound on the compressed size. +; They are coded as constants here for a reason--if the #define's are +; changed, then this function needs to be changed as well. The return +; value for 15 and 8 only works for those exact settings. + +; For any setting other than those defaults for windowBits and memLevel, +; the value returned is a conservative worst case for the maximum expansion +; resulting from using fixed blocks instead of stored blocks, which deflate +; can emit on compressed data for some combinations of the parameters. + +; This function could be more sophisticated to provide closer upper bounds for +; every combination of windowBits and memLevel. But even the conservative +; upper bound of about 14% expansion does not seem onerous for output buffer +; allocation. + +;uLong (strm, sourceLen) +; z_streamp strm; +; uLong sourceLen; +align 4 +proc deflateBound, strm:dword, sourceLen:dword +; deflate_state *s; +; uLong complen, wraplen; +; Bytef *str; +;zlib_debug 'deflateBound' + + ; conservative upper bound for compressed data +; complen = sourceLen + +; ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + ; if can't get parameters, return conservative bound plus zlib wrapper +; if (strm == Z_NULL || strm->state == Z_NULL) +; return complen + 6; + + ; compute wrapper length +; s = strm->state; +; switch (s->wrap) { +; case 0: /* raw deflate */ +; wraplen = 0; +; break; +; case 1: /* zlib wrapper */ +; wraplen = 6 + (s->strstart ? 4 : 0); +; break; +; case 2: /* gzip wrapper */ +; wraplen = 18; +; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ +; if (s->gzhead->extra != Z_NULL) +; wraplen += 2 + s->gzhead->extra_len; +; str = s->gzhead->name; +; if (str != Z_NULL) +; do { +; wraplen++; +; } while (*str++); +; str = s->gzhead->comment; +; if (str != Z_NULL) +; do { +; wraplen++; +; } while (*str++); +; if (s->gzhead->hcrc) +; wraplen += 2; +; } +; break; +; default: /* for compiler happiness */ +; wraplen = 6; +; } + + ; if not default parameters, return conservative bound +; if (s->w_bits != 15 || s->hash_bits != 8 + 7) +; return complen + wraplen; + + ; default settings: return tight bound for that case +; return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + +; (sourceLen >> 25) + 13 - 6 + wraplen; +.end_f: + ret +endp + +; ========================================================================= +; Put a short in the pending buffer. The 16-bit value is put in MSB order. +; IN assertion: the stream state is correct and there is enough room in +; pending_buf. + +;void (s, b) +; deflate_state *s; +; uInt b; +align 4 +proc putShortMSB uses ebx ecx, s:dword, b:dword + mov ebx,[s] + mov ecx,[b] + put_byte ebx, ch + put_byte ebx, cl + ret +endp + +; ========================================================================= +; Flush as much pending output as possible. All deflate() output goes +; through this function so some applications may wish to modify it +; to avoid allocating a large strm->next_out buffer and copying into it. +; (See also read_buf()). + +;void (strm) +; z_streamp strm; +align 4 +proc flush_pending uses eax ebx ecx edx, strm:dword +;ecx - len +;edx - deflate_state *s +;ebx - strm +;zlib_debug 'flush_pending' + mov ebx,[strm] + mov edx,[ebx+z_stream.state] + + stdcall _tr_flush_bits, edx + movzx ecx,word[edx+deflate_state.pending] + cmp cx,[ebx+z_stream.avail_out] + jle @f ;if (..>..) + movzx ecx,word[ebx+z_stream.avail_out] + @@: + cmp ecx,0 + je @f + + stdcall zmemcpy, [ebx+z_stream.next_out], [edx+deflate_state.pending_out], ecx + add [ebx+z_stream.next_out],ecx + add [edx+deflate_state.pending_out],ecx + add [ebx+z_stream.total_out],ecx + sub [ebx+z_stream.avail_out],cx + sub [edx+deflate_state.pending],cx + cmp word[edx+deflate_state.pending],0 + jne @f ;if (..==0) + mov eax,[edx+deflate_state.pending_buf] + mov [edx+deflate_state.pending_out],eax + @@: + ret +endp + +; ========================================================================= +;int (strm, flush) +; z_streamp strm; +; int flush; +align 4 +proc deflate uses ebx ecx edx edi esi, strm:dword, flush:dword +locals + old_flush dd ? ;int ;value of flush param for previous deflate call + val dd ? +endl + mov ebx,[strm] +zlib_debug 'deflate strm = %d',ebx + cmp ebx,Z_NULL + je @f + mov edi,[ebx+z_stream.state] ;s = strm.state + cmp edi,Z_NULL + je @f + cmp dword[flush],Z_BLOCK + jg @f + cmp dword[flush],0 + jl @f ;if (..==0 || ..==0 || ..>.. || ..<0) + jmp .end10 + @@: + mov eax,Z_STREAM_ERROR + jmp .end_f + .end10: + cmp dword[ebx+z_stream.next_out],Z_NULL + je .beg0 + cmp dword[ebx+z_stream.next_in],Z_NULL + jne @f + cmp word[ebx+z_stream.avail_in],0 + jne .beg0 + @@: + cmp dword[edi+deflate_state.status],FINISH_STATE + jne .end0 + cmp dword[flush],Z_FINISH + je .end0 + .beg0: ;if (..==0 || (..==0 && ..!=0) || (..=.. && ..!=..)) + ERR_RETURN ebx, Z_STREAM_ERROR + jmp .end_f + .end0: + cmp word[ebx+z_stream.avail_out],0 + jne @f ;if (..==0) + ERR_RETURN ebx, Z_BUF_ERROR + jmp .end_f + @@: + + mov dword[edi+deflate_state.strm],ebx ;just in case + mov eax,[edi+deflate_state.last_flush] + mov [old_flush],eax + mov eax,[flush] + mov [edi+deflate_state.last_flush],eax + + ; Write the header + cmp dword[edi+deflate_state.status],INIT_STATE + jne .end2 ;if (..==..) +if GZIP eq 1 + cmp dword[edi+deflate_state.wrap],2 + jne .end1 ;if (..==..) + stdcall calc_crc32, 0, Z_NULL, 0 + mov [ebx+z_stream.adler],eax + put_byte edi, 31 + put_byte edi, 139 + put_byte edi, 8 + cmp dword[edi+deflate_state.gzhead],Z_NULL + jne .end3 ;if (..==0) + put_byte edi, 0 + put_dword edi, 0 + xor cl,cl + cmp word[edi+deflate_state.level],2 + jge @f + mov cl,4 + @@: + cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY + jl @f + mov cl,4 + @@: + cmp word[edi+deflate_state.level],9 + jne @f + mov cl,2 + @@: ;..==.. ? 2 : (..>=.. || ..<.. ? 4 : 0) + put_byte edi, cl + put_byte edi, OS_CODE + mov dword[edi+deflate_state.status],BUSY_STATE + jmp .end2 + .end3: ;else + mov edx,[edi+deflate_state.gzhead] + xor cl,cl + cmp [edx+gz_header.text],0 + je @f + inc cl + @@: + cmp [edx+gz_header.hcrc],0 + je @f + add cl,2 + @@: + cmp [edx+gz_header.extra],Z_NULL + je @f + add cl,4 + @@: + cmp [edx+gz_header.name],Z_NULL + je @f + add cl,8 + @@: + cmp [edx+gz_header.comment],Z_NULL + je @f + add cl,16 + @@: + put_byte edi, cl + mov ecx,[edx+gz_header.time] + put_dword edi, ecx + xor cl,cl + cmp word[edi+deflate_state.level],2 + jge @f + mov cl,4 + @@: + cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY + jl @f + mov cl,4 + @@: + cmp word[edi+deflate_state.level],9 + jne @f + mov cl,2 + @@: ;..==.. ? 2 : (..>=.. || ..<.. ? 4 : 0) + put_byte edi, cl + mov ecx,[edx+gz_header.os] + put_byte edi, cl + cmp dword[edx+gz_header.extra],Z_NULL + je @f ;if (..!=0) + mov ecx,[edx+gz_header.extra_len] + put_byte edi, cl + put_byte edi, ch + @@: + cmp dword[edx+gz_header.hcrc],0 + je @f ;if (..) + movzx eax,word[edi+deflate_state.pending] + stdcall calc_crc32, [ebx+z_stream.adler],\ + [edi+deflate_state.pending_buf], eax + mov [ebx+z_stream.adler],eax + @@: + mov dword[edi+deflate_state.gzindex],0 + mov dword[edi+deflate_state.status],EXTRA_STATE + jmp .end2 + .end1: ;else +end if + mov edx,[edi+deflate_state.w_bits] + sub edx,8 + shl edx,4 + add edx,Z_DEFLATED + shl edx,8 ;edx = header + ;esi = level_flags + + mov esi,3 + cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY + jl @f + cmp word[edi+deflate_state.level],2 + jge @f ;if (..>=.. || ..<..) + xor esi,esi + jmp .end4 + @@: + cmp word[edi+deflate_state.level],6 + jge @f ;else if (..<..) + mov esi,1 + jmp .end4 + @@: + ;;cmp word[edi+deflate_state.level],6 + jne .end4 ;else if (..==..) + mov esi,2 + .end4: + shl esi,6 + or edx,esi + cmp dword[edi+deflate_state.strstart],0 + je @f ;if (..!=0) + or edx,PRESET_DICT + @@: + mov esi,edx + mov eax,edx + xor edx,edx + mov ecx,31 + div ecx + add esi,31 + sub esi,edx ;esi = header + + mov dword[edi+deflate_state.status],BUSY_STATE + stdcall putShortMSB, edi, esi + + ; Save the adler32 of the preset dictionary: + cmp dword[edi+deflate_state.strstart],0 + je @f ;if (..!=0) + mov ecx,[ebx+z_stream.adler] + bswap ecx + put_dword edi, ecx + @@: + stdcall calc_crc32, 0, Z_NULL, 0 + mov [ebx+z_stream.adler],eax + .end2: +if GZIP eq 1 + mov edx,[edi+deflate_state.gzhead] + cmp dword[edi+deflate_state.status],EXTRA_STATE + jne .end5 ;if (..==..) + cmp dword[edx+gz_header.extra],Z_NULL + je .end21 ;if (..!=..) + movzx esi,word[edi+deflate_state.pending] + ;esi = beg ;start of bytes to update crc + + movzx ecx,word[edx+gz_header.extra_len] + .cycle0: ;while (..<..) + cmp dword[edi+deflate_state.gzindex],ecx + jge .cycle0end + movzx eax,word[edi+deflate_state.pending] + cmp eax,[edi+deflate_state.pending_buf_size] + jne .end24 ;if (..==..) + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + stdcall flush_pending, ebx + movzx esi,word[edi+deflate_state.pending] + cmp esi,[edi+deflate_state.pending_buf_size] + je .cycle0end ;if (..==..) break + .end24: + push ebx + mov ebx,[edi+deflate_state.gzindex] + add ebx,[edx+gz_header.extra] + mov bl,[ebx] + put_byte edi, bl + pop ebx + inc dword[edi+deflate_state.gzindex] + jmp .cycle0 + .cycle0end: + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + mov eax,[edx+gz_header.extra_len] + cmp dword[edi+deflate_state.gzindex],eax + jne .end5 ;if (..==..) + mov dword[edi+deflate_state.gzindex],0 + mov dword[edi+deflate_state.status],NAME_STATE + jmp .end5 + .end21: ;else + mov dword[edi+deflate_state.status],NAME_STATE + .end5: + cmp dword[edi+deflate_state.status],NAME_STATE + jne .end6 ;if (..==..) + cmp dword[edx+gz_header.name],Z_NULL + je .end22 ;if (..!=..) + movzx esi,word[edi+deflate_state.pending] + ;esi = beg ;start of bytes to update crc + + .cycle1: ;do + movzx eax,word[edi+deflate_state.pending] + cmp eax,[edi+deflate_state.pending_buf_size] + jne .end25 ;if (..==..) + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + stdcall flush_pending, ebx + movzx esi,word[edi+deflate_state.pending] + movzx eax,word[edi+deflate_state.pending] + cmp eax,[edi+deflate_state.pending_buf_size] + jne .end25 ;if (..==..) + mov dword[val],1 + jmp .cycle1end + .end25: + push ebx + mov ebx,[edi+deflate_state.gzindex] + add ebx,[edx+gz_header.name] + movzx ebx,byte[ebx] + mov [val],ebx + inc dword[edi+deflate_state.gzindex] + put_byte edi, bl + pop ebx + cmp dword[val],0 + jne .cycle1 ;while (val != 0) + .cycle1end: + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + cmp dword[val],0 + jne .end6 ;if (val == 0) + mov dword[edi+deflate_state.gzindex],0 + mov dword[edi+deflate_state.status],COMMENT_STATE + jmp .end6 + .end22: ;else + mov dword[edi+deflate_state.status],COMMENT_STATE; + .end6: + cmp dword[edi+deflate_state.status],COMMENT_STATE + jne .end7 ;if (..==..) + cmp dword[edx+gz_header.comment],Z_NULL + je .end23 ;if (..!=..) + movzx esi,word[edi+deflate_state.pending] + ;esi = beg ;start of bytes to update crc + + .cycle2: ;do + movzx eax,word[edi+deflate_state.pending] + cmp eax,[edi+deflate_state.pending_buf_size] + jne .end26 ;if (..==..) + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + stdcall flush_pending, ebx + movzx esi,word[edi+deflate_state.pending] + movzx eax,word[edi+deflate_state.pending] + cmp eax,[edi+deflate_state.pending_buf_size] + jne .end26 ;if (..==..) + mov dword[val],1 + jmp .cycle2end + .end26: + push ebx + mov ebx,[edi+deflate_state.gzindex] + add ebx,[edx+gz_header.comment] + movzx ebx,byte[ebx] + mov [val],ebx + inc dword[edi+deflate_state.gzindex] + put_byte edi, bl + pop ebx + cmp dword[val],0 + jne .cycle2 ;while (val != 0) + .cycle2end: + mov dword[edx+gz_header.hcrc],0 + je @f + cmp [edi+deflate_state.pending],si + jle @f ;if (.. && ..>..) + movzx ecx,word[edi+deflate_state.pending] + sub ecx,esi + mov eax,[edi+deflate_state.pending_buf] + add eax,esi + stdcall calc_crc32, [ebx+z_stream.adler], eax, ecx + mov [ebx+z_stream.adler],eax + @@: + cmp dword[val],0 + jne .end7 ;if (val == 0) + mov dword[edi+deflate_state.status],HCRC_STATE + jmp .end7 + .end23: ;else + mov dword[edi+deflate_state.status],HCRC_STATE + .end7: + cmp dword[edi+deflate_state.status],HCRC_STATE + jne .end8 ;if (..==..) + cmp dword[edx+gz_header.hcrc],0 + je .end9 ;if (..) + movzx ecx,word[edi+deflate_state.pending] + add ecx,2 + cmp ecx,[edi+deflate_state.pending_buf_size] + jle @f ;if (..>..) + stdcall flush_pending, ebx + @@: + movzx ecx,word[edi+deflate_state.pending] + add ecx,2 + cmp ecx,[edi+deflate_state.pending_buf_size] + jg @f ;if (..<=..) + mov ecx,[ebx+z_stream.adler] + put_byte edi, cl + put_byte edi, ch + stdcall calc_crc32, 0, Z_NULL, 0 + mov [ebx+z_stream.adler],eax + mov dword[edi+deflate_state.status],BUSY_STATE + @@: + jmp .end8 + .end9: ;else + mov dword[edi+deflate_state.status],BUSY_STATE + .end8: +end if + + ; Flush as much pending output as possible + cmp word[edi+deflate_state.pending],0 + je .end13 ;if (..!=0) + stdcall flush_pending, ebx + cmp word[ebx+z_stream.avail_out],0 + jne @f ;if (..==0) + ; Since avail_out is 0, deflate will be called again with + ; more output space, but possibly with both pending and + ; avail_in equal to zero. There won't be anything to do, + ; but this is not an error situation so make sure we + ; return OK instead of BUF_ERROR at next call of deflate: + + mov dword[edi+deflate_state.last_flush],-1 + mov eax,Z_OK + jmp .end_f + @@: + ; Make sure there is something to do and avoid duplicate consecutive + ; flushes. For repeated and useless calls with Z_FINISH, we keep + ; returning Z_STREAM_END instead of Z_BUF_ERROR. + jmp @f + .end13: + cmp word[ebx+z_stream.avail_in],0 + jne @f + RANK dword[old_flush],esi + RANK dword[flush],eax + cmp eax,esi + jg @f + cmp dword[flush],Z_FINISH + je @f ;else if (..==0 && ..<=.. && ..!=..) + ERR_RETURN ebx, Z_BUF_ERROR + jmp .end_f + @@: + + ; User must not provide more input after the first FINISH: + cmp dword[edi+deflate_state.status],FINISH_STATE + jne @f + cmp word[ebx+z_stream.avail_in],0 + je @f ;if (..==.. && ..!=0) + ERR_RETURN ebx, Z_BUF_ERROR + jmp .end_f + @@: + + ; Start a new block or continue the current one. + + cmp word[ebx+z_stream.avail_in],0 + jne @f + cmp dword[edi+deflate_state.lookahead],0 + jne @f + cmp dword[flush],Z_NO_FLUSH + je .end11 + cmp dword[edi+deflate_state.status],FINISH_STATE + je .end11 + @@: ;if (..!=0 || ..!=0 || (..!=.. && ..!=..)) + ;edx = bstate + cmp word[edi+deflate_state.strategy],Z_HUFFMAN_ONLY + jne @f + stdcall deflate_huff, edi, [flush] + jmp .end20 + @@: + cmp word[edi+deflate_state.strategy],Z_RLE + jne @f + stdcall deflate_rle, edi, [flush] + jmp .end20 + @@: + movzx eax,word[edi+deflate_state.level] + imul eax,sizeof.config_s + add eax,configuration_table+config_s.co_func + stdcall dword[eax], edi, [flush] + .end20: + mov edx,eax + + cmp edx,finish_started + je @f + cmp edx,finish_done + je @f + jmp .end18 + @@: ;if (..==.. || ..==..) + mov dword[edi+deflate_state.status],FINISH_STATE + .end18: + cmp edx,need_more + je @f + cmp edx,finish_started + je @f + jmp .end19 + @@: ;if (..==.. || ..==..) + cmp word[ebx+z_stream.avail_out],0 + jne @f ;if (..==0) + mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR next call, see above + @@: + mov eax,Z_OK + jmp .end_f + ; If flush != Z_NO_FLUSH && avail_out == 0, the next call + ; of deflate should use the same flush parameter to make sure + ; that the flush is complete. So we don't have to output an + ; empty block here, this will be done at next call. This also + ; ensures that for a very small output buffer, we emit at most + ; one empty block. + + .end19: + cmp edx,block_done + jne .end11 ;if (..==..) + cmp dword[flush],Z_PARTIAL_FLUSH + jne @f ;if (..==..) + stdcall _tr_align, edi + jmp .end16 + @@: + cmp dword[flush],Z_BLOCK + je .end16 ;else if (..!=..) ;FULL_FLUSH or SYNC_FLUSH + stdcall _tr_stored_block, edi, 0, 0, 0 + ; For a full flush, this empty block will be recognized + ; as a special marker by inflate_sync(). + + cmp dword[flush],Z_FULL_FLUSH + jne .end16 ;if (..==..) + CLEAR_HASH edi ;forget history + cmp dword[edi+deflate_state.lookahead],0 + jne .end16 ;if (..==0) + mov dword[edi+deflate_state.strstart],0 + mov dword[edi+deflate_state.block_start],0 + mov dword[edi+deflate_state.insert],0 + .end16: + stdcall flush_pending, ebx + cmp word[ebx+z_stream.avail_out],0 + jne .end11 ;if (..==0) + mov dword[edi+deflate_state.last_flush],-1 ;avoid BUF_ERROR at next call, see above + mov eax,Z_OK + jmp .end_f + .end11: + cmp word[ebx+z_stream.avail_out],0 + jg @f + zlib_debug 'bug2' ;Assert(..>0) + @@: + + cmp dword[flush],Z_FINISH + je @f ;if (..!=0) + mov eax,Z_OK + jmp .end_f + @@: + cmp dword[edi+deflate_state.wrap],0 + jg @f ;if (..<=0) + mov eax,Z_STREAM_END + jmp .end_f + @@: + + ; Write the trailer +if GZIP eq 1 + cmp dword[edi+deflate_state.wrap],2 + jne @f ;if (..==..) + mov ecx,[ebx+z_stream.adler] + put_dword edi, ecx + mov ecx,[ebx+z_stream.total_in] + put_dword edi, ecx + jmp .end17 + @@: ;else +end if + mov ecx,[ebx+z_stream.adler] + bswap ecx + put_dword edi, ecx + .end17: + stdcall flush_pending, ebx + ; If avail_out is zero, the application will call deflate again + ; to flush the rest. + + cmp word[edi+deflate_state.pending],0 + jle @f ;if (..>0) ;write the trailer only once! + neg word[edi+deflate_state.pending] + inc word[edi+deflate_state.pending] + @@: + mov eax,Z_OK + cmp word[edi+deflate_state.pending],0 + je .end_f + mov eax,Z_STREAM_END +.end_f: +zlib_debug ' deflate.ret = %d',eax + ret +endp + +; ========================================================================= +;int (strm) +; z_streamp strm; +align 4 +proc deflateEnd uses ebx ecx edx, strm:dword + mov ebx,[strm] +zlib_debug 'deflateEnd' + cmp ebx,Z_NULL + je @f + mov edx,[ebx+z_stream.state] + cmp edx,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0) return .. + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + + mov ecx,[edx+deflate_state.status] + cmp ecx,INIT_STATE + je @f + cmp ecx,EXTRA_STATE + je @f + cmp ecx,NAME_STATE + je @f + cmp ecx,COMMENT_STATE + je @f + cmp ecx,HCRC_STATE + je @f + cmp ecx,BUSY_STATE + je @f + cmp ecx,FINISH_STATE + je @f ;if (..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=.. && ..!=..) + mov eax,Z_STREAM_ERROR + jmp .end_f + @@: + + ; Deallocate in reverse order of allocations: + TRY_FREE ebx, dword[edx+deflate_state.pending_buf] + TRY_FREE ebx, dword[edx+deflate_state.head] + TRY_FREE ebx, dword[edx+deflate_state.prev] + TRY_FREE ebx, dword[edx+deflate_state.window] + + ZFREE ebx, dword[ebx+z_stream.state] + mov dword[ebx+z_stream.state],Z_NULL + + mov eax,Z_DATA_ERROR + cmp ecx,BUSY_STATE + je .end_f + mov eax,Z_OK +.end_f: + ret +endp + +; ========================================================================= +; Copy the source state to the destination state. +; To simplify the source, this is not supported for 16-bit MSDOS (which +; doesn't have enough memory anyway to duplicate compression states). + +;int (dest, source) +; z_streamp dest; +; z_streamp source; +align 4 +proc deflateCopy uses edx edi esi, dest:dword, source:dword +locals + overlay dd ? ;uint_16p +endl +;edi = ds; deflate_state* +;esi = ss; deflate_state* + + mov esi,[source] + cmp esi,Z_NULL + je @f + mov edx,[dest] + cmp edx,Z_NULL + je @f + mov esi,[esi+z_stream.state] + cmp esi,Z_NULL + jne .end0 + @@: ;if (..==0 || ..==0 || ..==0) + mov eax,Z_STREAM_ERROR + jmp .end_f + .end0: + + stdcall zmemcpy, edx, [source], sizeof.z_stream + + ZALLOC edx, 1, sizeof.deflate_state + cmp eax,0 + jne @f ;if (..==0) return .. + mov eax,Z_MEM_ERROR + jmp .end_f + @@: + mov edi,eax + mov [edx+z_stream.state],eax + stdcall zmemcpy, edi, esi, sizeof.deflate_state + mov dword[edi+deflate_state.strm],edx + + ZALLOC edx, [edi+deflate_state.w_size], 2 ;2*sizeof.db + mov dword[edi+deflate_state.window],eax + ZALLOC edx, [edi+deflate_state.w_size], 4 ;sizeof.dd + mov dword[edi+deflate_state.prev],eax + ZALLOC edx, [edi+deflate_state.hash_size], 4 ;sizeof.dd + mov dword[edi+deflate_state.head],eax + ZALLOC edx, [edi+deflate_state.lit_bufsize], 4 ;sizeof.dw+2 + mov [overlay],eax + mov dword[edi+deflate_state.pending_buf],eax + + cmp dword[edi+deflate_state.window],Z_NULL + je @f + cmp dword[edi+deflate_state.prev],Z_NULL + je @f + cmp dword[edi+deflate_state.head],Z_NULL + je @f + cmp dword[edi+deflate_state.pending_buf],Z_NULL + jne .end1 + @@: ;if (..==0 || ..==0 || ..==0 || ..==0) + stdcall deflateEnd, edx + mov eax,Z_MEM_ERROR + jmp .end_f + .end1: + + ; following zmemcpy do not work for 16-bit MSDOS + mov eax,[edi+deflate_state.w_size] + shl eax,1 ;*= 2*sizeof.db + stdcall zmemcpy, [edi+deflate_state.window], [esi+deflate_state.window], eax +; zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); +; zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); +; zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + +; ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); +; ds->d_buf = overlay + ds->lit_bufsize/sizeof(uint_16); +; ds->l_buf = ds->pending_buf + (1+sizeof(uint_16))*ds->lit_bufsize; + + mov eax,edi + add eax,deflate_state.dyn_ltree + mov [edi+deflate_state.l_desc.dyn_tree],eax + add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree + mov [edi+deflate_state.d_desc.dyn_tree],eax + add eax,deflate_state.bl_tree-deflate_state.dyn_dtree + mov [edi+deflate_state.bl_desc.dyn_tree],eax + + mov eax,Z_OK +.end_f: + ret +endp + +; =========================================================================== +; Read a new buffer from the current input stream, update the adler32 +; and total number of bytes read. All deflate() input goes through +; this function so some applications may wish to modify it to avoid +; allocating a large strm->next_in buffer and copying from it. +; (See also flush_pending()). + +;int (strm, buf, size) +; z_streamp strm; +; Bytef *buf; +; unsigned size; +align 4 +proc read_buf uses ebx ecx, strm:dword, buf:dword, size:dword + mov ebx,[strm] + movzx eax,word[ebx+z_stream.avail_in] + + cmp eax,[size] + jle @f ;if (..>..) + mov eax,[size] + @@: + cmp eax,0 + jg @f + xor eax,eax + jmp .end_f ;if (..==0) return 0 + @@: + + sub [ebx+z_stream.avail_in],ax + + stdcall zmemcpy, [buf],[ebx+z_stream.next_in],eax + mov ecx,[ebx+z_stream.state] + cmp [ecx+deflate_state.wrap],1 + jne @f ;if (..==..) + push eax + stdcall adler32, [ebx+z_stream.adler], [buf], eax + mov [ebx+z_stream.adler],eax + pop eax + jmp .end0 + @@: +if GZIP eq 1 + cmp [ecx+deflate_state.wrap],2 + jne .end0 ;else if (..==..) + push eax + stdcall calc_crc32, [ebx+z_stream.adler], [buf], eax + mov [ebx+z_stream.adler],eax + pop eax +end if + .end0: + add [ebx+z_stream.next_in],eax + add [ebx+z_stream.total_in],eax + +.end_f: +;zlib_debug ' read_buf.ret = %d',eax + ret +endp + +; =========================================================================== +; Initialize the "longest match" routines for a new zlib stream + +;void (s) +; deflate_state *s +align 4 +proc lm_init uses eax ebx edi, s:dword + mov edi,[s] + mov eax,[edi+deflate_state.w_size] + shl eax,1 + mov [edi+deflate_state.window_size],eax + + CLEAR_HASH edi + + ; Set the default configuration parameters: + + movzx eax,word[edi+deflate_state.level] + imul eax,sizeof.config_s + add eax,configuration_table + movzx ebx,word[eax+config_s.max_lazy] + mov [edi+deflate_state.max_lazy_match],ebx + movzx ebx,word[eax+config_s.good_length] + mov [edi+deflate_state.good_match],ebx + movzx ebx,word[eax+config_s.nice_length] + mov [edi+deflate_state.nice_match],ebx + movzx ebx,word[eax+config_s.max_chain] + mov [edi+deflate_state.max_chain_length],ebx + + mov dword[edi+deflate_state.strstart],0 + mov dword[edi+deflate_state.block_start],0 + mov dword[edi+deflate_state.lookahead],0 + mov dword[edi+deflate_state.insert],0 + mov dword[edi+deflate_state.prev_length],MIN_MATCH-1 + mov dword[edi+deflate_state.match_length],MIN_MATCH-1 + mov dword[edi+deflate_state.match_available],0 + mov dword[edi+deflate_state.ins_h],0 +if FASTEST eq 0 +;if ASMV +; call match_init ;initialize the asm code +;end if +end if + ret +endp + +;uInt (s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ +align 4 +proc longest_match uses ebx ecx edx edi esi, s:dword, cur_match:dword +if FASTEST eq 0 +; =========================================================================== +; Set match_start to the longest match starting at the given string and +; return its length. Matches shorter or equal to prev_length are discarded, +; in which case the result is equal to prev_length and match_start is +; garbage. +; IN assertions: cur_match is the head of the hash chain for the current +; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 +; OUT assertion: the match length is not greater than s->lookahead. + +;#ifndef ASMV +; For 80x86 and 680x0, an optimized version will be provided in match.asm or +; match.S. The code will be functionally equivalent. + +; unsigned chain_length = s->max_chain_length;/* max hash chain length */ +; register Bytef *scan = s->window + s->strstart; /* current string */ +; register Bytef *match; /* matched string */ +; register int len; /* length of current match */ +; int best_len = s->prev_length; /* best match length so far */ +; int nice_match = s->nice_match; /* stop if match long enough */ +; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +; s->strstart - (IPos)MAX_DIST(s) : NIL; + ; Stop when cur_match becomes <= limit. To simplify the code, + ; we prevent matches with the string of window index 0. + +; Posf *prev = s->prev; +; uInt wmask = s->w_mask; + +if UNALIGNED_OK eq 1 + ; Compare two bytes at a time. Note: this is not always beneficial. + ; Try with and without -DUNALIGNED_OK to check. + +; register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; +; register uint_16 scan_start = *(uint_16p*)scan; +; register uint_16 scan_end = *(uint_16p*)(scan+best_len-1); +else +; register Bytef *strend = s->window + s->strstart + MAX_MATCH; +; register Byte scan_end1 = scan[best_len-1]; +; register Byte scan_end = scan[best_len]; +end if + + ; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + ; It is easy to get rid of this optimization if necessary. + +; Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + ; Do not waste too much time if we already have a good match: +; if (s->prev_length >= s->good_match) { +; chain_length >>= 2; +; } + ; Do not look for matches beyond the end of the input. This is necessary + ; to make deflate deterministic. + +; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + +; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + +; do { +; Assert(cur_match < s->strstart, "no future"); +; match = s->window + cur_match; + + ; Skip to next match if the match length cannot increase + ; or if the match length is less than 2. Note that the checks below + ; for insufficient lookahead only occur occasionally for performance + ; reasons. Therefore uninitialized memory will be accessed, and + ; conditional jumps will be made that depend on those values. + ; However the length of the match is limited to the lookahead, so + ; the output of deflate is not affected by the uninitialized values. + +if ((UNALIGNED_OK eq 1) & MAX_MATCH == 258) + ; This code assumes sizeof(unsigned short) == 2. Do not use + ; UNALIGNED_OK if your compiler uses a different size. + +; if (*(uint_16p*)(match+best_len-1) != scan_end || +; *(uint_16p*)match != scan_start) continue; + + ; It is not necessary to compare scan[2] and match[2] since they are + ; always equal when the other bytes match, given that the hash keys + ; are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + ; strstart+3, +5, ... up to strstart+257. We check for insufficient + ; lookahead only every 4th comparison; the 128th check will be made + ; at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + ; necessary to put more guard bytes at the end of the window, or + ; to check more often for insufficient lookahead. + +; Assert(scan[2] == match[2], "scan[2]?"); +; scan++, match++; +; do { +; } while (*(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) && +; *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) && +; *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) && +; *(uint_16p*)(scan+=2) == *(uint_16p*)(match+=2) && +; scan < strend); + ; The funny "do {}" generates better code on most compilers + + ; Here, scan <= window+strstart+257 +; Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); +; if (*scan == *match) scan++; + +; len = (MAX_MATCH - 1) - (int)(strend-scan); +; scan = strend - (MAX_MATCH-1); + +else ;UNALIGNED_OK + +; if (match[best_len] != scan_end || +; match[best_len-1] != scan_end1 || +; *match != *scan || +; *++match != scan[1]) continue; + + ; The check at best_len-1 can be removed because it will be made + ; again later. (This heuristic is not always a win.) + ; It is not necessary to compare scan[2] and match[2] since they + ; are always equal when the other bytes match, given that + ; the hash keys are equal and that HASH_BITS >= 8. + +; scan += 2, match++; +; Assert(*scan == *match, "match[2]?"); + + ; We check for insufficient lookahead only every 8th comparison; + ; the 256th check will be made at strstart+258. + +; do { +; } while (*++scan == *++match && *++scan == *++match && +; *++scan == *++match && *++scan == *++match && +; *++scan == *++match && *++scan == *++match && +; *++scan == *++match && *++scan == *++match && +; scan < strend); + +; Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + +; len = MAX_MATCH - (int)(strend - scan); +; scan = strend - MAX_MATCH; + +end if ;UNALIGNED_OK + +; if (len > best_len) { +; s->match_start = cur_match; +; best_len = len; +; if (len >= nice_match) break; +if UNALIGNED_OK eq 1 +; scan_end = *(uint_16p*)(scan+best_len-1); +else +; scan_end1 = scan[best_len-1]; +; scan_end = scan[best_len]; +end if +; } +; } while ((cur_match = prev[cur_match & wmask]) > limit +; && --chain_length != 0); + +; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +; return s->lookahead; +;end if /* ASMV */ + +else ;FASTEST + +; --------------------------------------------------------------------------- +; Optimized version for FASTEST only + mov edx,[s] +;zlib_debug 'longest_match' + + ; The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + ; It is easy to get rid of this optimization if necessary. + +if MAX_MATCH <> 258 + cmp dword[edx+deflate_state.hash_bits],8 + jge @f + zlib_debug 'Code too clever' ;Assert(..>=.. && ..==..) + @@: +end if + mov eax,[edx+deflate_state.window_size] + sub eax,MIN_LOOKAHEAD + cmp [edx+deflate_state.strstart],eax + jle @f + zlib_debug 'need lookahead' ;Assert(..<=..) + @@: + mov eax,[edx+deflate_state.strstart] + cmp [cur_match],eax + jl @f + zlib_debug 'no future' ;Assert(..<..) + @@: + + mov esi,[edx+deflate_state.window] + mov edi,esi + add esi,[cur_match] + add edi,[edx+deflate_state.strstart] + ;edi = scan + ;esi = match + + ; Return failure if the match length is less than 2: + + lodsw + cmp ax,word[edi] + je @f ;if (word[edi] != word[esi]) return + mov eax,MIN_MATCH-1 + jmp .end_f + @@: + + ; The check at best_len-1 can be removed because it will be made + ; again later. (This heuristic is not always a win.) + ; It is not necessary to compare scan[2] and match[2] since they + ; are always equal when the other bytes match, given that + ; the hash keys are equal and that HASH_BITS >= 8. + + add edi,2 + mov al,byte[edi] + cmp al,byte[esi] + je @f + zlib_debug 'match[2]?' ;Assert(..==..) + @@: + + ; We check for insufficient lookahead only every 8th comparison; + ; the 256th check will be made at strstart+258. + + mov ebx,edi + mov ecx,MAX_MATCH +align 4 + @@: + lodsb + scasb + loope @b + + mov eax,[edx+deflate_state.window_size] + dec eax + add eax,[edx+deflate_state.window] + cmp edi,eax + jle @f + zlib_debug 'wild scan' ;Assert(..<=..) + @@: + sub edi,ebx + ;edi = len + + cmp edi,MIN_MATCH + jge @f ;if (..<..) + mov eax,MIN_MATCH-1 + jmp .end_f + @@: + mov eax,[cur_match] + mov [edx+deflate_state.match_start],eax + mov eax,[edx+deflate_state.lookahead] + cmp edi,eax + jg @f ;if (len <= s.lookahead) ? len : s.lookahead + mov eax,edi + @@: +end if ;FASTEST +.end_f: +;zlib_debug ' longest_match.ret = %d',eax + ret +endp + + +; =========================================================================== +; Check that the match at match_start is indeed a match. + +;void (s, start, match, length) +; deflate_state *s; +; IPos start, match; +; int length; +align 4 +proc check_match, s:dword, start:dword, p3match:dword, length:dword +if DEBUG eq 1 + ; check that the match is indeed a match +; if (zmemcmp(s->window + match, +; s->window + start, length) != EQUAL) { +; fprintf(stderr, " start %u, match %u, length %d\n", +; start, match, length); +; do { +; fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); +; } while (--length != 0); +; z_error("invalid match"); +; } +; if (z_verbose > 1) { +; fprintf(stderr,"\\[%d,%d]", start-match, length); +; do { putc(s->window[start++], stderr); } while (--length != 0); +; } +end if ;DEBUG + ret +endp + + +; =========================================================================== +; Fill the window when the lookahead becomes insufficient. +; Updates strstart and lookahead. + +; IN assertion: lookahead < MIN_LOOKAHEAD +; OUT assertions: strstart <= window_size-MIN_LOOKAHEAD +; At least one byte has been read, or avail_in == 0; reads are +; performed for at least two bytes (required for the zip translate_eol +; option -- not supported here). + +;void (s) +; deflate_state *s +align 4 +proc fill_window, s:dword +pushad +;esi = p, str, curr +;ebx = more ;Amount of free space at the end of the window. + ;Объем свободного пространства в конце окна. +;ecx = wsize ;uInt +;edx = s.strm +;zlib_debug 'fill_window' + mov edi,[s] + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jl @f + zlib_debug 'already enough lookahead' ;Assert(..<..) + @@: + + mov ecx,[edi+deflate_state.w_size] + mov edx,[edi+deflate_state.strm] + .cycle0: ;do +;zlib_debug 'do' + mov ebx,[edi+deflate_state.window_size] + sub ebx,[edi+deflate_state.lookahead] + sub ebx,[edi+deflate_state.strstart] + + ; If the window is almost full and there is insufficient lookahead, + ; move the upper half to the lower one to make room in the upper half. + + MAX_DIST edi + add eax,ecx + cmp [edi+deflate_state.strstart],eax + jl .end0 ;if (..>=..) + push ecx + mov eax,[edi+deflate_state.window] + add eax,ecx + stdcall zmemcpy, [edi+deflate_state.window], eax + sub [edi+deflate_state.match_start],ecx + sub [edi+deflate_state.strstart],ecx ;we now have strstart >= MAX_DIST + sub [edi+deflate_state.block_start],ecx + + ; Slide the hash table (could be avoided with 32 bit values + ; at the expense of memory usage). We slide even when level == 0 + ; to keep the hash table consistent if we switch back to level > 0 + ; later. (Using level 0 permanently is not an optimal usage of + ; zlib, so we don't care about this pathological case.) + + push ebx ecx + ;ebx = wsize + ;ecx = n + mov ebx,ecx + mov ecx,[edi+deflate_state.hash_size] + mov esi,ecx + shl esi,2 + add esi,[edi+deflate_state.head] + .cycle1: ;do + sub esi,4 + mov eax,[esi] + mov dword[esi],NIL + cmp eax,ebx + jl @f + sub eax,ebx + mov dword[esi],eax + @@: + loop .cycle1 ;while (..) + + mov ecx,ebx +if FASTEST eq 0 + mov esi,ecx + shl esi,2 + add esi,[edi+deflate_state.prev] + .cycle2: ;do + sub esi,4 + mov eax,[esi] + mov dword[esi],NIL + cmp eax,ebx + jl @f + sub eax,ebx + mov dword[esi],eax + @@: + ; If n is not on any hash chain, prev[n] is garbage but + ; its value will never be used. + + loop .cycle2 ;while (..) +end if + pop ecx ebx + add ebx,ecx + .end0: + cmp word[edx+z_stream.avail_in],0 + je .cycle0end ;if (..==0) break + + ; If there was no sliding: + ; strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + ; more == window_size - lookahead - strstart + ; => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + ; => more >= window_size - 2*WSIZE + 2 + ; In the BIG_MEM or MMAP case (not yet supported), + ; window_size == input_size + MIN_LOOKAHEAD && + ; strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + ; Otherwise, window_size == 2*WSIZE so more >= 2. + ; If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + cmp ebx,2 + jge @f + zlib_debug 'more < 2' ;Assert(..>=..) + @@: + mov eax,[edi+deflate_state.window] + add eax,[edi+deflate_state.strstart] + add eax,[edi+deflate_state.lookahead] + stdcall read_buf, edx, eax, ebx + add [edi+deflate_state.lookahead],eax + + ; Initialize the hash value now that we have some input: + mov eax,[edi+deflate_state.lookahead] + add eax,[edi+deflate_state.insert] + cmp eax,MIN_MATCH + jl .end1 ;if (..>=..) + mov esi,[edi+deflate_state.strstart] + sub esi,[edi+deflate_state.insert] + ;esi = str + mov eax,[edi+deflate_state.window] + add eax,esi + mov [edi+deflate_state.ins_h],eax + inc eax + movzx eax,byte[eax] + UPDATE_HASH edi, [edi+deflate_state.ins_h], eax +if MIN_MATCH <> 3 +; Call UPDATE_HASH() MIN_MATCH-3 more times +end if + .cycle3: ;while (..) + cmp dword[edi+deflate_state.insert],0 + je .end1 + mov eax,esi + add eax,MIN_MATCH-1 + add eax,[edi+deflate_state.window] + movzx eax,byte[eax] + UPDATE_HASH edi, [edi+deflate_state.ins_h], eax +if FASTEST eq 0 + mov eax,[edi+deflate_state.ins_h] + shl eax,2 + add eax,[edi+deflate_state.head] + push ebx + mov ebx,[edi+deflate_state.w_mask] + and ebx,esi + shl ebx,2 + add ebx,[edi+deflate_state.prev] + mov eax,[eax] + mov [ebx],eax + pop ebx +end if + mov eax,[edi+deflate_state.ins_h] + shl eax,2 + add eax,[edi+deflate_state.head] + mov [eax],esi + inc esi + dec dword[edi+deflate_state.insert] + mov eax,[edi+deflate_state.lookahead] + add eax,[edi+deflate_state.insert] + cmp eax,MIN_MATCH + jl .end1 ;if (..<..) break + jmp .cycle3 + .end1: + ; If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + ; but this is not important since only literal bytes will be emitted. + + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jge .cycle0end + cmp word[edx+z_stream.avail_in],0 + jne .cycle0 + .cycle0end: ;while (..<.. && ..!=..) + + ; If the WIN_INIT bytes after the end of the current data have never been + ; written, then zero those bytes in order to avoid memory check reports of + ; the use of uninitialized (or uninitialised as Julian writes) bytes by + ; the longest match routines. Update the high water mark for the next + ; time through here. WIN_INIT is set to MAX_MATCH since the longest match + ; routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + + mov eax,[edi+deflate_state.window_size] + cmp [edi+deflate_state.high_water],eax + jge .end2 ;if (..<..) + mov esi,[edi+deflate_state.lookahead] + add esi,[edi+deflate_state.strstart] + ;esi = curr + + cmp [edi+deflate_state.high_water],esi + jge .end3 ;if (..<..) + ; Previous high water mark below current data -- zero WIN_INIT + ; bytes or up to end of window, whichever is less. + + mov eax,[edi+deflate_state.window_size] + sub eax,esi + cmp eax,WIN_INIT + jle @f ;if (..>..) + mov eax,WIN_INIT + @@: + mov edx,[edi+deflate_state.window] + add edx,esi + stdcall zmemzero, edx, eax + add eax,esi + mov [edi+deflate_state.high_water],eax + jmp .end2 + .end3: ;else if (..<..) + mov eax,esi + add eax,WIN_INIT + cmp [edi+deflate_state.high_water],eax + jge .end2 + ; High water mark at or above current data, but below current data + ; plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + ; to end of window, whichever is less. + + ;eax = esi+WIN_INIT + sub eax,[edi+deflate_state.high_water] + mov edx,[edi+deflate_state.window_size] + sub edx,[edi+deflate_state.high_water] + cmp eax,edx ;if (..>..) + jle @f + mov eax,edx + @@: + mov edx,[edi+deflate_state.window] + add edx,[edi+deflate_state.high_water] + stdcall zmemzero, edx, eax + add [edi+deflate_state.high_water],eax + .end2: + + mov eax,[edi+deflate_state.window_size] + sub eax,MIN_LOOKAHEAD + cmp [edi+deflate_state.strstart],eax + jle @f + zlib_debug 'not enough room for search' ;Assert(..<=..) + @@: +popad + ret +endp + +; =========================================================================== +; Flush the current block, with given end-of-file flag. +; IN assertion: strstart is set to the end of the current match. + +macro FLUSH_BLOCK_ONLY s, last +{ +local .end0 + push dword last + mov eax,[s+deflate_state.strstart] + sub eax,[s+deflate_state.block_start] + push eax + xor eax,eax + cmp dword[s+deflate_state.block_start],0 + jl .end0 + mov eax,[s+deflate_state.block_start] + add eax,[s+deflate_state.window] + .end0: + stdcall _tr_flush_block, s, eax + mov eax,[s+deflate_state.strstart] + mov [s+deflate_state.block_start],eax + stdcall flush_pending, [s+deflate_state.strm] +; Tracev((stderr,"[FLUSH]")); +} + +; Same but force premature exit if necessary. +macro FLUSH_BLOCK s, last +{ +local .end0 + FLUSH_BLOCK_ONLY s, last + mov eax,[s+deflate_state.strm] + cmp word[eax+z_stream.avail_out],0 + jne .end0 ;if (..==0) +if last eq 1 + mov eax,finish_started +else + mov eax,need_more +end if + jmp .end_f + .end0: +} + +; =========================================================================== +; Copy without compression as much as possible from the input stream, return +; the current block state. +; This function does not insert new strings in the dictionary since +; uncompressible data is probably not useful. This function is used +; only for the level=0 compression option. +; NOTE: this function should be optimized to avoid extra copying from +; window to pending_buf. + +;block_state (s, flush) +; deflate_state *s; +; int flush; +align 4 +proc deflate_stored uses ebx ecx edi, s:dword, flush:dword +; Stored blocks are limited to 0xffff bytes, pending_buf is limited +; to pending_buf_size, and each stored block has a 5 byte header: + mov edi,[s] +zlib_debug 'deflate_stored' + + mov ecx,0xffff + mov eax,[edi+deflate_state.pending_buf_size] + sub eax,5 + cmp ecx,eax + jle @f ;if (..>..) + mov ecx,eax + @@: + ;ecx = max_block_size + + ; Copy as much as possible from input to output: + .cycle0: ;for (;;) { + ; Fill the window as much as possible: + cmp dword[edi+deflate_state.lookahead],1 + jg .end0 ;if (..<=..) +; Assert(s->strstart < s->w_size+MAX_DIST(s) || +; s->block_start >= (long)s->w_size, "slide too late"); + + stdcall fill_window, edi + cmp dword[edi+deflate_state.lookahead],0 + jne @f + cmp dword[flush],Z_NO_FLUSH + jne @f ;if (..==0 && ..==..) + mov eax,need_more + jmp .end_f + @@: + cmp dword[edi+deflate_state.lookahead],0 + je .cycle0end ;if (..==0) break ;flush the current block + .end0: +; Assert(s->block_start >= 0, "block gone"); + + mov eax,[edi+deflate_state.lookahead] + add [edi+deflate_state.strstart],eax + mov dword[edi+deflate_state.lookahead],0 + + ; Emit a stored block if pending_buf will be full: + mov ebx,[edi+deflate_state.block_start] + add ebx,ecx + cmp dword[edi+deflate_state.strstart],0 + je @f + cmp [edi+deflate_state.strstart],ebx + jl .end1 + @@: ;if (..==0 || ..>=..) + ; strstart == 0 is possible when wraparound on 16-bit machine + mov eax,[edi+deflate_state.strstart] + sub eax,ebx + mov [edi+deflate_state.lookahead],eax + mov [edi+deflate_state.strstart],ebx + FLUSH_BLOCK edi, 0 + .end1: + ; Flush if we may have to slide, otherwise block_start may become + ; negative and the data will be gone: + + MAX_DIST edi + mov ebx,[edi+deflate_state.strstart] + sub ebx,[edi+deflate_state.block_start] + cmp ebx,eax + jl .cycle0 ;if (..>=..) + FLUSH_BLOCK edi, 0 + jmp .cycle0 +align 4 + .cycle0end: + mov dword[edi+deflate_state.insert],0 + cmp dword[flush],Z_FINISH + jne @f ;if (..==..) + FLUSH_BLOCK edi, 1 + mov eax,finish_done + jmp .end_f + @@: + mov eax,[edi+deflate_state.block_start] + cmp [edi+deflate_state.strstart],eax + jle @f ;if (..>..) + FLUSH_BLOCK edi, 0 + @@: + mov eax,block_done +.end_f: + ret +endp + +; =========================================================================== +; Compress as much as possible from the input stream, return the current +; block state. +; This function does not perform lazy evaluation of matches and inserts +; new strings in the dictionary only for unmatched strings or for short +; matches. It is used only for the fast compression options. + +;block_state (s, flush) +; deflate_state *s +; int flush +align 4 +proc deflate_fast uses ebx ecx edi, s:dword, flush:dword +locals + bflush dd ? ;int ;set if current block must be flushed +endl +;ecx = hash_head ;IPos ;head of the hash chain + mov edi,[s] +zlib_debug 'deflate_fast' + + .cycle0: ;for (..) + ; Make sure that we always have enough lookahead, except + ; at the end of the input file. We need MAX_MATCH bytes + ; for the next match, plus MIN_MATCH bytes to insert the + ; string following the next match. + + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jge .end0 ;if (..<..) + stdcall fill_window, edi + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jge @f ;if (..<.. && ..==..) + cmp dword[flush],Z_NO_FLUSH + jne @f + mov eax,need_more + jmp .end_f +align 4 + @@: + cmp dword[edi+deflate_state.lookahead],0 + je .cycle0end ;if (..==0) break ;flush the current block +align 4 + .end0: + + ; Insert the string window[strstart .. strstart+2] in the + ; dictionary, and set hash_head to the head of the hash chain: + + mov ecx,NIL + cmp dword[edi+deflate_state.lookahead],MIN_MATCH + jl @f ;if (..>=..) + INSERT_STRING edi, [edi+deflate_state.strstart], ecx + @@: + + ; Find the longest match, discarding those <= prev_length. + ; At this point we have always match_length < MIN_MATCH + + cmp ecx,NIL + je @f + MAX_DIST edi + mov ebx,[edi+deflate_state.strstart] + sub ebx,ecx + cmp ebx,eax + jg @f ;if (..!=0 && ..<=..) + ; To simplify the code, we prevent matches with the string + ; of window index 0 (in particular we have to avoid a match + ; of the string with itself at the start of the input file). + + stdcall longest_match, edi, ecx + mov [edi+deflate_state.match_length],eax + ; longest_match() sets match_start + @@: + cmp dword[edi+deflate_state.match_length],MIN_MATCH + jl .end1 ;if (..>=..) + stdcall check_match, edi, [edi+deflate_state.strstart], [edi+deflate_state.match_start], [edi+deflate_state.match_length] + + mov eax,[edi+deflate_state.strstart] + sub eax,[edi+deflate_state.match_start] + mov ebx,[edi+deflate_state.match_length] + sub ebx,MIN_MATCH + _tr_tally_dist edi, eax, ebx, [bflush] + + mov eax,[edi+deflate_state.match_length] + sub [edi+deflate_state.lookahead],eax + + ; Insert new strings in the hash table only if the match length + ; is not too large. This saves time but degrades compression. + +if FASTEST eq 0 + ;;mov eax,[edi+deflate_state.match_length] + cmp eax,[edi+deflate_state.max_insert_length] + jg .end3 + cmp dword[edi+deflate_state.lookahead],MIN_MATCH + jl .end3 ;if (..<=.. && ..>=..) + dec dword[edi+deflate_state.match_length] ;string at strstart already in table + .cycle1: ;do { + inc dword[edi+deflate_state.strstart] + INSERT_STRING edi, [edi+deflate_state.strstart], ecx + ; strstart never exceeds WSIZE-MAX_MATCH, so there are + ; always MIN_MATCH bytes ahead. + + dec dword[edi+deflate_state.match_length] + cmp dword[edi+deflate_state.match_length],0 + jne .cycle1 ;while (..!=0) + inc dword[edi+deflate_state.strstart] + jmp .end2 + .end3: ;else +end if + + mov eax,[edi+deflate_state.match_length] + add [edi+deflate_state.strstart],eax + mov dword[edi+deflate_state.match_length],0 + mov eax,[edi+deflate_state.window] + add eax,[edi+deflate_state.strstart] + mov [edi+deflate_state.ins_h],eax + inc eax + movzx eax,byte[eax] + UPDATE_HASH edi, [edi+deflate_state.ins_h], eax +if MIN_MATCH <> 3 +; Call UPDATE_HASH() MIN_MATCH-3 more times +end if + ; If lookahead < MIN_MATCH, ins_h is garbage, but it does not + ; matter since it will be recomputed at next deflate call. + jmp .end2 + .end1: ;else + ; No match, output a literal byte + mov eax,[edi+deflate_state.window] + add eax,[edi+deflate_state.strstart] + movzx eax,byte[eax] + Tracevv eax, + _tr_tally_lit edi, eax, [bflush] + dec dword[edi+deflate_state.lookahead] + inc dword[edi+deflate_state.strstart] + .end2: + cmp dword[bflush],0 + je .cycle0 ;if (..) + FLUSH_BLOCK edi, 0 + jmp .cycle0 +align 4 + .cycle0end: + mov eax,[edi+deflate_state.strstart] + cmp eax,MIN_MATCH-1 + jl @f + mov eax,MIN_MATCH-1 + @@: + mov [edi+deflate_state.insert],eax + cmp dword[flush],Z_FINISH + jne @f ;if (..==..) + FLUSH_BLOCK edi, 1 + mov eax,finish_done + jmp .end_f + @@: + cmp dword[edi+deflate_state.last_lit],0 + je @f ;if (..) + FLUSH_BLOCK edi, 0 + @@: + mov eax,block_done +.end_f: + ret +endp + +; =========================================================================== +; Same as above, but achieves better compression. We use a lazy +; evaluation for matches: a match is finally adopted only if there is +; no better match at the next window position. + +;block_state (s, flush) +; deflate_state *s +; int flush +align 4 +proc deflate_slow uses ebx ecx edx edi, s:dword, flush:dword +locals + bflush dd ? ;int ;set if current block must be flushed +endl +;ecx = hash_head ;IPos ;head of the hash chain + mov edi,[s] +zlib_debug 'deflate_slow' + + ; Process the input block. + .cycle0: ;for (;;) + ; Make sure that we always have enough lookahead, except + ; at the end of the input file. We need MAX_MATCH bytes + ; for the next match, plus MIN_MATCH bytes to insert the + ; string following the next match. + + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jge .end0 ;if (..<..) + stdcall fill_window, edi + cmp dword[edi+deflate_state.lookahead],MIN_LOOKAHEAD + jge @f ;if (..<.. && ..==..) + cmp dword[flush],Z_NO_FLUSH + jne @f + mov eax,need_more + jmp .end_f +align 4 + @@: + cmp dword[edi+deflate_state.lookahead],0 + je .cycle0end ;if (..==0) break ;flush the current block +align 4 + .end0: + + ; Insert the string window[strstart .. strstart+2] in the + ; dictionary, and set hash_head to the head of the hash chain: + + mov ecx,NIL + cmp dword[edi+deflate_state.lookahead],MIN_MATCH + jl @f ;if (..>=..) + INSERT_STRING edi, [edi+deflate_state.strstart], ecx + @@: + + ; Find the longest match, discarding those <= prev_length. + + mov eax,[edi+deflate_state.match_length] + mov [edi+deflate_state.prev_length],eax + mov eax,[edi+deflate_state.match_start] + mov [edi+deflate_state.prev_match],eax + mov dword[edi+deflate_state.match_length],MIN_MATCH-1 + + cmp ecx,NIL + je @f + mov eax,[edi+deflate_state.prev_length] + cmp eax,[edi+deflate_state.max_lazy_match] + jge @f + MAX_DIST edi + mov ebx,[edi+deflate_state.strstart] + sub ebx,ecx + cmp ebx,eax + jg .end1 ;if (..!=0 && ..<.. && ..<=..) + ; To simplify the code, we prevent matches with the string + ; of window index 0 (in particular we have to avoid a match + ; of the string with itself at the start of the input file). + + stdcall longest_match, edi, ecx + mov [edi+deflate_state.match_length],eax + ; longest_match() sets match_start + + cmp dword[edi+deflate_state.match_length],5 + jg .end1 + cmp word[edi+deflate_state.strategy],Z_FILTERED + jne .end1 +; if (..<=.. && (..==.. +;#if TOO_FAR <= 32767 +; || (s->match_length == MIN_MATCH && +; s->strstart - s->match_start > TOO_FAR) +;end if +; )) + + ; If prev_match is also MIN_MATCH, match_start is garbage + ; but we will ignore the current match anyway. + + mov dword[edi+deflate_state.match_length],MIN_MATCH-1 + .end1: + ; If there was a match at the previous step and the current + ; match is not better, output the previous match: + + + mov eax,[edi+deflate_state.prev_length] + cmp eax,MIN_MATCH + jl .end2: + cmp [edi+deflate_state.match_length],eax + jg .end2: ;if (..>=.. && ..<=..) + mov edx,[edi+deflate_state.strstart] + add edx,[edi+deflate_state.lookahead] + sub edx,MIN_MATCH + ;edx = max_insert + ; Do not insert strings in hash table beyond this. + + mov eax,[edi+deflate_state.strstart] + dec eax + stdcall check_match, edi, eax, [edi+deflate_state.prev_match], [edi+deflate_state.prev_length] + + mov eax,[edi+deflate_state.strstart] + dec eax + sub eax,[edi+deflate_state.prev_match] + mov ebx,[edi+deflate_state.prev_length] + sub ebx,MIN_MATCH + _tr_tally_dist edi, eax, ebx, [bflush] + + ; Insert in hash table all strings up to the end of the match. + ; strstart-1 and strstart are already inserted. If there is not + ; enough lookahead, the last two strings are not inserted in + ; the hash table. + + mov eax,[edi+deflate_state.prev_length] + dec eax + sub [edi+deflate_state.lookahead],eax + sub dword[edi+deflate_state.prev_length],2 + .cycle1: ;do + inc dword[edi+deflate_state.strstart] + cmp [edi+deflate_state.strstart],edx + jg @f ;if (..<=..) + INSERT_STRING edi, [edi+deflate_state.strstart], ecx + @@: + dec dword[edi+deflate_state.prev_length] + cmp dword[edi+deflate_state.prev_length],0 + jne .cycle1 ;while (..!=0) + mov dword[edi+deflate_state.match_available],0 + mov dword[edi+deflate_state.match_length],MIN_MATCH-1 + inc dword[edi+deflate_state.strstart] + + cmp dword[bflush],0 + je .cycle0 ;if (..) + FLUSH_BLOCK edi, 0 + jmp .cycle0 + .end2: ;else if (..) + cmp dword[edi+deflate_state.match_available],0 + je .end3 + ; If there was no match at the previous position, output a + ; single literal. If there was a match but the current match + ; is longer, truncate the previous match to a single literal. + + mov eax,[edi+deflate_state.strstart] + dec eax + add eax,[edi+deflate_state.window] + movzx eax,byte[eax] + Tracevv eax, + _tr_tally_lit edi, eax, [bflush] + cmp dword[bflush],0 + je @f ;if (..) + FLUSH_BLOCK_ONLY edi, 0 + @@: + inc dword[edi+deflate_state.strstart] + dec dword[edi+deflate_state.lookahead] + mov eax,[edi+deflate_state.strm] + cmp word[eax+z_stream.avail_out],0 + jne .cycle0 ;if (..==0) return .. + mov eax,need_more + jmp .end_f + jmp .cycle0 ;.end4 + .end3: ;else + ; There is no previous match to compare with, wait for + ; the next step to decide. + + mov dword[edi+deflate_state.match_available],1 + inc dword[edi+deflate_state.strstart] + dec dword[edi+deflate_state.lookahead] + ;.end4: + jmp .cycle0 + .cycle0end: + cmp dword[flush],Z_NO_FLUSH + jne @f + zlib_debug 'no flush?' ;Assert (..!=..) + @@: + cmp dword[edi+deflate_state.match_available],0 + je @f ;if (..) + mov eax,[edi+deflate_state.strstart] + dec eax + add eax,[edi+deflate_state.window] + movzx eax,byte[eax] + Tracevv eax, + _tr_tally_lit edi, eax, [bflush] + mov dword[edi+deflate_state.match_available],0 + @@: + mov eax,[edi+deflate_state.strstart] + cmp eax,MIN_MATCH-1 + jl @f + mov eax,MIN_MATCH-1 + @@: + mov [edi+deflate_state.insert],eax + cmp dword[flush],Z_FINISH + jne @f ;if (..==..) + FLUSH_BLOCK edi, 1 + mov eax,finish_done + jmp .end_f + @@: + cmp dword[edi+deflate_state.last_lit],0 + je @f ;if (..) + FLUSH_BLOCK edi, 0 + @@: + mov eax,block_done +.end_f: + ret +endp + +; =========================================================================== +; For Z_RLE, simply look for runs of bytes, generate matches only of distance +; one. Do not maintain a hash table. (It will be regenerated if this run of +; deflate switches away from Z_RLE.) + +;block_state (s, flush) +; deflate_state *s; +; int flush; +align 4 +proc deflate_rle uses ecx edx edi esi, s:dword, flush:dword +locals + bflush dd ? ;int ;set if current block must be flushed +; uInt prev; /* byte at distance one to match */ +; Bytef *scan, *strend; /* scan goes up to strend for length of run */ +endl + mov edx,[s] +zlib_debug 'deflate_rle' + .cycle0: ;for (;;) + ; Make sure that we always have enough lookahead, except + ; at the end of the input file. We need MAX_MATCH bytes + ; for the longest run, plus one for the unrolled loop. + cmp dword[edx+deflate_state.lookahead],MAX_MATCH + jg .end0 ;if (..<=..) + stdcall fill_window, edx + cmp dword[edx+deflate_state.lookahead],MAX_MATCH + jg @f + cmp dword[flush],Z_NO_FLUSH + jne @f ;if (..<=.. && ..==..) + mov eax,need_more + jmp .end_f +align 4 + @@: + cmp dword[edx+deflate_state.lookahead],0 + je .cycle0end ;flush the current block +align 4 + .end0: + + ; See how many times the previous byte repeats + mov dword[edx+deflate_state.match_length],0 + cmp dword[edx+deflate_state.lookahead],MIN_MATCH + jl .end1 + cmp dword[edx+deflate_state.strstart],0 + jle .end1 ;if (..>=.. && ..>..) + mov esi,[edx+deflate_state.window] + add esi,[edx+deflate_state.strstart] + dec esi + lodsb + mov edi,esi + scasb + jnz .end2 + scasb + jnz .end2 + scasb + jnz .end2 ;if (..==.. && ..==.. && ..==..) + ;edi = scan + ; al = prev + ;ecx = strend-scan + mov ecx,MAX_MATCH-2 + repz scasb + sub edi,[edx+deflate_state.window] + sub edi,[edx+deflate_state.strstart] + mov [edx+deflate_state.match_length],edi + mov eax,[edx+deflate_state.lookahead] + cmp [edx+deflate_state.match_length],eax + jle .end2 + mov [edx+deflate_state.match_length],eax + .end2: + mov eax,[edx+deflate_state.window_size] + dec eax + add eax,[edx+deflate_state.window] + cmp edi,eax + jle .end1 + zlib_debug 'wild scan' ;Assert(..<=..) + .end1: + + ; Emit match if have run of MIN_MATCH or longer, else emit literal + cmp dword[edx+deflate_state.match_length],MIN_MATCH + jl @f ;if (..>=..) + push dword[edx+deflate_state.match_length] + mov eax,[edx+deflate_state.strstart] + dec eax + stdcall check_match, edx, [edx+deflate_state.strstart], eax + + mov eax,[edx+deflate_state.match_length] + sub eax,MIN_MATCH + _tr_tally_dist edx, 1, eax, [bflush] + + mov eax,[edx+deflate_state.match_length] + sub [edx+deflate_state.lookahead],eax + add [edx+deflate_state.strstart],eax + mov dword[edx+deflate_state.match_length],0 + jmp .end3 + @@: ;else + ; No match, output a literal byte + mov eax,[edx+deflate_state.strstart] + add eax,[edx+deflate_state.window] + movzx eax,byte[eax] + Tracevv eax, + _tr_tally_lit edx, eax, [bflush] + dec dword[edx+deflate_state.lookahead] + inc dword[edx+deflate_state.strstart] + .end3: + cmp dword[bflush],0 + je .cycle0 ;if (..) + FLUSH_BLOCK edx, 0 + jmp .cycle0 +align 4 + .cycle0end: + mov dword[edx+deflate_state.insert],0 + cmp dword[flush],Z_FINISH + jne @f ;if (..==..) + FLUSH_BLOCK edx, 1 + mov eax,finish_done + jmp .end_f + @@: + cmp dword[edx+deflate_state.last_lit],0 + je @f ;if (..) + FLUSH_BLOCK edx, 0 + @@: + mov eax,block_done +.end_f: + ret +endp + +; =========================================================================== +; For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. +; (It will be regenerated if this run of deflate switches away from Huffman.) + +;block_state (s, flush) +; deflate_state *s; +; int flush; +align 4 +proc deflate_huff uses ebx edi, s:dword, flush:dword +locals + bflush dd ? ;int ;set if current block must be flushed +endl + mov edi,[s] +zlib_debug 'deflate_huff' + .cycle0: ;for (;;) + ; Make sure that we have a literal to write. + cmp dword[edi+deflate_state.lookahead],0 + jne .end0 ;if (..==0) + stdcall fill_window, edi + cmp dword[edi+deflate_state.lookahead],0 + jne .end0 ;if (..==0) + cmp dword[flush],Z_NO_FLUSH + jne @f ;if (..==..) + mov eax,need_more + jmp .end_f +align 4 + @@: + jmp .cycle0end ;flush the current block +align 4 + .end0: + + ; Output a literal byte + mov dword[edi+deflate_state.match_length],0 + mov eax,[edi+deflate_state.strstart] + add eax,[edi+deflate_state.window] + movzx eax,byte[eax] + Tracevv eax, + _tr_tally_lit edi, eax, [bflush] + dec dword[edi+deflate_state.lookahead] + inc dword[edi+deflate_state.strstart] + cmp dword[bflush],0 + je @f ;if (..) + FLUSH_BLOCK edi, 0 + @@: + jmp .cycle0 +align 4 + .cycle0end: + mov dword[edi+deflate_state.insert],0 + cmp dword[flush],Z_FINISH + jne @f ;if (..==..) + FLUSH_BLOCK edi, 1 + mov eax,finish_done + jmp .end_f + @@: + cmp dword[edi+deflate_state.last_lit],0 + je @f ;if (..) + FLUSH_BLOCK edi, 0 + @@: + mov eax,block_done +.end_f: + ret +endp diff --git a/programs/fs/kfar/trunk/zlib/deflate.inc b/programs/fs/kfar/trunk/zlib/deflate.inc new file mode 100644 index 0000000000..77454f289f --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/deflate.inc @@ -0,0 +1,353 @@ +; deflate.inc -- internal compression state +; Copyright (C) 1995-2012 Jean-loup Gailly +; For conditions of distribution and use, see copyright notice in zlib.inc + +; WARNING: this file should *not* be used by applications. It is +; part of the implementation of the compression library and is +; subject to change. Applications should only use zlib.inc. + +include 'zutil.inc' + +; =========================================================================== +; Internal compression state. + + +LENGTH_CODES equ 29 +; number of length codes, not counting the special END_BLOCK code + +LITERALS equ 256 +; number of literal bytes 0..255 + +L_CODES equ (LITERALS+1+LENGTH_CODES) +; number of Literal or Length codes, including the END_BLOCK code + +D_CODES equ 30 +; number of distance codes + +BL_CODES equ 19 +; number of codes used to transfer the bit lengths + +HEAP_SIZE equ (2*L_CODES+1) +; maximum heap size + +MAX_BITS equ 15 +; All codes must not exceed MAX_BITS bits + +Buf_size equ 16 +; size of bit buffer in bi_buf + +INIT_STATE equ 42 +EXTRA_STATE equ 69 +NAME_STATE equ 73 +COMMENT_STATE equ 91 +HCRC_STATE equ 103 +BUSY_STATE equ 113 +FINISH_STATE equ 800 +; Stream status + +; Data structure describing a single value and its code string. +struct ct_data ;ct_data_s + fc dw ? ;union + ;uint_16 freq ;frequency count + ;uint_16 code ;bit string + dale dw ? ;union + ;uint_16 dad ;father node in Huffman tree + ;uint_16 len ;length of bit string +ends + +Freq equ ct_data.fc ;.freq +Code equ ct_data.fc ;.code +Dad equ ct_data.dale ;.dad +Len equ ct_data.dale ;.len + +struct tree_desc ;tree_desc_s + dyn_tree dd ? ;ct_data * ;the dynamic tree + max_code dd ? ;int ;largest code with non zero frequency + stat_desc dd ? ;static_tree_desc * ;the corresponding static tree +ends + +; A Pos is an index in the character window. We use short instead of int to +; save space in the various tables. IPos is used only for parameter passing. + +struct deflate_state ;internal_state + strm dd ? ;z_streamp ;pointer back to this zlib stream + status dd ? ;int ;as the name implies + pending_buf dd ? ;Bytef *;output still pending + pending_buf_size dd ? ;ulg ;size of pending_buf + pending_out dd ? ;Bytef * ;next pending byte to output to the stream + pending dw ? ;uInt ;nb of bytes in the pending buffer + wrap dd ? ;int ;bit 0 true for zlib, bit 1 true for gzip + gzhead dd ? ;gz_headerp ;gzip header information to write + gzindex dd ? ;uInt ;where in extra, name, or comment + method db ? ;Byte ;can only be DEFLATED + last_flush dd ? ;int ;value of flush param for previous deflate call + +; used by deflate.asm: + + w_size dd ? ;uInt ;LZ77 window size (32K by default) + w_bits dd ? ;uInt ;log2(w_size) (8..16) + w_mask dd ? ;uInt ;w_size - 1 + + window dd ? ;Bytef * + ; Sliding window. Input bytes are read into the second half of the window, + ; and move to the first half later to keep a dictionary of at least wSize + ; bytes. With this organization, matches are limited to a distance of + ; wSize-MAX_MATCH bytes, but this ensures that IO is always + ; performed with a length multiple of the block size. Also, it limits + ; the window size to 64K, which is quite useful on MSDOS. + ; To do: use the user input buffer as sliding window. + + window_size dd ? ;ulg + ; Actual size of window: 2*wSize, except when the user input buffer + ; is directly used as sliding window. + + prev dd ? ;Posf * + ; Link to older string with same hash index. To limit the size of this + ; array to 64K, this link is maintained only for the last 32K strings. + ; An index in this array is thus a window index modulo 32K. + + head dd ? ;Posf * ;Heads of the hash chains or NIL. + + ins_h dd ? ;uInt ;hash index of string to be inserted + hash_size dd ? ;uInt ;number of elements in hash table + hash_bits dd ? ;uInt ;log2(hash_size) + hash_mask dd ? ;uInt ;hash_size-1 + + hash_shift dd ? ;uInt + ; Number of bits by which ins_h must be shifted at each input + ; step. It must be such that after MIN_MATCH steps, the oldest + ; byte no longer takes part in the hash key, that is: + ; hash_shift * MIN_MATCH >= hash_bits + + block_start dd ? ;long + ; Window position at the beginning of the current output block. Gets + ; negative when the window is moved backwards. + + match_length dd ? ;uInt ;length of best match + prev_match dd ? ;IPos ;previous match + match_available dd ? ;int ;set if previous match exists + strstart dd ? ;uInt ;start of string to insert + match_start dd ? ;uInt ;start of matching string + lookahead dd ? ;uInt ;number of valid bytes ahead in window + + prev_length dd ? ;uInt + ; Length of the best match at previous step. Matches not greater than this + ; are discarded. This is used in the lazy match evaluation. + + max_chain_length dd ? ;uInt + ; To speed up deflation, hash chains are never searched beyond this + ; length. A higher limit improves compression ratio but degrades the + ; speed. + + max_lazy_match dd ? ;uInt + ; Attempt to find a better match only when the current match is strictly + ; smaller than this value. This mechanism is used only for compression + ; levels >= 4. + +;# define max_insert_length max_lazy_match + ; Insert new strings in the hash table only if the match length is not + ; greater than this length. This saves time but degrades compression. + ; max_insert_length is used only for compression levels <= 3. + + level dw ? ;int ;compression level (1..9) + strategy dw ? ;int ;favor or force Huffman coding + + good_match dd ? ;uInt + ; Use a faster search when the previous match is longer than this + + nice_match dd ? ;int ;Stop searching when current match exceeds this + +; used by trees.asm: + ; Didn't use ct_data typedef below to suppress compiler warning + dyn_ltree rb sizeof.ct_data * HEAP_SIZE ;literal and length tree + dyn_dtree rb sizeof.ct_data * (2*D_CODES+1) ;distance tree + bl_tree rb sizeof.ct_data * (2*BL_CODES+1) ;Huffman tree for bit lengths + + l_desc tree_desc ;desc. for literal tree + d_desc tree_desc ;desc. for distance tree + bl_desc tree_desc ;desc. for bit length tree + + bl_count rw MAX_BITS+1 ;uint_16[] + ; number of codes at each bit length for an optimal tree + + heap rw 2*L_CODES+1 ;int[] ;heap used to build the Huffman trees + heap_len dd ? ;int ;number of elements in the heap + heap_max dd ? ;int ;element of largest frequency + ; The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + ; The same heap array is used to build all trees. + + depth rb 2*L_CODES+1 ;uch[] + ; Depth of each subtree used as tie breaker for trees of equal frequency + + l_buf dd ? ;uchf * ;buffer for literals or lengths + + lit_bufsize dd ? ;uInt + ; Size of match buffer for literals/lengths. There are 4 reasons for + ; limiting lit_bufsize to 64K: + ; - frequencies can be kept in 16 bit counters + ; - if compression is not successful for the first block, all input + ; data is still in the window so we can still emit a stored block even + ; when input comes from standard input. (This can also be done for + ; all blocks if lit_bufsize is not greater than 32K.) + ; - if compression is not successful for a file smaller than 64K, we can + ; even emit a stored file instead of a stored block (saving 5 bytes). + ; This is applicable only for zip (not gzip or zlib). + ; - creating new Huffman trees less frequently may not provide fast + ; adaptation to changes in the input data statistics. (Take for + ; example a binary file with poorly compressible code followed by + ; a highly compressible string table.) Smaller buffer sizes give + ; fast adaptation but have of course the overhead of transmitting + ; trees more frequently. + ; - I can't count above 4 + + last_lit dd ? ;uInt ;running index in l_buf + + d_buf dd ? ;uint_16p + ; Buffer for distances. To simplify the code, d_buf and l_buf have + ; the same number of elements. To use different lengths, an extra flag + ; array would be necessary. + + opt_len dd ? ;ulg ;bit length of current block with optimal trees + static_len dd ? ;ulg ;bit length of current block with static trees + matches dd ? ;uInt ;number of string matches in current block + insert dd ? ;uInt ;bytes at end of window left to insert + +if DEBUG eq 1 + compressed_len dd ? ;ulg ;total bit length of compressed file mod 2^32 + bits_sent dd ? ;ulg ;bit length of compressed data sent mod 2^32 +end if + + bi_buf dw ? ;uint_16 + ; Output buffer. bits are inserted starting at the bottom (least + ; significant bits). + + bi_valid dd ? ;int + ; Number of valid bits in bi_buf. All bits above the last valid bit + ; are always zero. + + high_water dd ? ;ulg + ; High water mark offset in window for initialized bytes -- bytes above + ; this are set to zero in order to avoid memory check warnings when + ; longest match routines access bytes past the input. This is then + ; updated to the new high water mark. +ends + +; Output a byte on the stream. +; IN assertion: there is enough room in pending_buf. + +macro put_byte s, c +{ +;xor eax,eax +;mov al,c +;zlib_debug '(%d)',eax + movzx eax,word[s+deflate_state.pending] + add eax,[s+deflate_state.pending_buf] + mov byte[eax],c + inc word[s+deflate_state.pending] +} +macro put_dword s, d +{ +;mov eax,d +;zlib_debug '(%d)',eax + movzx eax,word[s+deflate_state.pending] + add eax,[s+deflate_state.pending_buf] + mov dword[eax],d + add word[s+deflate_state.pending],4 +} + +MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) +; Minimum amount of lookahead, except at the end of the input file. +; See deflate.asm for comments about the MIN_MATCH+1. + +macro MAX_DIST s +{ + mov eax,[s+deflate_state.w_size] + sub eax,MIN_LOOKAHEAD +} +; In order to simplify the code, particularly on 16 bit machines, match +; distances are limited to MAX_DIST instead of WSIZE. + +WIN_INIT equ MAX_MATCH +; Number of bytes after end of data in window to initialize in order to avoid +; memory checker errors from longest match routines + +macro d_code dist +{ +;if (dist < 256) _dist_code[dist] +;else _dist_code[ 256+(dist>>7) ] +local .end0 + mov eax,dist + cmp eax,256 + jl .end0 + shr eax,7 + add eax,256 + .end0: + movzx eax,byte[eax+_dist_code] +} +; Mapping from a distance to a distance code. dist is the distance - 1 and +; must not have side effects. _dist_code[256] and _dist_code[257] are never +; used. + +macro _tr_tally_lit s, c, flush +{ +local .end0 +if DEBUG eq 0 +; Inline versions of _tr_tally for speed: +if c eq eax +else + mov eax,c +end if + push ecx + mov ecx,[s+deflate_state.last_lit] + shl ecx,1 + add ecx,[s+deflate_state.d_buf] + mov word[ecx],0 + mov ecx,[s+deflate_state.last_lit] + add ecx,[s+deflate_state.l_buf] + mov byte[ecx],al + inc dword[s+deflate_state.last_lit] + and eax,0xff + imul eax,sizeof.ct_data + add eax,s + inc word[eax+deflate_state.dyn_ltree+Freq] + xor eax,eax + mov ecx,[s+deflate_state.lit_bufsize] + dec ecx + cmp [s+deflate_state.last_lit],ecx + jne .end0 + inc eax ;flush = (..==..) + .end0: + mov flush, eax + pop ecx +else + stdcall _tr_tally, s, 0, c + mov flush, eax +end if +} +macro _tr_tally_dist s, distance, length, flush +{ +if 0 ;;;DEBUG eq 0 + push ecx +; uch len = (length) +if distance eq eax +else + mov eax,distance +end if + mov ecx,[s+deflate_state.last_lit] + shl ecx,1 + add ecx,[s+deflate_state.d_buf] + mov word[ecx],ax + mov ecx,[s+deflate_state.last_lit] + add ecx,[s+deflate_state.l_buf] + mov byte[ecx],length + inc dword[s+deflate_state.last_lit] + dec eax +; s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; +; s->dyn_dtree[d_code(dist)].Freq++; +; flush = (s->last_lit == s->lit_bufsize-1); + pop ecx +else + stdcall _tr_tally, s, distance, length + mov flush, eax +end if +} diff --git a/programs/fs/kfar/trunk/zlib/example1.asm b/programs/fs/kfar/trunk/zlib/example1.asm new file mode 100644 index 0000000000..954e366fce --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/example1.asm @@ -0,0 +1,287 @@ +use32 ; 32- ० ᥬ +org 0x0 ; + db 'MENUET01' + dd 1,START,I_END,MEM,STACKTOP,0,cur_dir_path + +include '../../../../proc32.inc' +include '../../../../macros.inc' +include '../../../../KOSfuncs.inc' +include '../../../../develop/libraries/box_lib/load_lib.mac' + +include 'deflate.inc' +include 'debug.inc' +include 'zlib.inc' + +@use_library + +align 4 +m0size dd 90 ;ࠧ 㯠 +m1size dd 1024 ;ࠧ 㯠 +m2size dd 0 ;ࠧ ᯠ + +align 4 +m0: ; 㯠 +file 'zlib.txt' + +align 4 +m1 rb 1024 ; 㯠 +m2 dd 0 ;㪠⥫ ᯠ + +buf rb 1024 ; 뢮 ᦠ +strategy dd Z_DEFAULT_STRATEGY ;⥣ ᦠ + +align 4 +START: +load_libraries l_libs_start,load_lib_end +mov ebp,lib0 +.test_lib_open: + cmp dword [ebp+ll_struc_size-4],0 + jz @f + mcall SF_TERMINATE_PROCESS ;exit not correct +@@: + add ebp,ll_struc_size + cmp ebp,load_lib_end + jl .test_lib_open + +; mcall SF_SYS_MISC, SSF_HEAP_INIT + + call test_code + +align 4 +red: ; ᮢ + call draw_window ; 뢠 楤 ᮢ + +align 4 +still: + mcall SF_WAIT_EVENT + cmp eax,1 ; ᮢ ? + je red + cmp eax,2 ; ? + je key + cmp eax,3 ; ? + je button + jmp still + +align 4 +key: + mcall SF_GET_KEY + + cmp ah,178 ;Up + jne @f + cmp dword[strategy],0 + jle @f + dec dword[strategy] + call test_code + call draw_window + @@: + cmp ah,177 ;Down + jne @f + cmp dword[strategy],4 + jge @f + inc dword[strategy] + call test_code + call draw_window + @@: + cmp ah,176 ;Left + jne @f + cmp dword[m0size],8 + jl @f + dec dword[m0size] + call test_code + call draw_window + @@: + cmp ah,179 ;Right + jne @f + inc dword[m0size] + call test_code + call draw_window + @@: + jmp still ; 砫 横 + +;--------------------------------------------------------------------- +align 4 +button: + mcall SF_GET_BUTTON + + cmp ah,1 + jne still + +.exit: + mcall SF_SYS_MISC,SSF_MEM_FREE,[m2] + mcall SF_TERMINATE_PROCESS ; ணࠬ + +align 4 +draw_window: + mcall SF_REDRAW, SSF_BEGIN_DRAW ; 㭪 12: ᮮ 砫 ᮢ + mcall SF_STYLE_SETTINGS, SSF_GET_COLORS, sc,sizeof.system_colors + mov edx, [sc.work] ; 梥 䮭 + or edx, 0x33000000 ; ⨯ 3 + mcall SF_CREATE_WINDOW, <50,600>, <50,180>, , ,title + + cStr edx,'Strategy:' + mcall SF_DRAW_TEXT, <10,10>,0x40f0,,9 + cStr edx,'Input size:' + mcall , <10,20>,,,11 + cStr edx,'Compr. size:' + mcall , <10,30>,,,12 + cStr edx,'Outp. size:' + mcall , <10,120>,,,11 + + mcall SF_DRAW_NUMBER, (1 shl 16)+1, strategy, <90,10>, 0 + mcall , (5 shl 16)+1, m0size, <90,20> + mcall , (5 shl 16)+1, m1size, <90,30> + mcall , (5 shl 16)+1, m2size, <90,120> + ;mov ecx,(1 shl 31) + mov esi,[m2size] + cmp esi,95 + jle @f + mov esi,95 + @@: + mcall SF_DRAW_TEXT, <10,130>, 0, [m2] + + mov esi,7 + mov ebx,(10 shl 16)+45 ;(x shl 16)+y + mov edx,buf + .cycle1: ;rows + mcall SF_DRAW_TEXT,, (1 shl 31) + add ebx,10 + add edx,32*3 + dec esi + jnz .cycle1 + + mcall SF_REDRAW, SSF_END_DRAW ; 㭪 12.2, 稫 ᮢ + ret + +align 4 +test_code: + stdcall [deflateInit2], my_strm,\ + -1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, [strategy] +;⥣: +; Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED + + mov eax,my_strm + mov [eax+z_stream.next_in],m0 ;⠭ ᦠ + mov ecx,[m0size] + mov word[eax+z_stream.avail_in],cx ;ࠧ ᦨ + mov [eax+z_stream.next_out],m1 ;⠭ ᦠ + mov word[eax+z_stream.avail_out],1024 ;ࠧ ᦠ + + ;call print_z_struct + + stdcall [deflate], my_strm, Z_FINISH ;Z_NO_FLUSH + + ;call print_z_struct + + ;ࠧ ᦠ : 1024-word[eax+z_stream.avail_out] + mov eax,my_strm + mov ecx,1024 + sub cx,word[eax+z_stream.avail_out] + mov [m1size],ecx + +;assert(ret != Z_STREAM_ERROR) +;while (strm.avail_out == 0) + + mov ebx,[m1size] + mov esi,m1 + mov edi,buf + mov edx,7 + .cycle1: ;rows + mov ecx,32 + .cycle0: ;cols + stdcall hex_in_str, edi,[esi],2 + add edi,2 + inc esi + mov byte[edi],' ' ;format space + dec ebx + jz .cycle1end ;if end file + inc edi + loop .cycle0 + mov byte[edi-1],0 + dec edx + jnz .cycle1 + + .cycle1end: + mov byte[edi],0 + + mcall SF_SYS_MISC,SSF_MEM_FREE,[m2] + + mov eax,[m1size] + sub eax,2 ;;; 2? or 6? + mov [m2size],eax + mov eax,m1 + add eax,2 + stdcall [deflate_unpack],eax,m2size + mov [m2],eax + mov ecx,[m0size] ;;; ??? + mov [m2size],ecx + ret + +align 4 +proc print_z_struct uses eax ebx + mov eax,my_strm + mov ebx,[eax+z_stream.state] + stdcall debug_fields,eax,sv_2 + stdcall debug_fields,ebx,sv_3 + ret +endp + +sc system_colors + +title db 'Zlib test, press on [Up], [Down], [Left], [Right]',0 + +align 4 +import_archiver: + deflate_unpack dd sz_deflate_unpack + dd 0,0 + sz_deflate_unpack db 'deflate_unpack',0 + +align 4 +import_zlib: +; dd sz_lib_init + deflateInit dd sz_deflateInit + deflateInit2 dd sz_deflateInit2 + deflateReset dd sz_deflateReset + deflate dd sz_deflate + deflateEnd dd sz_deflateEnd + + dd 0,0 + +; sz_lib_init db 'lib_init',0 + sz_deflateInit db 'deflateInit',0 + sz_deflateInit2 db 'deflateInit2',0 + sz_deflateReset db 'deflateReset',0 + sz_deflate db 'deflate',0 + sz_deflateEnd db 'deflateEnd',0 +;-------------------------------------------------- +system_dir_0 db '/sys/lib/' +lib_name_0 db 'archiver.obj',0 + +system_dir_1 db '/sys/lib/' +lib_name_1 db 'zlib.obj',0 + +err_message_found_lib0 db 'Sorry I cannot load library archiver.obj',0 +err_message_found_lib1 db 'Sorry I cannot load library zlib.obj',0 +head_f_i: +head_f_l db 'System error',0 +err_message_import0 db 'Error on load import library archiver.obj',0 +err_message_import1 db 'Error on load import library zlib.obj',0 + +l_libs_start: + lib0 l_libs lib_name_0, cur_dir_path, library_path, system_dir_0,\ + err_message_found_lib0, head_f_l, import_archiver,err_message_import0, head_f_i + lib1 l_libs lib_name_1, cur_dir_path, library_path, system_dir_1,\ + err_message_found_lib1, head_f_l, import_zlib, err_message_import1, head_f_i +load_lib_end: +;--------------------------------------------------------------------- + +align 16 +I_END: +my_strm z_stream + rd 4096 +align 16 +STACKTOP: +cur_dir_path: + rb 4096 +library_path: + rb 4096 +MEM: diff --git a/programs/fs/kfar/trunk/zlib/trees.asm b/programs/fs/kfar/trunk/zlib/trees.asm new file mode 100644 index 0000000000..07d4d2e1bb --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/trees.asm @@ -0,0 +1,2096 @@ +; trees.asm -- output deflated data using Huffman coding +; Copyright (C) 1995-2012 Jean-loup Gailly +; detect_data_type() function provided freely by Cosmin Truta, 2006 +; For conditions of distribution and use, see copyright notice in zlib.h + +; ALGORITHM + +; The "deflation" process uses several Huffman trees. The more +; common source values are represented by shorter bit sequences. + +; Each code tree is stored in a compressed form which is itself +; a Huffman encoding of the lengths of all the code strings (in +; ascending order by source values). The actual code strings are +; reconstructed from the lengths in the inflate process, as described +; in the deflate specification. + +; REFERENCES + +; Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". +; Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + +; Storer, James A. +; Data Compression: Methods and Theory, pp. 49-50. +; Computer Science Press, 1988. ISBN 0-7167-8156-5. + +; Sedgewick, R. +; Algorithms, p290. +; Addison-Wesley, 1983. ISBN 0-201-06672-6. + +; =========================================================================== +; Constants + + +MAX_BL_BITS equ 7 +; Bit length codes must not exceed MAX_BL_BITS bits + +END_BLOCK equ 256 +; end of block literal code + +REP_3_6 equ 16 +; repeat previous bit length 3-6 times (2 bits of repeat count) + +REPZ_3_10 equ 17 +; repeat a zero length 3-10 times (3 bits of repeat count) + +REPZ_11_138 equ 18 +; repeat a zero length 11-138 times (7 bits of repeat count) + +align 4 +extra_lbits dd \ ;int [LENGTH_CODES] ;extra bits for each length code + 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 + +align 4 +extra_dbits dd \ ;int [D_CODES] ;extra bits for each distance code + 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 + +align 4 +extra_blbits dd \ ;int [BL_CODES] ;extra bits for each bit length code + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 + +align 4 +bl_order db 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 +; The lengths of the bit length codes are sent in order of decreasing +; probability, to avoid transmitting the lengths for unused bit length codes. + + +; =========================================================================== +; Local data. These are initialized only once. + + +DIST_CODE_LEN equ 512 ;see definition of array dist_code below + +if GEN_TREES_H eq 1 ;| !(STDC) +; non ANSI compilers may not accept trees.inc + +align 4 +static_ltree rb sizeof.ct_data * (L_CODES+2) +; The static literal tree. Since the bit lengths are imposed, there is no +; need for the L_CODES extra codes used during heap construction. However +; The codes 286 and 287 are needed to build a canonical tree (see _tr_init +; below). + +align 4 +static_dtree rb sizeof.ct_data * D_CODES +; The static distance tree. (Actually a trivial tree since all codes use +; 5 bits.) + +align 4 +_dist_code rb DIST_CODE_LEN ;uch[] +; Distance codes. The first 256 values correspond to the distances +; 3 .. 258, the last 256 values correspond to the top 8 bits of +; the 15 bit distances. + +align 4 +_length_code rb MAX_MATCH-MIN_MATCH+1 ;uch[] +; length code for each normalized match length (0 == MIN_MATCH) + +align 4 +base_length rd LENGTH_CODES ;int[] +; First normalized length for each code (0 = MIN_MATCH) + +align 4 +base_dist rd D_CODES ;int[] +; First normalized distance for each code (0 = distance of 1) + +else +include 'trees.inc' +end if ;GEN_TREES_H + +struct static_tree_desc ;_s + static_tree dd ? ;const ct_data * ;static tree or NULL + extra_bits dd ? ;const intf * ;extra bits for each code or NULL + extra_base dd ? ;int ;base index for extra_bits + elems dd ? ;int ;max number of elements in the tree + max_length dd ? ;int ;max bit length for the codes +ends + +align 4 +static_l_desc static_tree_desc static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS + +align 4 +static_d_desc static_tree_desc static_dtree, extra_dbits, 0, D_CODES, MAX_BITS + +align 4 +static_bl_desc static_tree_desc 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS + +; =========================================================================== +; Local (static) routines in this file. + + +macro send_code s, c, tree +{ +if DEBUG eq 1 +; if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)) +end if +push eax ebx +if c eq eax +else + mov eax,c +end if + imul eax,sizeof.ct_data + add eax,tree + movzx ebx,word[eax+Len] + push ebx + movzx ebx,word[eax+Code] + push ebx + stdcall send_bits, s ;tree[c].Code, tree[c].Len +pop ebx eax +} +; Send a code of the given tree[c] and tree must not have side effects + +; =========================================================================== +; Output a short LSB first on the stream. +; IN assertion: there is enough room in pendingBuf. + +macro put_short s, w +{ + movzx eax,word[s+deflate_state.pending] + add eax,[s+deflate_state.pending_buf] + mov word[eax],w + add word[s+deflate_state.pending],2 +} + +; =========================================================================== +; Send a value on a given number of bits. +; IN assertion: length <= 16 and value fits in length bits. + +;void (s, value, length) +; deflate_state* s +; int value ;value to send +; int length ;number of bits +align 4 +proc send_bits uses eax ecx edi, s:dword, value:dword, length:dword +; Tracevv((stderr," l %2d v %4x ", length, value)); +;zlib_debug 'send_bits value = %d',[value] +;if DEBUG eq 1 + mov eax,[length] + cmp eax,0 + jle @f + cmp eax,15 + jle .end1 + @@: + zlib_debug 'invalid length' ;Assert(..>0 && ..<=15) + .end1: + mov edi,[s] + add [edi+deflate_state.bits_sent],eax + + ; If not enough room in bi_buf, use (valid) bits from bi_buf and + ; (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + ; unused bits in value. + + mov ecx,Buf_size + sub ecx,eax + cmp [edi+deflate_state.bi_valid],ecx + jle @f ;if (..>..) + mov eax,[value] + mov ecx,[edi+deflate_state.bi_valid] + shl eax,cl + or [edi+deflate_state.bi_buf],ax + mov cx,[edi+deflate_state.bi_buf] + put_short edi, cx + mov eax,[value] + mov ecx,Buf_size + sub ecx,[edi+deflate_state.bi_valid] + shr eax,cl + mov [edi+deflate_state.bi_buf],ax + mov eax,[length] + sub eax,Buf_size + jmp .end0 + @@: ;else + mov eax,[value] + mov ecx,[edi+deflate_state.bi_valid] + shl eax,cl + or [edi+deflate_state.bi_buf],ax + mov eax,[length] + .end0: + add [edi+deflate_state.bi_valid],eax +;else ;!DEBUG + +;{ int len = length; +; if (s->bi_valid > (int)Buf_size - len) { +; int val = value; +; s->bi_buf |= (uint_16)val << s->bi_valid; +; put_short(s, s->bi_buf); +; s->bi_buf = (uint_16)val >> (Buf_size - s->bi_valid); +; s->bi_valid += len - Buf_size; +; } else { +; s->bi_buf |= (uint_16)(value) << s->bi_valid; +; s->bi_valid += len; +; } +;} +;end if ;DEBUG + ret +endp + +; the arguments must not have side effects + +; =========================================================================== +; Initialize the various 'constant' tables. + +;int static_init_done = 0 + +;void () +align 4 +proc tr_static_init +if GEN_TREES_H eq 1 + +; int n ;iterates over tree elements +; int bits ;bit counter +; int length ;length value +; int code ;code value +; int dist ;distance index +; uint_16 bl_count[MAX_BITS+1]; + ; number of codes at each bit length for an optimal tree + +; if (static_init_done) return; + + ; For some embedded targets, global variables are not initialized: +;if NO_INIT_GLOBAL_POINTERS +; static_l_desc.static_tree = static_ltree; +; static_l_desc.extra_bits = extra_lbits; +; static_d_desc.static_tree = static_dtree; +; static_d_desc.extra_bits = extra_dbits; +; static_bl_desc.extra_bits = extra_blbits; +;end if + + ; Initialize the mapping length (0..255) -> length code (0..28) +; length = 0; +; for (code = 0; code < LENGTH_CODES-1; code++) { +; base_length[code] = length; +; for (n = 0; n < (1< dist code (0..29) +; dist = 0; +; for (code = 0 ; code < 16; code++) { +; base_dist[code] = dist; +; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ +; for ( ; code < D_CODES; code++) { +; base_dist[code] = dist << 7; +; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { +; _dist_code[256 + dist++] = (uch)code; +; } +; } +; Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + ; Construct the codes of the static literal tree +; for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; +; n = 0; +; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; +; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; +; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; +; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + ; Codes 286 and 287 do not exist, but we must include them in the + ; tree construction to get a canonical Huffman tree (longest code + ; all ones) + +; gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + ; The static distance tree is trivial: +; for (n = 0; n < D_CODES; n++) { +; static_dtree[n].Len = 5; +; static_dtree[n].Code = bi_reverse((unsigned)n, 5); +; } +; static_init_done = 1; + +if GEN_TREES_H eq 1 + call gen_trees_header +end if +end if ;(GEN_TREES_H) | !(STDC) + ret +endp + +; =========================================================================== +; Genererate the file trees.h describing the static trees. + +;# define SEPARATOR(i, last, width) \ +; ((i) == (last)? "\n};\n\n" : \ +; ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +;void () +align 4 +proc gen_trees_header +; FILE *header = fopen("trees.inc", "w"); +; int i; + +; Assert (header != NULL, "Can't open trees.inc"); +; fprintf(header, +; "/* header created automatically with -DGEN_TREES_H */\n\n"); + +; fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); +; for (i = 0; i < L_CODES+2; i++) { +; fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, +; static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); +; } + +; fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); +; for (i = 0; i < D_CODES; i++) { +; fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, +; static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); +; } + +; fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); +; for (i = 0; i < DIST_CODE_LEN; i++) { +; fprintf(header, "%2u%s", _dist_code[i], +; SEPARATOR(i, DIST_CODE_LEN-1, 20)); +; } + +; fprintf(header, +; "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); +; for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { +; fprintf(header, "%2u%s", _length_code[i], +; SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); +; } + +; fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); +; for (i = 0; i < LENGTH_CODES; i++) { +; fprintf(header, "%1u%s", base_length[i], +; SEPARATOR(i, LENGTH_CODES-1, 20)); +; } + +; fprintf(header, "local const int base_dist[D_CODES] = {\n"); +; for (i = 0; i < D_CODES; i++) { +; fprintf(header, "%5u%s", base_dist[i], +; SEPARATOR(i, D_CODES-1, 10)); +; } + +; fclose(header); + ret +endp + +; =========================================================================== +; Initialize the tree data structures for a new zlib stream. + +;void (s) +; deflate_state* s; +align 4 +proc _tr_init uses eax edi, s:dword + mov edi,[s] +;zlib_debug '_tr_init' + call tr_static_init + + mov eax,edi + add eax,deflate_state.dyn_ltree + mov [edi+deflate_state.l_desc.dyn_tree],eax + mov [edi+deflate_state.l_desc.stat_desc],static_l_desc + + add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree + mov [edi+deflate_state.d_desc.dyn_tree],eax + mov [edi+deflate_state.d_desc.stat_desc],static_d_desc + + add eax,deflate_state.bl_tree-deflate_state.dyn_dtree + mov [edi+deflate_state.bl_desc.dyn_tree],eax + mov [edi+deflate_state.bl_desc.stat_desc],static_bl_desc; + + mov word[edi+deflate_state.bi_buf],0 + mov dword[edi+deflate_state.bi_valid],0 +if DEBUG eq 1 + mov dword[edi+deflate_state.compressed_len],0 + mov dword[edi+deflate_state.bits_sent],0 +end if + + ; Initialize the first block of the first file: + stdcall init_block,edi + ret +endp + +; =========================================================================== +; Initialize a new block. + +;void (s) +; deflate_state* s +align 4 +proc init_block uses eax ecx edi, s:dword +; int n ;iterates over tree elements + mov edi,[s] + + ; Initialize the trees. + mov eax,edi + add eax,deflate_state.dyn_ltree+Freq + mov ecx,L_CODES + @@: + mov word[eax],0 + add eax,sizeof.ct_data + loop @b + mov eax,edi + add eax,deflate_state.dyn_dtree+Freq + mov ecx,D_CODES + @@: + mov word[eax],0 + add eax,sizeof.ct_data + loop @b + mov eax,edi + add eax,deflate_state.bl_tree+Freq + mov ecx,BL_CODES + @@: + mov word[eax],0 + add eax,sizeof.ct_data + loop @b + + mov ecx,sizeof.ct_data*END_BLOCK+deflate_state.dyn_ltree+Freq + mov word[ecx+edi],1 + mov dword[edi+deflate_state.static_len],0 + mov dword[edi+deflate_state.opt_len],0 + mov dword[edi+deflate_state.matches],0 + mov dword[edi+deflate_state.last_lit],0 + ret +endp + +SMALLEST equ 1 +; Index within the heap array of least frequent node in the Huffman tree + + +; =========================================================================== +; Remove the smallest element from the heap and recreate the heap with +; one less element. Updates heap and heap_len. + +macro pqremove s, tree, top +{ + mov eax,s + add eax,deflate_state.heap+2*SMALLEST + movzx top,word[eax] +push ebx + mov ebx,[s+deflate_state.heap_len] + mov bx,[s+deflate_state.heap+2*ebx] + mov word[eax],bx + dec dword[s+deflate_state.heap_len] +pop ebx + stdcall pqdownheap, s, tree, SMALLEST +} + +; =========================================================================== +; Compares to subtrees, using the tree depth as tie breaker when +; the subtrees have equal frequency. This minimizes the worst case length. + +macro smaller tree, n, m, depth, m_end +{ +;if (..<.. || (..==.. && depth[n] <= depth[m])) +local .end0 + movzx eax,n + imul eax,sizeof.ct_data + add eax,tree + mov ax,word[eax+Freq] + movzx ebx,m + imul ebx,sizeof.ct_data + add ebx,tree + mov bx,word[ebx+Freq] + cmp ax,bx + jl .end0 + jne m_end + movzx eax,n + add eax,depth + mov al,byte[eax] + movzx ebx,m + add ebx,depth + mov bl,byte[ebx] + cmp al,bl + jg m_end + .end0: +} + +; =========================================================================== +; Restore the heap property by moving down the tree starting at node k, +; exchanging a node with the smallest of its two sons if necessary, stopping +; when the heap property is re-established (each father smaller than its +; two sons). + +;void (s, tree, k) +; deflate_state* s +; ct_data* tree ;the tree to restore +; int k ;node to move down +align 4 +proc pqdownheap, s:dword, tree:dword, k:dword +locals + v dw ? +endl +pushad + mov edi,[s] + mov eax,[k] +;zlib_debug 'pqdownheap k = %d',eax + mov esi,eax + shl esi,1 + mov ax,[edi+deflate_state.heap+2*eax] + mov [v],ax + ;esi = j ;left son of k + .cycle0: ;while (..<=..) + cmp esi,[edi+deflate_state.heap_len] + jg .cycle0end + ; Set j to the smallest of the two sons: + ;;cmp esi,[edi+deflate_state.heap_len] + jge .end1 ;if (..<.. && + mov ecx,edi + add ecx,deflate_state.depth + mov edx,esi + shl edx,1 + add edx,edi + add edx,deflate_state.heap + smaller [tree], word[edx+2], word[edx], ecx, .end1 + inc esi + .end1: + ; Exit if v is smaller than both sons + mov ecx,edi + add ecx,deflate_state.depth + mov dx,[edi+deflate_state.heap+2*esi] + smaller [tree], [v], dx, ecx, .end2 + jmp .cycle0end ;break + .end2: + ; Exchange v with the smallest son + mov dx,[edi+deflate_state.heap+2*esi] + mov eax,[k] + mov [edi+deflate_state.heap+2*eax],dx + mov [k],esi + ; And continue down the tree, setting j to the left son of k + shl esi,1 + jmp .cycle0 + .cycle0end: + mov eax,[k] + mov bx,[v] + mov [edi+deflate_state.heap+2*eax],bx +popad + ret +endp + +; =========================================================================== +; Compute the optimal bit lengths for a tree and update the total bit length +; for the current block. +; IN assertion: the fields freq and dad are set, heap[heap_max] and +; above are the tree nodes sorted by increasing frequency. +; OUT assertions: the field len is set to the optimal bit length, the +; array bl_count contains the frequencies for each bit length. +; The length opt_len is updated; static_len is also updated if stree is +; not null. + +;void (s, desc) +; deflate_state* s +; tree_desc* desc ;the tree descriptor +align 4 +proc gen_bitlen, s:dword, desc:dword +locals + tree dd ? ;ct_data* ;= desc.dyn_tree + max_code dd ? ;int ;= desc.max_code + stree dd ? ;ct_data* ;= desc.stat_desc.static_tree + extra dd ? ;intf* ;= desc.stat_desc.extra_bits + base dd ? ;int ;= desc.stat_desc.extra_base + max_length dd ? ;int ;= desc.stat_desc.max_length + h dd ? ;int ;heap index + m dd ? ;int ;iterate over the tree elements + bits dd ? ;int ;bit length + xbits dd ? ;int ;extra bits + f dw ? ;uint_16 ;frequency + overflow dd 0 ;int ;number of elements with bit length too large +endl +pushad +;zlib_debug 'gen_bitlen' + mov edi,[s] + mov edx,[desc] + mov eax,[edx+tree_desc.dyn_tree] + mov [tree],eax + mov eax,[edx+tree_desc.max_code] + mov [max_code],eax + mov ebx,[edx+tree_desc.stat_desc] + mov eax,[ebx+static_tree_desc.static_tree] + mov [stree],eax + mov eax,[ebx+static_tree_desc.extra_bits] + mov [extra],eax + mov eax,[ebx+static_tree_desc.extra_base] + mov [base],eax + mov eax,[ebx+static_tree_desc.max_length] + mov [max_length],eax + + xor ecx,ecx + .cycle0: + cmp ecx,MAX_BITS + jg .cycle0end ;for (..;..<=..;..) + mov word[edi+deflate_state.bl_count+2*ecx],0 + inc ecx + jmp .cycle0 +align 4 + .cycle0end: + + ; In a first pass, compute the optimal bit lengths (which may + ; overflow in the case of the bit length tree). + + mov eax,[edi+deflate_state.heap_max] + movzx eax,word[edi+deflate_state.heap+2*eax] + imul eax,sizeof.ct_data + add eax,[tree] + mov word[eax+Len],0 ;root of the heap + + mov eax,[edi+deflate_state.heap_max] + inc eax + mov [h],eax + .cycle1: + cmp dword[h],HEAP_SIZE + jge .cycle1end ;for (..;..<..;..) + mov eax,[h] + movzx ecx,word[edi+deflate_state.heap+2*eax] + ;ecx = n + mov eax,sizeof.ct_data + imul eax,ecx + add eax,[tree] + movzx eax,word[eax+Dad] + imul eax,sizeof.ct_data + add eax,[tree] + movzx eax,word[eax+Len] + inc eax + mov [bits],eax ;bits = tree[tree[n].Dad].Len + 1 + mov eax,[max_length] + cmp [bits],eax + jle @f ;if (..>..) + mov [bits],eax + inc dword[overflow] + @@: + mov esi,[bits] + mov eax,sizeof.ct_data + imul eax,ecx + add eax,[tree] + mov word[eax+Len],si + ; We overwrite tree[n].Dad which is no longer needed + + cmp ecx,[max_code] + jle @f + inc dword[h] + jmp .cycle1 ;if (..>..) continue ;not a leaf node + @@: + + mov eax,[bits] + shl eax,1 ;*= sizeof.uint_16 + inc word[eax+edi+deflate_state.bl_count] + mov dword[xbits],0 + cmp ecx,[base] + jl @f ;if (..>=..) + mov eax,ecx + sub eax,[base] + shl eax,2 ;*= sizeof.dd + add eax,[extra] + mov eax,[eax] + mov [xbits],eax + @@: + mov eax,sizeof.ct_data + imul eax,ecx + add eax,[tree] + movzx eax,word[eax+Freq] + mov [f],ax + mov esi,[bits] + add esi,[xbits] + imul eax,esi + add [edi+deflate_state.opt_len],eax + cmp dword[stree],0 + je @f ;if (..) + movzx eax,word[f] + mov esi,sizeof.ct_data + imul esi,ecx + add esi,[tree] + movzx esi,word[esi+Len] + add esi,[xbits] + imul eax,esi + add [edi+deflate_state.static_len],eax + @@: + inc dword[h] + jmp .cycle1 +align 4 + .cycle1end: + cmp dword[overflow],0 + je .end_f ;if (..==0) return + +; Trace((stderr,"\nbit length overflow\n")); + ; This happens for example on obj2 and pic of the Calgary corpus + + ; Find the first bit length which could increase: + .cycle2: ;do + mov eax,[max_length] + dec eax + mov [bits],eax + shl eax,1 ;*= sizeof.dw + add eax,edi + add eax,deflate_state.bl_count + @@: + cmp word[eax],0 + jne @f ;while (..==0) bits-- + dec dword[bits] + sub eax,2 + jmp @b + @@: + dec word[eax] ;move one leaf down the tree + add word[eax+2],2 ;move one overflow item as its brother + mov eax,[max_length] + dec word[edi+deflate_state.bl_count+2*eax] + ; The brother of the overflow item also moves one step up, + ; but this does not affect bl_count[max_length] + + sub dword[overflow],2 + cmp dword[overflow],0 + jg .cycle2 ;while (..>0) + + ; Now recompute all bit lengths, scanning in increasing frequency. + ; h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + ; lengths instead of fixing only the wrong ones. This idea is taken + ; from 'ar' written by Haruhiko Okumura.) + + mov eax,[max_length] + mov [bits],eax + .cycle3: + cmp dword[bits],0 + je .end_f ;for (..;..!=0;..) + mov eax,[bits] + shl eax,1 ;*= sizeof.dw + movzx ecx,word[eax+edi+deflate_state.bl_count] + .cycle4: ;while (..!=0) + cmp ecx,0 + je .cycle4end + dec dword[h] + mov eax,[h] + movzx eax,word[edi+deflate_state.heap+2*eax] + mov [m],eax ;m = s.heap[--h] + cmp eax,[max_code] + jle @f ;if (..>..) continue + dec ecx + jmp .cycle4 + @@: + mov esi,[m] + imul esi,sizeof.ct_data + add esi,[tree] ;esi = &tree[m] + mov eax,[bits] + cmp word[esi+Len],ax + je @f ;if (..!=..) +; Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + movzx ebx,word[esi+Len] + sub eax,ebx + movzx ebx,word[esi+Freq] + imul eax,ebx ;eax = (bits - tree[m].Len) * tree[m].Freq + add [edi+deflate_state.opt_len],eax + mov eax,[bits] + mov word[esi+Len],ax + @@: + dec ecx + jmp .cycle4 + .cycle4end: + dec dword[bits] + jmp .cycle3 +.end_f: +popad + ret +endp + +; =========================================================================== +; Generate the codes for a given tree and bit counts (which need not be +; optimal). +; IN assertion: the array bl_count contains the bit length statistics for +; the given tree and the field len is set for all tree elements. +; OUT assertion: the field code is set for all tree elements of non +; zero code length. + +;void (tree, max_code, bl_count) +; ct_data *tree ;the tree to decorate +; int max_code ;largest code with non zero frequency +; uint_16p bl_count ;number of codes at each bit length +align 4 +proc gen_codes uses eax ebx ecx edx edi, tree:dword, max_code:dword, bl_count:dword +locals + u_code dw 0 ;uint_16 ;running code value + bits dd 1 ;int ;bit index + next_code rw MAX_BITS+1 ;uint_16[] ;next code value for each bit length +endl + ; The distribution counts are first used to generate the code values + ; without bit reversal. +;zlib_debug 'gen_codes' + mov ebx,ebp + sub ebx,2*(MAX_BITS+1) + + .cycle0: ;for (..;..<=..;..) + cmp dword[bits],MAX_BITS + jg .cycle0end + mov eax,[bits] + dec eax + shl eax,1 + add eax,[bl_count] + mov ax,word[eax] + add ax,[u_code] + shl ax,1 ;ax = (u_code + bl_count[bits-1]) << 1 + mov [u_code],ax + mov ecx,[bits] + mov word[ebx+2*ecx],ax ;next_code[bits] = u_code + inc dword[bits] + jmp .cycle0 + .cycle0end: + ; Check that the bit counts in bl_count are consistent. The last code + ; must be all ones. + + mov eax,[bl_count] + mov ax,word[eax+2*MAX_BITS] + add ax,[u_code] + dec ax + cmp ax,(1 shl MAX_BITS)-1 + je @f + zlib_debug 'inconsistent bit counts' ;Assert(..==..) + @@: +; Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + xor ecx,ecx ;n = 0 + .cycle1: ;for (..;..<=..;..) + cmp ecx,[max_code] + jg .cycle1end + mov edx,sizeof.ct_data + imul edx,ecx + add edx,[tree] ;edx = &tree[n] + movzx edi,word[edx+Len] + cmp edi,0 + jne @f ;if (..==0) continue + inc ecx + jmp .cycle1 + @@: + ; Now reverse the bits + movzx eax,word[ebx+2*edi] + stdcall bi_reverse, eax, edi + mov word[edx+Code],ax + inc word[ebx+2*edi] + +; Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", +; n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + inc ecx + jmp .cycle1 + .cycle1end: + ret +endp + +; =========================================================================== +; Construct one Huffman tree and assigns the code bit strings and lengths. +; Update the total bit length for the current block. +; IN assertion: the field freq is set for all tree elements. +; OUT assertions: the fields len and code are set to the optimal bit length +; and corresponding code. The length opt_len is updated; static_len is +; also updated if stree is not null. The field max_code is set. + +;void (s, desc) +; deflate_state* s +; tree_desc *desc ;the tree descriptor +align 4 +proc build_tree uses eax ebx ecx edx edi, s:dword, desc:dword +locals + tree dd ? ;ct_data* ;= desc.dyn_tree + stree dd ? ;ct_data* ;= desc.stat_desc.static_tree + elems dd ? ;int ;= desc.stat_desc.elems + m dd ? ;int ;iterate over heap elements + max_code dd -1 ;int ;largest code with non zero frequency + node dd ? ;int ;new node being created +endl + ; Construct the initial heap, with least frequent element in + ; heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + ; heap[0] is not used. + mov ebx,[desc] + mov eax,[ebx+tree_desc.dyn_tree] + mov [tree],eax + mov ecx,[ebx+tree_desc.stat_desc] + mov eax,[ecx+static_tree_desc.static_tree] + mov [stree],eax + mov ecx,[ecx+static_tree_desc.elems] + mov [elems],ecx + mov edi,[s] +;zlib_debug 'build_tree cycle0 ecx = %d',ecx + + mov dword[edi+deflate_state.heap_len],0 + mov dword[edi+deflate_state.heap_max],HEAP_SIZE + + cmp ecx,0 + jle .cycle0end + xor edx,edx + .cycle0: ;for (..;..<..;..) + mov eax,edx + imul eax,sizeof.ct_data + add eax,[tree] + cmp word[eax+Freq],0 + je @f ;if (..!=0) + inc dword[edi+deflate_state.heap_len] + mov eax,[edi+deflate_state.heap_len] + mov [max_code],edx + mov [edi+deflate_state.heap+2*eax],dx + mov eax,edx + add eax,edi + add eax,deflate_state.depth + mov byte[eax],0 + jmp .end0 +align 4 + @@: ;else + mov word[eax+Len],0 + .end0: + inc edx + loop .cycle0 +align 4 + .cycle0end: + + ; The pkzip format requires that at least one distance code exists, + ; and that at least one bit should be sent even if there is only one + ; possible code. So to avoid special checks later on we force at least + ; two codes of non zero frequency. + + .cycle1: ;while (..<..) + cmp dword[edi+deflate_state.heap_len],2 + jge .cycle1end + inc dword[edi+deflate_state.heap_len] + xor eax,eax + cmp dword[max_code],2 + jge @f + inc dword[max_code] + mov eax,[max_code] + @@: + mov ecx,[edi+deflate_state.heap_len] + mov [edi+deflate_state.heap+2*ecx],ax + mov [node],eax + imul eax,sizeof.ct_data + add eax,[tree] + mov word[eax+Freq],1 + mov eax,[node] + mov byte[edi+deflate_state.depth+eax],0 + dec dword[edi+deflate_state.opt_len] + cmp dword[stree],0 + je .cycle1 ;if (..) + mov eax,[node] + imul eax,sizeof.ct_data + add eax,[stree] + movzx eax,word[eax+Len] + sub [edi+deflate_state.static_len],eax + ; node is 0 or 1 so it does not have extra bits + jmp .cycle1 +align 4 + .cycle1end: + mov eax,[max_code] + mov [ebx+tree_desc.max_code],eax + + ; The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + ; establish sub-heaps of increasing lengths: + + mov ecx,[edi+deflate_state.heap_len] + shr ecx,1 + .cycle2: ;for (..;..>=..;..) + cmp ecx,1 + jl .cycle2end + stdcall pqdownheap, edi, [tree], ecx + dec ecx + jmp .cycle2 +align 4 + .cycle2end: + + ; Construct the Huffman tree by repeatedly combining the least two + ; frequent nodes. + + mov eax,[elems] + mov [node],eax ;next internal node of the tree + .cycle3: ;do + pqremove edi, [tree], ecx ;n = node of least frequency + movzx edx,word[eax] + mov [m],edx ;m = node of next least frequency + + mov eax,[edi+deflate_state.heap_max] + dec eax + mov [edi+deflate_state.heap+2*eax],cx ;keep the nodes sorted by frequency + dec eax + mov [edi+deflate_state.heap_max],eax + mov [edi+deflate_state.heap+2*eax],dx + + ; Create a new node father of n and m + ;;mov edx,[m] + imul edx,sizeof.ct_data + add edx,[tree] + mov ax,word[edx+Freq] + mov edx,ecx + imul edx,sizeof.ct_data + add edx,[tree] + add ax,word[edx+Freq] + mov edx,[node] + imul edx,sizeof.ct_data + add edx,[tree] + mov word[edx+Freq],ax + + mov eax,ecx + add eax,edi + add eax,deflate_state.depth + mov al,byte[eax] + mov edx,[m] + add edx,edi + add edx,deflate_state.depth + mov ah,byte[edx] + cmp al,ah + jl @f ;if (al>=ah) al=al : al=ah + mov al,ah + @@: + inc al + mov edx,[node] + add edx,edi + add edx,deflate_state.depth + mov byte[edx],al + + mov eax,[node] + mov edx,[m] + imul edx,sizeof.ct_data + add edx,[tree] + mov [edx+Dad],ax + mov edx,ecx + imul edx,sizeof.ct_data + add edx,[tree] + mov [edx+Dad],ax +;if DUMP_BL_TREE eq 1 +; if (tree == s->bl_tree) { +; fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", +; node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); +; } +;end if + ; and insert the new node in the heap + mov ecx,[node] + mov [edi+deflate_state.heap+2*SMALLEST],cx + inc dword[node] + stdcall pqdownheap, edi, [tree], SMALLEST + cmp dword[edi+deflate_state.heap_len],2 + jge .cycle3 ;while (..>=..) + + mov cx,[edi+deflate_state.heap+2*SMALLEST] + dec dword[edi+deflate_state.heap_max] + mov eax,[edi+deflate_state.heap_max] + mov [edi+deflate_state.heap+2*eax],cx + + ; At this point, the fields freq and dad are set. We can now + ; generate the bit lengths. + + stdcall gen_bitlen, edi, [desc] + + ; The field len is now set, we can generate the bit codes + mov eax,edi + add eax,deflate_state.bl_count + stdcall gen_codes, [tree], [max_code], eax + ret +endp + +; =========================================================================== +; Scan a literal or distance tree to determine the frequencies of the codes +; in the bit length tree. + +;void (s, tree, max_code) +; deflate_state* s +; ct_data *tree ;the tree to be scanned +; int max_code ;and its largest code of non zero frequency +align 4 +proc scan_tree uses eax ebx ecx edi, s:dword, tree:dword, max_code:dword +locals + n dd ? ;int ;iterates over all tree elements + prevlen dd -1 ;int ;last emitted length + curlen dd ? ;int ;length of current code + nextlen dd ? ;int ;= tree[0].Len ;length of next code + count dd 0 ;int ;repeat count of the current code + max_count dd 7 ;int ;max repeat count + min_count dd 4 ;int ;min repeat count +endl + mov edi,[s] +;zlib_debug 'scan_tree' + mov eax,[tree] + movzx eax,word[eax+Len] + mov [nextlen],eax + cmp eax,0 + jne @f ;if (..==0) + mov dword[max_count],138 + mov dword[min_count],3 + @@: + mov eax,[max_code] + inc eax + imul eax,sizeof.ct_data + add eax,[tree] + mov word[eax+Len],0xffff ;guard + + xor ecx,ecx + .cycle0: + cmp ecx,[max_code] + jg .cycle0end ;for (..;..<=..;..) + mov eax,[nextlen] + mov [curlen],eax + mov eax,ecx + inc eax + imul eax,sizeof.ct_data + add eax,[tree] + movzx eax,word[eax+Len] + mov [nextlen],eax + inc dword[count] + mov ebx,[count] + cmp ebx,[max_count] + jge .end0 + mov eax,[nextlen] + cmp [curlen],eax + jne .end0 ;if (..<.. && ..==..) + inc ecx + jmp .cycle0 ;continue + .end0: + cmp ebx,[min_count] + jge .end1 ;else if (..<..) + mov eax,[curlen] + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Freq + add word[eax],bx + jmp .end4 + .end1: + cmp dword[curlen],0 + je .end2 ;else if (..!=0) + mov eax,[curlen] + cmp eax,[prevlen] + je @f ;if (..!=..) + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Freq + inc word[eax] + @@: + mov eax,REP_3_6 + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Freq + inc word[eax] + jmp .end4 + .end2: + cmp ebx,10 + jg .end3 ;else if (..<=..) + mov eax,REPZ_3_10 + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Freq + inc word[eax] + jmp .end4 + .end3: ;else + mov eax,REPZ_11_138 + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Freq + inc word[eax] + .end4: + mov dword[curlen],0 + mov eax,[curlen] + mov [prevlen],eax + mov [nextlen],eax + cmp eax,0 + jne .end5 ;if (..==0) + mov dword[max_count],138 + mov dword[min_count],3 + jmp .end7 + .end5: + mov eax,[curlen] + cmp eax,[nextlen] + jne .end6 ;else if (..==..) + mov dword[max_count],6 + mov dword[min_count],3 + jmp .end7 + .end6: ;else + mov dword[max_count],7 + mov dword[min_count],4 + .end7: + inc ecx + jmp .cycle0 + .cycle0end: + ret +endp + +; =========================================================================== +; Send a literal or distance tree in compressed form, using the codes in +; bl_tree. + +;void (s, tree, max_code) +; deflate_state* s +; ct_data *tree ;the tree to be scanned +; int max_code ;and its largest code of non zero frequency +align 4 +proc send_tree uses eax ebx ecx edi, s:dword, tree:dword, max_code:dword +locals + n dd ? ;int ;iterates over all tree elements + prevlen dd -1 ;int ;last emitted length + curlen dd ? ;int ;length of current code + nextlen dd ? ;int ;= tree[0].Len ;length of next code + count dd 0 ;int ;repeat count of the current code + max_count dd 7 ;int ;max repeat count + min_count dd 4 ;int ;min repeat count +endl + mov edi,[s] +;zlib_debug 'send_tree' + ; *** tree[max_code+1].Len = -1 ;guard already set + mov eax,[tree] + movzx eax,word[eax+Len] + mov [nextlen],eax + cmp eax,0 + jne @f ;if (..==0) + mov dword[max_count],138 + mov dword[min_count],3 + @@: + + xor ecx,ecx + .cycle0: ;for (..;..<=..;..) + cmp ecx,[max_code] + jg .cycle0end + mov eax,[nextlen] + mov [curlen],eax + mov eax,ecx + inc eax + imul eax,sizeof.ct_data + add eax,[tree] + movzx eax,word[eax+Len] + mov [nextlen],eax + inc dword[count] + mov ebx,[count] + cmp ebx,[max_count] + jge .end0 + mov eax,[nextlen] + cmp [curlen],eax + jne .end0 ;if (..<.. && ..==..) + inc ecx + jmp .cycle0 ;continue + .end0: + cmp ebx,[min_count] + jge .end1 ;else if (..<..) + @@: ;do + mov ebx,edi + add ebx,deflate_state.bl_tree + send_code edi, [curlen], ebx + dec dword[count] + cmp dword[count],0 + jne @b ;while (..!=0) + jmp .end4 +align 4 + .end1: + cmp dword[curlen],0 + je .end2 ;else if (..!=0) + mov eax,[curlen] + cmp eax,[prevlen] + je @f ;if (..!=..) + mov ebx,edi + add ebx,deflate_state.bl_tree + send_code edi, eax, ebx + dec dword[count] + @@: + cmp dword[count],3 + jl @f + cmp dword[count],6 + jle .end8 + @@: + zlib_debug ' 3_6?' ;Assert(..>=.. && ..<=..) + .end8: + mov ebx,edi + add ebx,deflate_state.bl_tree + send_code edi, REP_3_6, ebx + mov ebx,[count] + sub ebx,3 + stdcall send_bits, edi, ebx, 2 + jmp .end4 + .end2: + cmp ebx,10 + jg .end3 ;else if (..<=..) + mov ebx,edi + add ebx,deflate_state.bl_tree + send_code edi, REPZ_3_10, ebx + mov ebx,[count] + sub ebx,3 + stdcall send_bits, edi, ebx, 3 + jmp .end4 + .end3: ;else + mov ebx,edi + add ebx,deflate_state.bl_tree + send_code edi, REPZ_11_138, ebx + mov ebx,[count] + sub ebx,11 + stdcall send_bits, edi, ebx, 7 + .end4: + mov dword[curlen],0 + mov eax,[curlen] + mov [prevlen],eax + mov [nextlen],eax + cmp eax,0 + jne .end5 ;if (..==0) + mov dword[max_count],138 + mov dword[min_count],3 + jmp .end7 + .end5: + mov eax,[curlen] + cmp eax,[nextlen] + jne .end6 ;else if (..==..) + mov dword[max_count],6 + mov dword[min_count],3 + jmp .end7 + .end6: ;else + mov dword[max_count],7 + mov dword[min_count],4 + .end7: + inc ecx + jmp .cycle0 +align 4 + .cycle0end: + ret +endp + +; =========================================================================== +; Construct the Huffman tree for the bit lengths and return the index in +; bl_order of the last bit length code to send. + +;int (s) +; deflate_state* s +align 4 +proc build_bl_tree uses edi, s:dword +locals + max_blindex dd ? ;int ;index of last bit length code of non zero freq +endl + mov edi,[s] + ; Determine the bit length frequencies for literal and distance trees + mov eax,edi + add eax,deflate_state.dyn_ltree + stdcall scan_tree, edi, eax, [edi+deflate_state.l_desc.max_code] + mov eax,edi + add eax,deflate_state.dyn_dtree + stdcall scan_tree, edi, eax, [edi+deflate_state.d_desc.max_code] + + ; Build the bit length tree: + mov eax,edi + add eax,deflate_state.bl_desc + stdcall build_tree, edi, eax + ; opt_len now includes the length of the tree representations, except + ; the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + + ; Determine the number of bit length codes to send. The pkzip format + ; requires that at least 4 bit length codes be sent. (appnote.txt says + ; 3 but the actual value used is 4.) + + mov dword[max_blindex],BL_CODES-1 + .cycle0: ;for (..;..>=..;..) + cmp dword[max_blindex],3 + jl .cycle0end + dec dword[max_blindex] + mov eax,[max_blindex] + add eax,bl_order + movzx eax,byte[eax] + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.bl_tree+Len + cmp word[eax],0 + jne .cycle0end ;if (..!=0) break + jmp .cycle0 + .cycle0end: + ; Update opt_len to include the bit length tree and counts + mov eax,[max_blindex] + inc eax + imul eax,3 + add eax,5+5+4 + add [edi+deflate_state.opt_len],eax +; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); + + mov eax,[max_blindex] + ret +endp + +; =========================================================================== +; Send the header for a block using dynamic Huffman trees: the counts, the +; lengths of the bit length codes, the literal tree and the distance tree. +; IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + +;void (s, lcodes, dcodes, blcodes) +; deflate_state* s +; int lcodes, dcodes, blcodes ;number of codes for each tree +align 4 +proc send_all_trees uses eax ebx ecx edi, s:dword, lcodes:dword, dcodes:dword, blcodes:dword +;ecx = index in bl_order +;zlib_debug 'send_all_trees' + cmp dword[lcodes],257 + jl @f + cmp dword[dcodes],1 + jl @f + cmp dword[blcodes],4 + jge .end0 + @@: + zlib_debug 'not enough codes' ;Assert(..>=.. && ..>=.. && ..>=..) + .end0: + cmp dword[lcodes],L_CODES + jg @f + cmp dword[dcodes],D_CODES + jg @f + cmp dword[blcodes],BL_CODES + jle .end1 + @@: + zlib_debug 'too many codes' ;Assert(..<=.. && ..<=.. && ..<=..) + .end1: +; Tracev((stderr, "\nbl counts: ")); + mov edi,[s] + mov eax,[lcodes] + sub eax,257 + stdcall send_bits, edi, eax, 5 ;not +255 as stated in appnote.txt + mov eax,[dcodes] + dec eax + stdcall send_bits, edi, eax, 5 + mov eax,[blcodes] + sub eax,4 + stdcall send_bits, edi, eax, 4 ;not -3 as stated in appnote.txt + xor ecx,ecx + .cycle0: + cmp ecx,[blcodes] + jge .cycle0end ;for (..;..<..;..) +; Tracev((stderr, "\nbl code %2d ", bl_order[ecx])); + mov eax,ecx + add eax,bl_order + movzx eax,byte[eax] + imul eax,sizeof.ct_data + mov ebx,edi + add ebx,deflate_state.bl_tree+Len + add ebx,eax + stdcall send_bits, edi, ebx, 3 + inc ecx + jmp .cycle0 +align 4 + .cycle0end: +; Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + mov ebx,[lcodes] + dec ebx + mov eax,edi + add eax,deflate_state.dyn_ltree + stdcall send_tree, edi, eax, ebx ;literal tree +; Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + mov ebx,[dcodes] + dec ebx + add eax,deflate_state.dyn_dtree-deflate_state.dyn_ltree + stdcall send_tree, edi, eax, ebx ;distance tree +; Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + ret +endp + +; =========================================================================== +; Send a stored block + +;void (s, buf, stored_len, last) +; deflate_state* s +; charf *buf ;input block +; ulg stored_len ;length of input block +; int last ;one if this is the last block for a file +align 4 +proc _tr_stored_block uses eax edi, s:dword, buf:dword, stored_len:dword, last:dword + mov edi,[s] + mov eax,[last] + add eax,STORED_BLOCK shl 1 + stdcall send_bits, edi, eax, 3 ;send block type +if DEBUG eq 1 + mov eax,[edi+deflate_state.compressed_len] + add eax,3+7 + and eax,not 7 + mov [edi+deflate_state.compressed_len],eax + mov eax,[stored_len] + add eax,4 + shl eax,3 + add [edi+deflate_state.compressed_len],eax +end if + stdcall copy_block, edi, [buf], [stored_len], 1 ;with header + ret +endp + +; =========================================================================== +; Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + +;void (s) +; deflate_state* s; +align 4 +proc _tr_flush_bits, s:dword + stdcall bi_flush, [s] + ret +endp + +; =========================================================================== +; Send one empty static block to give enough lookahead for inflate. +; This takes 10 bits, of which 7 may remain in the bit buffer. + +;void (s) +; deflate_state* s +align 4 +proc _tr_align uses edi, s:dword + mov edi,[s] + stdcall send_bits, edi, STATIC_TREES shl 1, 3 + send_code edi, END_BLOCK, static_ltree +if DEBUG eq 1 + add [edi+deflate_state.compressed_len],10 ;3 for block type, 7 for EOB +end if + stdcall bi_flush, edi + ret +endp + +; =========================================================================== +; Determine the best encoding for the current block: dynamic trees, static +; trees or store, and output the encoded block to the zip file. + +;void (s, buf, stored_len, last) +; deflate_state* s +; charf *buf ;input block, or NULL if too old +; ulg stored_len ;length of input block +; int last ;one if this is the last block for a file +align 4 +proc _tr_flush_block uses eax ebx edi, s:dword, buf:dword, stored_len:dword, last:dword +locals + opt_lenb dd ? ;ulg + static_lenb dd ? ;opt_len and static_len in bytes + max_blindex dd 0 ;int ;index of last bit length code of non zero freq +endl + ; Build the Huffman trees unless a stored block is forced + mov edi,[s] +;zlib_debug '_tr_flush_block' + cmp word[edi+deflate_state.level],0 + jle .end0 ;if (..>0) + + ; Check if the file is binary or text + mov ebx,[edi+deflate_state.strm] + cmp word[ebx+z_stream.data_type],Z_UNKNOWN + jne @f ;if (..==..) + stdcall detect_data_type, edi + mov [ebx+z_stream.data_type],ax + @@: + + ; Construct the literal and distance trees + mov eax,edi + add eax,deflate_state.l_desc + stdcall build_tree, edi, eax +; Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); + + mov eax,edi + add eax,deflate_state.d_desc + stdcall build_tree, edi, eax +; Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); + ; At this point, opt_len and static_len are the total bit lengths of + ; the compressed block data, excluding the tree representations. + + ; Build the bit length tree for the above two trees, and get the index + ; in bl_order of the last bit length code to send. + + stdcall build_bl_tree, edi + mov [max_blindex],eax + + ; Determine the best encoding. Compute the block lengths in bytes. + mov eax,[edi+deflate_state.opt_len] + add eax,3+7 + shr eax,3 + mov [opt_lenb],eax + mov eax,[edi+deflate_state.static_len] + add eax,3+7 + shr eax,3 + mov [static_lenb],eax + +; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", +; opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, +; s->last_lit)); + + cmp eax,[opt_lenb] + jg .end1 ;if (..<=..) + mov [opt_lenb],eax + jmp .end1 + .end0: ;else + cmp dword[buf],0 + jne @f + zlib_debug 'lost buf' ;Assert(..!=0) + @@: + mov eax,[stored_len] + add eax,5 + mov [static_lenb],eax + mov [opt_lenb],eax ;force a stored block + .end1: + +if FORCE_STORED eq 1 + cmp dword[buf],0 + je .end2 ;if (..!=0) ;force stored block +else + mov eax,[stored_len] + add eax,4 + cmp eax,[opt_lenb] + jg .end2 + cmp dword[buf],0 + je .end2 ;if (..<=.. && ..!=0) + ;4: two words for the lengths +end if + ; The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + ; Otherwise we can't have processed more than WSIZE input bytes since + ; the last block flush, because compression would have been + ; successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + ; transform a block into a stored block. + + stdcall _tr_stored_block, edi, [buf], [stored_len], [last] + jmp .end4 + .end2: +if FORCE_STATIC eq 1 + cmp dword[static_lenb],0 + jl .end3 ;else if (..>=0) ;force static trees +else + cmp word[edi+deflate_state.strategy],Z_FIXED + je @f + mov eax,[opt_lenb] + cmp [static_lenb],eax + je @f ;else if (..==.. || ..==..) + jmp .end3 + @@: +end if + mov eax,STATIC_TREES shl 1 + add eax,[last] + stdcall send_bits, edi, eax, 3 + stdcall compress_block, edi, static_ltree, static_dtree +if DEBUG eq 1 + mov eax,[edi+deflate_state.static_len] + add eax,3 + add [edi+deflate_state.compressed_len],eax +end if + jmp .end4 + .end3: ;else + mov eax,DYN_TREES shl 1 + add eax,[last] + stdcall send_bits, edi, eax, 3 + mov eax,[max_blindex] + inc eax + push eax + mov eax,[edi+deflate_state.d_desc.max_code] + inc eax + push eax + mov eax,[edi+deflate_state.l_desc.max_code] + inc eax + stdcall send_all_trees, edi, eax ;, ..., ... + mov eax,edi + add eax,deflate_state.dyn_dtree + push eax + add eax,deflate_state.dyn_ltree-deflate_state.dyn_dtree + stdcall compress_block, edi, eax ;, ... +if DEBUG eq 1 + mov eax,[edi+deflate_state.opt_len] + add eax,3 + add [edi+deflate_state.compressed_len],eax +end if + .end4: +; Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + ; The above check is made mod 2^32, for files larger than 512 MB + ; and uLong implemented on 32 bits. + + stdcall init_block,edi + + cmp dword[last],0 + je @f ;if (..) + stdcall bi_windup,edi +if DEBUG eq 1 + add [edi+deflate_state.compressed_len],7 ;align on byte boundary +end if + @@: +; Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, +; s->compressed_len-7*last)); + ret +endp + +; =========================================================================== +; Save the match info and tally the frequency counts. Return true if +; the current block must be flushed. + +;int (s, dist, lc) +; deflate_state* s +; unsigned dist ;distance of matched string +; unsigned lc ;match length-MIN_MATCH or unmatched char (if dist==0) +align 4 +proc _tr_tally uses ebx edi, s:dword, dist:dword, lc:dword + mov edi,[s] +;zlib_debug '_tr_tally' + mov eax,[edi+deflate_state.last_lit] + shl eax,1 + add eax,[edi+deflate_state.d_buf] + mov ebx,[dist] + mov word[eax],bx + mov eax,[edi+deflate_state.last_lit] + add eax,[edi+deflate_state.l_buf] + mov ebx,[lc] + mov byte[eax],bl + inc dword[edi+deflate_state.last_lit] + cmp dword[dist],0 + jne @f ;if (..==0) + ; lc is the unmatched char + mov eax,[lc] + imul eax,sizeof.ct_data + add eax,edi + inc word[eax+deflate_state.dyn_ltree+Freq] + jmp .end0 + @@: ;else + inc dword[edi+deflate_state.matches] + ; Here, lc is the match length - MIN_MATCH + dec dword[dist] ;dist = match distance - 1 + MAX_DIST edi + cmp word[dist],ax + jge @f + cmp word[lc],MAX_MATCH-MIN_MATCH + jg @f + d_code [dist] + cmp ax,D_CODES + jl .end2 + @@: + zlib_debug '_tr_tally: bad match' ;Assert(..<.. && ..<=.. && ..<..) + .end2: + mov eax,[lc] + add eax,_length_code + movzx eax,byte[eax] + add eax,LITERALS+1 + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.dyn_ltree+Freq + inc word[eax] + d_code [dist] + imul eax,sizeof.ct_data + add eax,edi + add eax,deflate_state.dyn_dtree+Freq + inc word[eax] + .end0: + +if TRUNCATE_BLOCK eq 1 + ; Try to guess if it is profitable to stop the current block here + mov eax,[edi+deflate_state.last_lit] + and eax,0x1fff + cmp eax,0 + jne .end1 + cmp word[edi+deflate_state.level],2 + jle .end1 ;if (..==.. && ..>..) + ; Compute an upper bound for the compressed length +; ulg out_length = (ulg)s->last_lit*8L; +; ulg in_length = (ulg)((long)s->strstart - s->block_start); +; int dcode; +; for (dcode = 0; dcode < D_CODES; dcode++) { +; out_length += (ulg)s->dyn_dtree[dcode].Freq * +; (5L+extra_dbits[dcode]); +; } +; out_length >>= 3; +; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", +; s->last_lit, in_length, out_length, +; 100L - out_length*100L/in_length)); +; if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + .end1: +end if + mov ebx,[edi+deflate_state.last_lit] + mov edi,[edi+deflate_state.lit_bufsize] + dec edi + xor eax,eax + cmp ebx,edi + jne @f + inc eax ;return (..==..) + @@: + ; We avoid equality with lit_bufsize because of wraparound at 64K + ; on 16 bit machines and because stored blocks are restricted to + ; 64K-1 bytes. + ret +endp + +; =========================================================================== +; Send the block data compressed using the given Huffman trees + +;void (s, ltree, dtree) +; deflate_state* s; +; ct_data *ltree ;literal tree +; ct_data *dtree ;distance tree +align 4 +proc compress_block uses eax edi, s:dword, ltree:dword, dtree:dword +locals + dist dd ? ;unsigned ;distance of matched string + lc dd ? ;int ;match length or unmatched char (if dist == 0) + lx dd 0 ;unsigned ;running index in l_buf + u_code dd ? ;unsigned ;the code to send + extra dd ? ;int ;number of extra bits to send +endl + mov edi,[s] + cmp dword[edi+deflate_state.last_lit],0 + je .end0 ;if (..!=0) + .cycle0: ; do + mov eax,[lx] + shl eax,1 + add eax,[edi+deflate_state.d_buf] + movzx eax,word[eax] + mov [dist],eax + mov eax,[lx] + add eax,[edi+deflate_state.l_buf] + movzx eax,byte[eax] + mov [lc],eax + inc dword[lx] + cmp dword[dist],0 + jne @f ;if (..==0) + send_code edi, [lc], [ltree] ;send a literal byte +; Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + jmp .end1 + @@: ;else + ; Here, lc is the match length - MIN_MATCH + mov eax,[lc] + add eax,_length_code + movzx eax,byte[eax] + mov [u_code],eax + add eax,LITERALS+1 + send_code edi, eax, [ltree] ;send the length code + mov eax,[u_code] + shl eax,2 + add eax,extra_lbits + mov eax,[eax] + mov [extra],eax + cmp eax,0 + je @f ;if (..!=0) + mov eax,[u_code] + shl eax,2 + add eax,base_length + mov eax,[eax] + sub [lc],eax + stdcall send_bits, edi, [lc], [extra] ;send the extra length bits + @@: + dec dword[dist] ;dist is now the match distance - 1 + d_code [dist] + mov [u_code],eax + cmp eax,D_CODES + jl @f + zlib_debug 'bad d_code' ;Assert(..<..) + @@: + send_code edi, [u_code], [dtree] ;send the distance code + mov eax,[u_code] + shl eax,2 + add eax,extra_dbits + mov eax,[eax] + mov [extra],eax + cmp eax,0 + je .end1 ;if (..!=0) + mov eax,[u_code] + shl eax,2 + add eax,base_dist + mov eax,[eax] + sub [dist],eax + stdcall send_bits, edi, [dist], [extra] ;send the extra distance bits + .end1: ;literal or match pair ? + + ; Check that the overlay between pending_buf and d_buf+l_buf is ok: + mov eax,[lx] + shl eax,1 + add eax,[edi+deflate_state.lit_bufsize] + cmp word[edi+deflate_state.pending],ax + jl @f + zlib_debug 'pendingBuf overflow' ;Assert(..<..) + @@: + mov eax,[edi+deflate_state.last_lit] + cmp [lx],eax + jl .cycle0 ;while (..<..) +align 4 + .end0: + + send_code edi, END_BLOCK, [ltree] + ret +endp + +; =========================================================================== +; Check if the data type is TEXT or BINARY, using the following algorithm: +; - TEXT if the two conditions below are satisfied: +; a) There are no non-portable control characters belonging to the +; "black list" (0..6, 14..25, 28..31). +; b) There is at least one printable character belonging to the +; "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). +; - BINARY otherwise. +; - The following partially-portable control characters form a +; "gray list" that is ignored in this detection algorithm: +; (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). +; IN assertion: the fields Freq of dyn_ltree are set. + +;int (s) +; deflate_state* s +align 4 +proc detect_data_type uses ebx ecx edi, s:dword + ; black_mask is the bit mask of black-listed bytes + ; set bits 0..6, 14..25, and 28..31 + ; 0xf3ffc07f = binary 11110011111111111100000001111111 +locals + black_mask dd 0xf3ffc07f +; int n; +endl + mov edi,[s] +;zlib_debug 'detect_data_type' + + ; Check for non-textual ("black-listed") bytes. + xor ecx,ecx + mov ebx,edi + add ebx,deflate_state.dyn_ltree+Freq + .cycle0: + cmp ecx,31 + jg .cycle0end ;for (..;..<=..;..,..) + bt dword[black_mask],0 + jnc @f + cmp word[ebx],0 + je @f ;if (..&.. && ..!=0) + mov eax,Z_BINARY + jmp .end_f + @@: + shr dword[black_mask],1 + add ebx,sizeof.ct_data + inc ecx + jmp .cycle0 + .cycle0end: + + ; Check for textual ("white-listed") bytes. + mov ebx,edi + add ebx,deflate_state.dyn_ltree+Freq+9*sizeof.ct_data + cmp word[ebx],0 + jne @f + add ebx,sizeof.ct_data + cmp word[ebx],0 + jne @f + add ebx,3*sizeof.ct_data + cmp word[ebx],0 + je .end0 + @@: ;if (..!=0 || ..!=0 || ..!= 0) + mov eax,Z_TEXT + jmp .end_f + .end0: + mov ecx,32 + mov ebx,edi + add ebx,deflate_state.dyn_ltree+Freq + .cycle1: + cmp ecx,LITERALS + jge .cycle1end ;for (..;..<..;..,..) + cmp word[ebx],0 + je @f ;if (..!=0) + mov eax,Z_TEXT + jmp .end_f + @@: + add ebx,sizeof.ct_data + inc ecx + jmp .cycle1 + .cycle1end: + + ; There are no "black-listed" or "white-listed" bytes: + ; this stream either is empty or has tolerated ("gray-listed") bytes only. + + mov eax,Z_BINARY +.end_f: + ret +endp + +; =========================================================================== +; Reverse the first len bits of a code, using straightforward code (a faster +; method would use a table) +; IN assertion: 1 <= len <= 15 + +;unsigned (code, len) +; unsigned code ;the value to invert +; int len ;its bit length +align 4 +proc bi_reverse uses ebx, p1code:dword, len:dword +;zlib_debug 'bi_reverse' + xor eax,eax + @@: ;do + mov ebx,[p1code] + and ebx,1 + or eax,ebx + shr dword[p1code],1 + shl eax,1 + dec dword[len] + cmp dword[len],0 + jg @b ;while (..>..) + shl eax,1 + ret +endp + +; =========================================================================== +; Flush the bit buffer, keeping at most 7 bits in it. + +;void (s) +; deflate_state* s +align 4 +proc bi_flush uses eax ecx edi, s:dword + mov edi,[s] + cmp dword[edi+deflate_state.bi_valid],16 + jne @f ;if (..==..) + mov cx,[edi+deflate_state.bi_buf] + put_short edi,cx + mov word[edi+deflate_state.bi_buf],0 + mov dword[edi+deflate_state.bi_valid],0 + jmp .end0 + @@: ;else if (..>=..) + cmp dword[edi+deflate_state.bi_valid],8 + jl .end0 + mov cl,byte[edi+deflate_state.bi_buf] + put_byte edi,cl + shr word[edi+deflate_state.bi_buf],8 + sub dword[edi+deflate_state.bi_valid],8 + .end0: + ret +endp + +; =========================================================================== +; Flush the bit buffer and align the output on a byte boundary + +;void (s) +; deflate_state* s +align 4 +proc bi_windup uses eax ecx edi, s:dword + mov edi,[s] + cmp dword[edi+deflate_state.bi_valid],8 + jle @f ;if (..>..) + mov cx,[edi+deflate_state.bi_buf] + put_short edi, cx + jmp .end0 + @@: ;else if (..>0) + cmp dword[edi+deflate_state.bi_valid],0 + jle .end0 + mov cl,byte[edi+deflate_state.bi_buf] + put_byte edi, cl + .end0: + mov word[edi+deflate_state.bi_buf],0 + mov dword[edi+deflate_state.bi_valid],0 +if DEBUG eq 1 + mov eax,[edi+deflate_state.bits_sent] + add eax,7 + and eax,not 7 + mov [edi+deflate_state.bits_sent],eax +end if + ret +endp + +; =========================================================================== +; Copy a stored block, storing first the length and its +; one's complement if requested. + +;void (s, buf, len, header) +; deflate_state* s +; charf *buf ;the input data +; unsigned len ;its length +; int header ;true if block header must be written +align 4 +proc copy_block uses eax ebx ecx edi esi, s:dword, buf:dword, len:dword, p4header:dword + mov edi,[s] + stdcall bi_windup,edi ;align on byte boundary + + cmp dword[p4header],0 + je @f ;if (..) + mov ecx,[len] + put_short edi, cx + not cx + put_short edi, cx +if DEBUG eq 1 + add dword[edi+deflate_state.bits_sent],2*16 +end if + @@: +if DEBUG eq 1 + mov ecx,[len] + shl ecx,3 + add [edi+deflate_state.bits_sent],ecx +end if + mov ecx,[len] + mov esi,[buf] + @@: ;while (len--) + lodsb + mov bl,al + put_byte edi, bl + loop @b + ret +endp diff --git a/programs/fs/kfar/trunk/zlib/trees.inc b/programs/fs/kfar/trunk/zlib/trees.inc new file mode 100644 index 0000000000..313b6f777e --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/trees.inc @@ -0,0 +1,139 @@ + + +;ct_data[L_CODES+2] +align 4 +static_ltree dw \ + 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,\ + 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,\ + 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,\ + 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,\ + 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,\ + 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,\ + 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,\ + 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,\ + 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,\ + 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,\ + 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,\ + 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,\ + 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,\ + 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,\ + 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,\ + 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,\ + 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,\ + 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,\ + 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,\ + 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,\ + 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,\ + 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,\ + 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,\ + 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,\ + 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,\ + 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,\ + 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,\ + 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,\ + 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,\ + 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,\ + 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,\ + 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,\ + 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,\ + 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,\ + 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,\ + 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,\ + 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,\ + 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,\ + 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,\ + 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,\ + 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,\ + 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,\ + 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,\ + 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,\ + 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,\ + 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,\ + 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,\ + 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,\ + 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,\ + 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,\ + 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,\ + 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,\ + 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,\ + 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,\ + 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,\ + 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,\ + 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,\ + 163, 8, 99, 8, 227, 8 + + +;ct_data[D_CODES] +align 4 +static_dtree dw \ + 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,\ + 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,\ + 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,\ + 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,\ + 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,\ + 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 + + +;uch[DIST_CODE_LEN] +align 4 +_dist_code db \ + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,\ + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,\ + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\ + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\ + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,\ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\ + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,\ + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\ + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\ + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,\ + 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\ + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\ + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\ + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\ + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,\ + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\ + 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\ + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\ + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\ + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\ + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\ + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\ + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + + +;uch[MAX_MATCH-MIN_MATCH+1] +align 4 +_length_code db \ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,\ + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\ + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,\ + 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\ + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,\ + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,\ + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\ + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\ + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\ + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,\ + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\ + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\ + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 + + +;int[LENGTH_CODES] +align 4 +base_length dd \ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,\ + 64, 80, 96, 112, 128, 160, 192, 224, 0 + + +;int[D_CODES] +align 4 +base_dist dd \ + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,\ + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,\ + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 + diff --git a/programs/fs/kfar/trunk/zlib/zconf.inc b/programs/fs/kfar/trunk/zlib/zconf.inc new file mode 100644 index 0000000000..5d0e3a9845 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zconf.inc @@ -0,0 +1,165 @@ +; zconf.inc -- configuration of the zlib compression library +; Copyright (C) 1995-2013 Jean-loup Gailly. +; For conditions of distribution and use, see copyright notice in zlib.inc + +; Compile with -DMAXSEG_64K if the alloc function cannot allocate more +; than 64k bytes at a time (needed on systems with 16-bit int). + +;if MSDOS +;# define UNALIGNED_OK +;end if + +; Maximum value for memLevel in deflateInit2 +MAX_MEM_LEVEL equ 9 + +; Maximum value for windowBits in deflateInit2 and inflateInit2. +; WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files +; created by gzip. (Files created by minigzip can still be extracted by +; gzip.) + +MAX_WBITS equ 15 ;32K LZ77 window + +; The memory requirements for deflate are (in bytes): +; (1 << (windowBits+2)) + (1 << (memLevel+9)) +; that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) +; plus a few kilobytes for small objects. For example, if you want to reduce +; the default memory requirements from 256K to 128K, compile with +; make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" +; Of course this will generally degrade compression (there's no free lunch). + +; The memory requirements for inflate are (in bytes) 1 << windowBits +; that is, 32K for windowBits=15 (default value) plus a few kilobytes +; for small objects. + +; /* Type declarations */ + +;#ifndef OF /* function prototypes */ +;# ifdef STDC +;# define OF(args) args +;# else +;# define OF(args) () +;# endif +;end if + +;#ifndef Z_ARG /* function prototypes for stdarg */ +;# if defined(STDC) || defined(Z_HAVE_STDARG_H) +;# define Z_ARG(args) args +;# else +;# define Z_ARG(args) () +;# endif +;end if + +; The following definitions for FAR are needed only for MSDOS mixed +; model programming (small or medium model with some far allocations). +; This was tested only with MSC; for other MSDOS compilers you may have +; to define NO_MEMCPY in zutil.h. If you don't need the mixed model, +; just define FAR to be empty. + +;#if defined(WINDOWS) || defined(WIN32) + ; If building or using zlib as a DLL, define ZLIB_DLL. + ; This is not mandatory, but it offers a little performance increase. + +;# ifdef ZLIB_DLL +;# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +;# ifdef ZLIB_INTERNAL +;# define ZEXTERN extern __declspec(dllexport) +;# else +;# define ZEXTERN extern __declspec(dllimport) +;# endif +;# endif +;# endif /* ZLIB_DLL */ + ; If building or using zlib with the WINAPI/WINAPIV calling convention, + ; define ZLIB_WINAPI. + ; Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + +;#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +;# include +;# if (UINT_MAX == 0xffffffffUL) +;# define Z_U4 unsigned +;# elif (ULONG_MAX == 0xffffffffUL) +;# define Z_U4 unsigned long +;# elif (USHRT_MAX == 0xffffffffUL) +;# define Z_U4 unsigned short +;# endif +;end if + +;if Z_U4 +; typedef Z_U4 z_crc_t; +;else +; typedef unsigned long z_crc_t; +;end if + +;if HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +;# define Z_HAVE_UNISTD_H +;end if + +;if HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +;# define Z_HAVE_STDARG_H +;end if + +;if STDC +;# ifndef Z_SOLO +;# include /* for off_t */ +;# endif +;end if + +;#if defined(STDC) || defined(Z_HAVE_STDARG_H) +;# ifndef Z_SOLO +;# include /* for va_list */ +;# endif +;end if + +; a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and +; "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even +; though the former does not conform to the LFS document), but considering +; both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as +; equivalently requesting no 64-bit operations + +;#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +;# undef _LARGEFILE64_SOURCE +;end if + +;#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +;# define Z_HAVE_UNISTD_H +;end if +;#ifndef Z_SOLO +;# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +;# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +;# ifdef VMS +;# include /* for off_t */ +;# endif +;# ifndef z_off_t +;# define z_off_t off_t +;# endif +;# endif +;end if + +;#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +;# define Z_LFS64 +;end if + +;#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +;# define Z_LARGE64 +;end if + +;#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +;# define Z_WANT64 +;end if + +;#if !defined(SEEK_SET) && !defined(Z_SOLO) +;# define SEEK_SET 0 /* Seek from beginning of file. */ +;# define SEEK_CUR 1 /* Seek from current position. */ +;# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +;end if + +;# define z_off_t long + +;#if !defined(_WIN32) && defined(Z_LARGE64) +;# define z_off64_t off64_t +;else +;# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +;# define z_off64_t __int64 +;# else +;# define z_off64_t z_off_t +;# endif +;end if diff --git a/programs/fs/kfar/trunk/zlib/zlib.asm b/programs/fs/kfar/trunk/zlib/zlib.asm new file mode 100644 index 0000000000..11fa575849 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zlib.asm @@ -0,0 +1,179 @@ +format MS COFF +public EXPORTS + +section '.flat' code readable align 16 + +include '../../../../proc32.inc' +include '../../../../macros.inc' +include '../../../../KOSfuncs.inc' + +FASTEST equ 1 +GEN_TREES_H equ 0 +DEBUG equ 0 +DYNAMIC_CRC_TABLE equ 1 + +; define NO_GZIP when compiling if you want to disable gzip header and +; trailer creation by deflate(). NO_GZIP would be used to avoid linking in +; the crc code when it is not needed. For shared libraries, gzip encoding +; should be left enabled. +GZIP equ 1 + +macro zlib_debug fmt,p1 +{ +local .end_t +local .m_fmt +jmp .end_t + .m_fmt db fmt,13,10,0 +align 4 +.end_t: +if p1 eq + stdcall dbg_print,0,.m_fmt +else + stdcall str_format_dbg, buf_param,.m_fmt,p1 +end if +} + +include 'zlib.inc' +include 'deflate.inc' +include 'zutil.asm' +include 'crc32.asm' +include 'adler32.asm' +include 'trees.asm' +include 'deflate.asm' + +align 4 +buf_param rb 80 + +align 4 +proc dbg_print, fun:dword, mes:dword +pushad + mov eax,SF_BOARD + mov ebx,SSF_DEBUG_WRITE + + mov esi,[fun] + cmp esi,0 + je .end0 + @@: + mov cl,byte[esi] + int 0x40 + inc esi + cmp byte[esi],0 + jne @b + mov cl,':' + int 0x40 + mov cl,' ' + int 0x40 + .end0: + mov esi,[mes] + cmp esi,0 + je .end_f + @@: + mov cl,byte[esi] + cmp cl,0 + je .end_f + int 0x40 + inc esi + jmp @b + .end_f: +popad + ret +endp + +align 4 +proc str_format_dbg, buf:dword, fmt:dword, p1:dword +pushad + mov esi,[fmt] + mov edi,[buf] + mov ecx,80-1 + .cycle0: + lodsb + cmp al,'%' + jne .no_param + lodsb + dec ecx + cmp al,0 + je .cycle0end + cmp al,'d' + je @f + cmp al,'u' + je @f + cmp al,'l' + je .end1 + jmp .end0 + .end1: ;%lu %lx + lodsb + dec ecx + cmp al,'u' + jne .end0 + @@: + mov eax,[p1] + stdcall convert_int_to_str,ecx + xor al,al + repne scasb + dec edi + .end0: + loop .cycle0 + .no_param: + stosb + cmp al,0 + je .cycle0end + loop .cycle0 + .cycle0end: + xor al,al + stosb + stdcall dbg_print,0,[buf] +popad + ret +endp + +;input: +; eax - число +; edi - буфер для строки +; len - длинна буфера +;output: +align 4 +proc convert_int_to_str, len:dword +pushad + mov esi,[len] + add esi,edi + dec esi + call .str +popad + ret +endp + +align 4 +.str: + mov ecx,0x0a + cmp eax,ecx + jb @f + xor edx,edx + div ecx + push edx + call .str + pop eax + @@: + cmp edi,esi + jge @f + or al,0x30 + stosb + mov byte[edi],0 + @@: + ret + +; export table +align 4 +EXPORTS: + dd adeflateInit, deflateInit + dd adeflateInit2, deflateInit2 + dd adeflateReset, deflateReset + dd adeflate, deflate + dd adeflateEnd, deflateEnd + dd 0 + +; exported names +adeflateInit db 'deflateInit',0 +adeflateInit2 db 'deflateInit2',0 +adeflateReset db 'deflateReset',0 +adeflate db 'deflate',0 +adeflateEnd db 'deflateEnd',0 \ No newline at end of file diff --git a/programs/fs/kfar/trunk/zlib/zlib.inc b/programs/fs/kfar/trunk/zlib/zlib.inc new file mode 100644 index 0000000000..250d0b6495 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zlib.inc @@ -0,0 +1,262 @@ +; zlib.inc -- interface of the 'zlib' general purpose compression library +; version 1.2.8, April 28th, 2013 + +; Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. + +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: + +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software. +; 3. This notice may not be removed or altered from any source distribution. + +; Jean-loup Gailly Mark Adler +; jloup@gzip.org madler@alumni.caltech.edu + + +; The data format used by the zlib library is described by RFCs (Request for +; Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 +; (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). + + +include 'zconf.inc' + +align 4 +ZLIB_VERSION db '1.2.8',0 +ZLIB_VERNUM equ 0x1280 +ZLIB_VER_MAJOR equ 1 +ZLIB_VER_MINOR equ 2 +ZLIB_VER_REVISION equ 8 +ZLIB_VER_SUBREVISION equ 0 + + +; The 'zlib' compression library provides in-memory compression and +; decompression functions, including integrity checks of the uncompressed data. +; This version of the library supports only one compression method (deflation) +; but other algorithms will be added later and will have the same stream +; interface. + +; Compression can be done in a single step if the buffers are large enough, +; or can be done by repeated calls of the compression function. In the latter +; case, the application must provide more input and/or consume the output +; (providing more output space) before each call. + +; The compressed data format used by default by the in-memory functions is +; the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped +; around a deflate stream, which is itself documented in RFC 1951. + +; The library also supports reading and writing files in gzip (.gz) format +; with an interface similar to that of stdio using the functions that start +; with "gz". The gzip format is different from the zlib format. gzip is a +; gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + +; This library can optionally read and write gzip streams in memory as well. + +; The zlib format was designed to be compact and fast for use in memory +; and on communications channels. The gzip format was designed for single- +; file compression on file systems, has a larger header than zlib to maintain +; directory information, and uses a different, slower check method than zlib. + +; The library does not install any signal handler. The decoder checks +; the consistency of the compressed data, so the library should never crash +; even in case of corrupted input. + +struct z_stream ;z_stream_s + next_in dd ? ;z_const Bytef * ;next input byte + avail_in dw ? ;uInt ;number of bytes available at next_in + total_in dd ? ;uLong ;total number of input bytes read so far + + next_out dd ? ;Bytef * ;next output byte should be put there + avail_out dw ? ;uInt ;remaining free space at next_out + total_out dd ? ;uLong ;total number of bytes output so far + + msg dd ? ;z_const char * ;last error message, NULL if no error + state dd ? ;deflate_state* ;not visible by applications + + zalloc dd ? ;alloc_func ;used to allocate the internal state + zfree dd ? ;free_func ;used to free the internal state + opaque dd ? ;voidpf ;private data object passed to zalloc and zfree + + data_type dw ? ;int ;best guess about the data type: binary or text + adler dd ? ;uLong ;adler32 value of the uncompressed data + reserved dd ? ;uLong ;reserved for future use +ends + +; gzip header information passed to and from zlib routines. See RFC 1952 +; for more details on the meanings of these fields. + +struct gz_header ;_s + text dd ? ;int ;true if compressed data believed to be text + time dd ? ;uLong ;modification time + xflags dd ? ;int ;extra flags (not used when writing a gzip file) + os dd ? ;int ;operating system + extra dd ? ;Bytef* ;pointer to extra field or Z_NULL if none + extra_len dd ? ;uInt ;extra field length (valid if extra != Z_NULL) + extra_max dd ? ;uInt ;space at extra (only when reading header) + name dd ? ;Bytef* ;pointer to zero-terminated file name or Z_NULL + name_max dd ? ;uInt ;space at name (only when reading header) + comment dd ? ;Bytef* ;pointer to zero-terminated comment or Z_NULL + comm_max dd ? ;uInt ;space at comment (only when reading header) + hcrc dd ? ;int ;true if there was or will be a header crc + done dd ? ;int ;true when done reading gzip header (not used + ;when writing a gzip file) +ends + + +; The application must update next_in and avail_in when avail_in has dropped +; to zero. It must update next_out and avail_out when avail_out has dropped +; to zero. The application must initialize zalloc, zfree and opaque before +; calling the init function. All other fields are set by the compression +; library and must not be updated by the application. + +; The opaque value provided by the application will be passed as the first +; parameter for calls of zalloc and zfree. This can be useful for custom +; memory management. The compression library attaches no meaning to the +; opaque value. + +; zalloc must return Z_NULL if there is not enough memory for the object. +; If zlib is used in a multi-threaded application, zalloc and zfree must be +; thread safe. + +; On 16-bit systems, the functions zalloc and zfree must be able to allocate +; exactly 65536 bytes, but will not be required to allocate more than this if +; the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers +; returned by zalloc for objects of exactly 65536 bytes *must* have their +; offset normalized to zero. The default allocation function provided by this +; library ensures this (see zutil.c). To reduce memory requirements and avoid +; any allocation of 64K objects, at the expense of compression ratio, compile +; the library with -DMAX_WBITS=14 (see zconf.h). + +; The fields total_in and total_out can be used for statistics or progress +; reports. After compression, total_in holds the total size of the +; uncompressed data and may be saved for use in the decompressor (particularly +; if the decompressor wants to decompress everything in a single step). + + +; constants + +Z_NO_FLUSH equ 0 +Z_PARTIAL_FLUSH equ 1 +Z_SYNC_FLUSH equ 2 +Z_FULL_FLUSH equ 3 +Z_FINISH equ 4 +Z_BLOCK equ 5 +Z_TREES equ 6 +; Allowed flush values; see deflate() and inflate() below for details + +Z_OK equ 0 +Z_STREAM_END equ 1 +Z_NEED_DICT equ 2 +Z_ERRNO equ (-1) +Z_STREAM_ERROR equ (-2) +Z_DATA_ERROR equ (-3) +Z_MEM_ERROR equ (-4) +Z_BUF_ERROR equ (-5) +Z_VERSION_ERROR equ (-6) +; Return codes for the compression/decompression functions. Negative values +; are errors, positive values are used for special but normal events. + + +Z_NO_COMPRESSION equ 0 +Z_BEST_SPEED equ 1 +Z_BEST_COMPRESSION equ 9 +Z_DEFAULT_COMPRESSION equ (-1) +; compression levels + +Z_FILTERED equ 1 +Z_HUFFMAN_ONLY equ 2 +Z_RLE equ 3 +Z_FIXED equ 4 +Z_DEFAULT_STRATEGY equ 0 +; compression strategy; see deflateInit2() below for details + +Z_BINARY equ 0 +Z_TEXT equ 1 +Z_ASCII equ Z_TEXT ;for compatibility with 1.2.2 and earlier +Z_UNKNOWN equ 2 +; Possible values of the data_type field (though see inflate()) + +Z_DEFLATED equ 8 +; The deflate compression method (the only one supported in this version) + +Z_NULL equ 0 ;for initializing zalloc, zfree, opaque + +zlib_version equ zlibVersion +; for compatibility with versions < 1.0.2 + +; various hacks, don't look :) + +; deflateInit and inflateInit are macros to allow checking the zlib version +; and the compiler's view of z_stream: + +;int inflateBackInit_ OF((z_streamp strm, int windowBits, +; unsigned char FAR *window, +; const char *version, +; int stream_size)); +;#define inflateInit(strm) \ +; inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) + +;#define inflateInit2(strm, windowBits) \ +; inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ +; (int)sizeof(z_stream)) +;#define inflateBackInit(strm, windowBits, window) \ +; inflateBackInit_((strm), (windowBits), (window), \ +; ZLIB_VERSION, (int)sizeof(z_stream)) + +;#ifndef Z_SOLO + +; gzgetc() macro and its supporting function and exposed data structure. Note +; that the real internal state is much larger than the exposed structure. +; This abbreviated structure exposes just enough for the gzgetc() macro. The +; user should not mess with these exposed elements, since their names or +; behavior could change in the future, perhaps even capriciously. They can +; only be used by the gzgetc() macro. You have been warned. + +;struct gzFile_s { +; unsigned have; +; unsigned char *next; +; z_off64_t pos; +;}; +;int gzgetc_ OF((gzFile file)); /* backward compatibility */ +;if Z_PREFIX_SET +;# undef z_gzgetc +;# define z_gzgetc(g) \ +; ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +;#else +;# define gzgetc(g) \ +; ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +;end if + +; provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or +; change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if +; both are true, the application gets the *64 functions, and the regular +; functions are changed to 64 bits) -- in case these are set on systems +; without large file support, _LFS64_LARGEFILE must also be true + +; undocumented functions +;const char * zError OF((int)); +;int inflateSyncPoint OF((z_streamp)); +;const z_crc_t FAR * get_crc_table OF((void)); +;int inflateUndermine OF((z_streamp, int)); +;int inflateResetKeep OF((z_streamp)); +;#if defined(_WIN32) && !defined(Z_SOLO) +;gzFile gzopen_w OF((const wchar_t *path, +; const char *mode)); +;end if +;#if defined(STDC) || defined(Z_HAVE_STDARG_H) +;# ifndef Z_SOLO +;int ZEXPORTVA gzvprintf Z_ARG((gzFile file, +; const char *format, +; va_list va)); +;# endif +;end if + diff --git a/programs/fs/kfar/trunk/zlib/zlib.txt b/programs/fs/kfar/trunk/zlib/zlib.txt new file mode 100644 index 0000000000..b185dc2327 --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zlib.txt @@ -0,0 +1,1405 @@ + zlib.inc -- interface of the 'zlib' general purpose compression library + version 1.2.8, April 28th, 2013 + + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + + + basic functions + + +const char * zlibVersion OF((void)); + + The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + + +int deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). + + +int deflate OF((z_streamp strm, int flush)); + + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. + + +int deflateEnd OF((z_streamp strm)); + + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). + + +int inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. + + +int inflate OF((z_streamp strm, int flush)); + + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. + + +int inflateEnd OF((z_streamp strm)); + + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). + + + Advanced functions + + The following functions are needed only in some special applications. + + +int deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). + + +int deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); + + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). + + +int deflateCopy OF((z_streamp dest, + z_streamp source)); + + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. + + +int deflateReset OF((z_streamp strm)); + + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). + + +int deflateParams OF((z_streamp strm, + int level, + int strategy)); + + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. + + +int deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); + + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + + +uLong deflateBound OF((z_streamp strm, + uLong sourceLen)); + + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. + + +int deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); + + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + + +int deflatePrime OF((z_streamp strm, + int bits, + int value)); + + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. + + +int deflateSetHeader OF((z_streamp strm, + gz_headerp head)); + + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + + +int inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. + + +int inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); + + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). + + +int inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); + + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. + + +int inflateSync OF((z_streamp strm)); + + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. + + +int inflateCopy OF((z_streamp dest, + z_streamp source)); + + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. + + +int inflateReset OF((z_streamp strm)); + + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). + + +int inflateReset2 OF((z_streamp strm, + int windowBits)); + + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. + + +int inflatePrime OF((z_streamp strm, + int bits, + int value)); + + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + + +long inflateMark OF((z_streamp strm)); + + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. + + +int inflateGetHeader OF((z_streamp strm, + gz_headerp head)); + + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + + +int inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. + + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +int inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); + + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. + + +int inflateBackEnd OF((z_streamp strm)); + + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. + + +uLong zlibCompileFlags OF((void)); + Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + + +#ifndef Z_SOLO + + utility functions + + + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. + + +int compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); + + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. + + +int compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); + + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. + + +uLong compressBound OF((uLong sourceLen)); + + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. + + +int uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); + + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. + + + gzip file access functions + + + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. + + +typedef struct gzFile_s *gzFile; ;semi-opaque gzip file descriptor + + +gzFile gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. + + +gzFile gzdopen OF((int fd, const char *mode)); + + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). + + +int gzbuffer OF((gzFile file, unsigned size)); + + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. + + +int gzsetparams OF((gzFile file, int level, int strategy)); + + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. + + +int gzread OF((gzFile file, voidp buf, unsigned len)); + + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. + + +int gzwrite OF((gzFile file, + voidpc buf, unsigned len)); + + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. + + +int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); + + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). + + +int gzputs OF((gzFile file, const char *s)); + + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. + + +char * gzgets OF((gzFile file, char *buf, int len)); + + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. + + +int gzputc OF((gzFile file, int c)); + + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. + + +int gzgetc OF((gzFile file)); + + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. + + +int gzungetc OF((int c, gzFile file)); + + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). + + +int gzflush OF((gzFile file, int flush)); + + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. + + + +z_off_t gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. + + +int gzrewind OF((gzFile file)); + + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) + + + +z_off_t gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) + + + +z_off_t gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. + + +int gzeof OF((gzFile file)); + + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. + + +int gzdirect OF((gzFile file)); + + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) + + +int gzclose OF((gzFile file)); + + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. + + +int gzclose_r OF((gzFile file)); +int gzclose_w OF((gzFile file)); + + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. + + +const char * gzerror OF((gzFile file, int *errnum)); + + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. + + +void gzclearerr OF((gzFile file)); + + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. + + +end if ;!Z_SOLO + + checksum functions + + + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. + + +uLong adler32 OF((uLong adler, const Bytef *buf, uInt len)); + + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); + + +uLong adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. + + +uLong crc32 OF((uLong crc, const Bytef *buf, uInt len)); + + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); + + +uLong crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. diff --git a/programs/fs/kfar/trunk/zlib/zutil.asm b/programs/fs/kfar/trunk/zlib/zutil.asm new file mode 100644 index 0000000000..0d0803da4e --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zutil.asm @@ -0,0 +1,203 @@ +; zutil.asm -- target dependent utility functions for the compression library +; Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. +; For conditions of distribution and use, see copyright notice in zlib.inc + +align 4 +z_errmsg dd ze0,ze1,ze2,ze3,ze4,ze5,ze6,ze7,ze8,ze9 +ze0 db 'need dictionary',0 ;Z_NEED_DICT 2 +ze1 db 'stream end',0 ;Z_STREAM_END 1 +ze2 db '',0 ;Z_OK 0 +ze3 db 'file error',0 ;Z_ERRNO (-1) +ze4 db 'stream error',0 ;Z_STREAM_ERROR (-2) +ze5 db 'data error',0 ;Z_DATA_ERROR (-3) +ze6 db 'insufficient memory',0 ;Z_MEM_ERROR (-4) +ze7 db 'buffer error',0 ;Z_BUF_ERROR (-5) +ze8 db 'incompatible version',0 ;Z_VERSION_ERROR (-6) +ze9 db '',0 + +;const char * () +align 4 +proc zlibVersion + mov eax,ZLIB_VERSION; + ret +endp + +;uLong () +align 4 +proc zlibCompileFlags +; uLong flags; + +; flags = 0; +; switch ((int)(sizeof(uInt))) { +; case 2: break; +; case 4: flags += 1; break; +; case 8: flags += 2; break; +; default: flags += 3; +; } +; switch ((int)(sizeof(uLong))) { +; case 2: break; +; case 4: flags += 1 << 2; break; +; case 8: flags += 2 << 2; break; +; default: flags += 3 << 2; +; } +; switch ((int)(sizeof(voidpf))) { +; case 2: break; +; case 4: flags += 1 << 4; break; +; case 8: flags += 2 << 4; break; +; default: flags += 3 << 4; +; } +; switch ((int)(sizeof(z_off_t))) { +; case 2: break; +; case 4: flags += 1 << 6; break; +; case 8: flags += 2 << 6; break; +; default: flags += 3 << 6; +; } +;if DEBUG +; flags += 1 << 8; +;end if +;#if defined(ASMV) || defined(ASMINF) +; flags += 1 << 9; +;end if +if ZLIB_WINAPI eq 1 +; flags += 1 << 10; +end if +if BUILDFIXED eq 1 +; flags += 1 << 12; +end if +if DYNAMIC_CRC_TABLE eq 1 +; flags += 1 << 13; +end if +if NO_GZCOMPRESS eq 1 +; flags += 1L << 16; +end if +if NO_GZIP eq 1 +; flags += 1L << 17; +end if +if PKZIP_BUG_WORKAROUND eq 1 +; flags += 1L << 20; +end if +if FASTEST eq 1 +; flags += 1L << 21; +end if +;#if defined(STDC) || defined(Z_HAVE_STDARG_H) +;# ifdef NO_vsnprintf +; flags += 1L << 25; +;# ifdef HAS_vsprintf_void +; flags += 1L << 26; +;# endif +;# else +;# ifdef HAS_vsnprintf_void +; flags += 1L << 26; +;# endif +;# endif +;#else +; flags += 1L << 24; +;# ifdef NO_snprintf +; flags += 1L << 25; +;# ifdef HAS_sprintf_void +; flags += 1L << 26; +;# endif +;# else +;# ifdef HAS_snprintf_void +; flags += 1L << 26; +;# endif +;# endif +;end if +; return flags; + ret +endp + +;if DEBUG + +;# define verbose 0 +;int z_verbose = verbose; + +;void (m) +; char *m; +align 4 +proc z_error, m:dword +; fprintf(stderr, "%s\n", m); +; exit(1); + ret +endp +;end if + +; exported to allow conversion of error code to string for compress() and +; uncompress() + +;const char * (err) +; int err; +align 4 +proc zError, err:dword +; return ERR_MSG(err); + ret +endp + +;#ifndef HAVE_MEMCPY + +;void (dest, source, len) +; Bytef* dest; +; const Bytef* source; +; uInt len; +align 4 +proc zmemcpy uses ecx edi esi, dest:dword, source:dword, len:dword + mov ecx,[len] + cmp ecx,0 + jle @f + mov edi,[dest] + mov esi,[source] + rep movsb + jmp .end0 + @@: +zlib_debug 'zmemcpy size = %d',ecx + .end0: + ret +endp + +;int (s1, s2, len) +; const Bytef* s1; +; const Bytef* s2; +; uInt len; +align 4 +proc zmemcmp, s1:dword, s2:dword, len:dword +; uInt j; + +; for (j = 0; j < len; j++) { +; if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; +; } +; return 0; + ret +endp + +;void (dest, len) +; Bytef* dest; +; uInt len; +align 4 +proc zmemzero, dest:dword, len:dword +; if (len == 0) return; +; do { +; *dest++ = 0; /* ??? to be unrolled */ +; } while (--len != 0); + ret +endp +;end if + +;#ifndef Z_SOLO + +;voidpf (voidpf opaque, unsigned items, unsigned size) +align 4 +proc zcalloc uses ebx ecx, opaque:dword, items:dword, size:dword + mov ecx,[size] + imul ecx,[items] + mcall SF_SYS_MISC, SSF_MEM_ALLOC + ret +endp + +;void (voidpf opaque, voidpf ptr) +align 4 +proc zcfree uses eax ebx ecx, opaque:dword, p2ptr:dword + mcall SF_SYS_MISC, SSF_MEM_FREE, [p2ptr] + ret +endp + +;end if /* !Z_SOLO */ diff --git a/programs/fs/kfar/trunk/zlib/zutil.inc b/programs/fs/kfar/trunk/zlib/zutil.inc new file mode 100644 index 0000000000..4e0bf7056f --- /dev/null +++ b/programs/fs/kfar/trunk/zlib/zutil.inc @@ -0,0 +1,88 @@ +; zutil.inc -- internal interface and configuration of the compression library +; Copyright (C) 1995-2013 Jean-loup Gailly. +; For conditions of distribution and use, see copyright notice in zlib.inc + +; WARNING: this file should *not* be used by applications. It is +; part of the implementation of the compression library and is +; subject to change. Applications should only use zlib.inc. + + +macro ERR_MSG err +{ + mov ecx,Z_NEED_DICT-err + mov ecx,[4*ecx+z_errmsg] +} + +macro ERR_RETURN strm,err +{ + ERR_MSG err + mov [strm+z_stream.msg],ecx + mov eax,err +} +; To be used only when the state is known to be valid + +; /* common constants */ + +;#ifndef DEF_WBITS +;# define DEF_WBITS MAX_WBITS +;end if +; default windowBits for decompression. MAX_WBITS is for compression only + +;#if MAX_MEM_LEVEL >= 8 +DEF_MEM_LEVEL equ 8 +;#else +;# define DEF_MEM_LEVEL MAX_MEM_LEVEL +;end if +; default memLevel + +STORED_BLOCK equ 0 +STATIC_TREES equ 1 +DYN_TREES equ 2 +; The three kinds of block type + +MIN_MATCH equ 3 +MAX_MATCH equ 258 +; The minimum and maximum match lengths + +PRESET_DICT equ 0x20 ;preset dictionary flag in zlib header + +; /* common defaults */ + +OS_CODE equ 0x03 ;assume Unix + +; /* functions */ + +; Diagnostic functions +;if DEBUG eq 1 +;# define Trace(x) {if (z_verbose>=0) fprintf x ;} +;# define Tracev(x) {if (z_verbose>0) fprintf x ;} +macro Tracevv mes1, mes2 +{ + ;zlib_debug 'Tracevv = %d', mes1 +} +;# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +;# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +;end if + +macro ZALLOC strm, items, size +{ + stdcall dword[strm+z_stream.zalloc], [strm+z_stream.opaque], items, size +} +macro ZFREE strm, p2addr +{ + stdcall dword[strm+z_stream.zfree], dword[strm+z_stream.opaque], p2addr +} +macro TRY_FREE s, p +{ +local .end0 + cmp p,0 + je .end0 + ZFREE s, p + .end0: +} + +; Reverse the bytes in a 32-bit value +macro ZSWAP32 q +{ + bswap q +}