zlib 1.2.0.1
diff --git a/ChangeLog b/ChangeLog
index 6193e00..55c29c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 
-		ChangeLog file for zlib
+                ChangeLog file for zlib
+Changes in 1.2.0.1 (17 March 2003)
+- Add Z_RLE strategy for run-length encoding [Truta]
+    - When Z_RLE requested, restrict matches to distance one
+    - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
+- Correct FASTEST compilation to allow level == 0
+- Clean up what gets compiled for FASTEST
+- Incorporate changes to zconf.in.h [Vollant]
+    - Refine detection of Turbo C need for dummy returns
+    - Refine ZLIB_DLL compilation
+    - Include additional header file on VMS for off_t typedef
+- Try to use _vsnprintf where it supplants vsprintf [Vollant]
+- Add some casts in inffast.c
+- Enchance comments in zlib.h on what happens if the gzprintf() tries to
+  write more than 4095 bytes before compression
+- Remove unused state from inflateBackEnd()
+- Remove exit(0) from minigzip.c, example.c
+- Get rid of all those darn tabs
+- Add "check" target to Makefile.in that does the same thing as "test"
+- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
+- Update contrib/inflate86 [Anderson]
+- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
+- Add msdos and win32 directories with makefiles [Truta]
+- More additions and improvements to the FAQ
+
 Changes in 1.2.0 (9 March 2003)
 - New and improved inflate code
     - About 20% faster
@@ -236,13 +260,13 @@
 - added Makefile.nt (thanks to Stephen Williams)
 - added the unsupported "contrib" directory:
    contrib/asm386/ by Gilles Vollant <info@winimage.com>
-	386 asm code replacing longest_match().
+        386 asm code replacing longest_match().
    contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
         A C++ I/O streams interface to the zlib gz* functions
    contrib/iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
-	Another C++ I/O streams interface
+        Another C++ I/O streams interface
    contrib/untgz/  by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
-	A very simple tar.gz file extractor using zlib
+        A very simple tar.gz file extractor using zlib
    contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
         How to use compress(), uncompress() and the gz* functions from VB.
 - pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
@@ -269,7 +293,7 @@
 - add NEED_DUMMY_RETURN for Borland
 - use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
 - allow compilation with CC
-- defined STDC for OS/2 (David Charlap)	
+- defined STDC for OS/2 (David Charlap)
 - limit external names to 8 chars for MVS (Thomas Lund)
 - in minigzip.c, use static buffers only for 16-bit systems
 - fix suffix check for "minigzip -d foo.gz"
diff --git a/FAQ b/FAQ
index abf680c..2a8247c 100644
--- a/FAQ
+++ b/FAQ
@@ -1,5 +1,5 @@
 
-		Frequently Asked Questions about zlib
+                Frequently Asked Questions about zlib
 
 
 If your question is not there, please check the zlib home page 
@@ -90,13 +90,14 @@
     ./configure -s
     make
 
-14. Why does "make test" fail on Mac OS X?
+14. How do I install a shared zlib library on Unix?
 
-    Mac OS X already includes zlib as a shared library, and so -lz links the
-    shared library instead of the one that the "make" compiled. The two are
-    incompatible due to different compile-time options. Simply change the -lz
-    in the Makefile to libz.a, and it will use the compiled library instead
-    of the shared one and the "make test" will succeed.
+    make install
+
+    However, many flavors of Unix come with a shared zlib already installed.
+    Before going to the trouble of compiling a shared version of zlib and
+    trying to install it, you may want to check if it's already there! If you
+    can #include <zlib.h>, it's there. The -lz option will probably link to it.
 
 15. I have a question about OttoPDF
 
@@ -108,8 +109,8 @@
     The compress and deflate functions produce data in the zlib format, which
     is different and incompatible with the gzip format. The gz* functions in
     zlib on the other hand use the gzip format. Both the zlib and gzip
-    formats use the same compressed data format, but have different headers
-    and trailers.
+    formats use the same compressed data format internally, but have different
+    headers and trailers around the compressed data.
 
 17. Ok, so why are there two different formats?
 
@@ -127,12 +128,13 @@
 19. Is zlib thread-safe?
 
     Yes. However any library routines that zlib uses and any application-
-    provided memory allocation routines must also be thread-safe. Of course,
-    you should only operate on any given zlib or gzip stream from a single
-    thread. zlib's gz* functions use stdio library routines, and most of
-    zlib's functions use the library memory allocation routines by default.
-    zlib's Init functions allow for the application to provide custom memory
-    allocation routines.
+    provided memory allocation routines must also be thread-safe. zlib's gz*
+    functions use stdio library routines, and most of zlib's functions use the
+    library memory allocation routines by default. zlib's Init functions allow
+    for the application to provide custom memory allocation routines.
+
+    Of course, you should only operate on any given zlib or gzip stream from a
+    single thread at a time.
 
 20. Can I use zlib in my commercial application?
 
@@ -142,24 +144,44 @@
 
     No. Please read the license in zlib.h.
 
-22. Will zlib work on a big-endian or little-endian architecture, and can I
+22. The license says that altered source versions must be "plainly marked". So
+    what exactly do I need to do to meet that requirement?
+
+    You need to append something the ZLIB_VERSION string in zlib.h. For
+    example, if the version of the base zlib you are altering is "1.2.3", then
+    you could change the string to "1.2.3-fred-mods-v3". You should not change
+    it to "1.2.4" or "1.2.3.1" since the zlib authors would like to reserve
+    those forms of the version for their own use.
+
+    For altered source distributions, you should also note the origin and
+    nature of the changes in zlib.h, as well as in ChangeLog and README, along
+    with the dates of the alterations. The origin should include at least your
+    name (or your company's name), and an email address to contact for help or
+    issues with the library.
+
+    Note that distributing a compiled zlib library along with zlib.h and
+    zconf.h is also a source distribution, and so you should change
+    ZLIB_VERSION and note the origin and nature of the changes in zlib.h as you
+    would for a full source distribution.
+
+23. Will zlib work on a big-endian or little-endian architecture, and can I
     exchange compressed data between them?
 
     Yes and yes.
 
-23. Will zlib work on a 64-bit machine?
+24. Will zlib work on a 64-bit machine?
 
     It should. It has been tested on 64-bit machines, and has no dependence
     on any data types being limited to 32-bits in length. If you have any
     difficulties, please provide a complete problem report to zlib@gzip.org
 
-24. Will zlib decompress data from the PKWare Data Compression Library?
+25. Will zlib decompress data from the PKWare Data Compression Library?
 
     No. The PKWare DCL uses a completely different compressed data format
     than does PKZIP and zlib. However, you can look in zlib's contrib/blast
     directory for a possible solution to your problem.
 
-25. Can I access data randomly in a compressed stream?
+26. Can I access data randomly in a compressed stream?
 
     No, not without some preparation. If when compressing you periodically
     use Z_FULL_FLUSH, carefully write all the pending data at those points,
@@ -167,76 +189,83 @@
     at those points. You have to be careful to not use Z_FULL_FLUSH too
     often, since it can significantly degrade compression.
 
-26. Does zlib work on MVS, OS/390, CICS, etc.?
+27. Does zlib work on MVS, OS/390, CICS, etc.?
 
     We don't know for sure. We have heard occasional reports of success on
     these systems. If you do use it on one of these, please provide us with
     a report, instructions, and patches that we can reference when we get
     these questions. Thanks.
 
-27. Is there some simpler, easier to read version of inflate I can look at
+28. Is there some simpler, easier to read version of inflate I can look at
     to understand the deflate format?
 
     First off, you should read RFC 1951. Second, yes. Look in zlib's
     contrib/puff directory.
 
-28. Does zlib infringe on any patents?
+29. Does zlib infringe on any patents?
 
     As far as we know, no. In fact, that was originally the whole point behind
     zlib. Look here for some more information:
 
     http://www.gzip.org/#faq11
 
-29. Can zlib work with greater than 4 GB of data?
+30. Can zlib work with greater than 4 GB of data?
 
     Yes. inflate() and deflate() will process any amount of data correctly.
     However the strm.total_in and strm_total_out counters may be limited to
-    4 GB. The user can easily set up their own counters updated after each
+    4 GB. The application can easily set up its own counters updated after each
     call of inflate() or deflate() to count beyond 4 GB. compress() and
-    uncompress() may be limited to 4 GB, since they operate in a single
-    call using unsigned long lengths. gzseek() may be limited to 4 GB
+    uncompress() may be limited to 4 GB, since they operate in a single call
+    using unsigned long lengths. gzseek() and gztell() may be limited to 4 GB
     depending on how zlib is compiled.
 
-30. Does zlib have any security vulnerabilities?
+31. Does zlib have any security vulnerabilities?
 
     The only one that we are aware of is potentially in gzprintf(). If zlib
     is compiled to use sprintf() or vsprintf(), then there is no protection
     against a buffer overflow of a 4K string space, other than the caller of
     gzprintf() assuring that the output will not exceed 4K. On the other
-    hand, if zlib is compiled to use snprintf() or vsnprintf(), then there is
-    no vulnerability.
+    hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
+    normally be the case, then there is no vulnerability. The ./configure
+    script will display warnings if an insecure variation of sprintf() will
+    be used by gzprintf().
+
+    If you don't have snprintf() or vsnprintf() and would like one, you can
+    find a portable implementation here:
+
+        http://www.ijs.si/software/snprintf/
 
     Note that you should be using the most recent version of zlib. Versions
     1.1.3 and before were subject to a double-free vulnerability.
 
-31. Is there a Java version of zlib?
+32. Is there a Java version of zlib?
 
     Probably what you want is to use zlib in Java. zlib is already included
     as part of the Java SDK in the java.util.zip class. If you really want
     a version of zlib written in the Java language, look on the zlib home
     page for links: http://www.zlib.org/
 
-32. I get this or that compiler or source-code scanner warning. Can't you guys
-    write proper code?
+33. I get this or that compiler or source-code scanner warning when I crank it
+    up to maximally-pendantic. Can't you guys write proper code?
 
     Many years ago, we gave up attempting to avoid warnings on every compiler
     in the universe. It just got to be a waste of time, and some compilers
     were downright silly. So now, we simply make sure that the code always
     works.
 
-33. Will zlib read the (insert any ancient or arcane format here) compressed
+34. Will zlib read the (insert any ancient or arcane format here) compressed
     data format?
 
     Probably not. Look in the comp.compression FAQ for pointers to various
     formats and associated software.
 
-34. How can I encrypt/decrypt zip files with zlib?
+35. How can I encrypt/decrypt zip files with zlib?
 
     zlib doesn't support encryption. PKZIP encryption is very weak and can be
     broken with freely available programs. To get strong encryption, use gpg
     which already includes zlib compression.
 
-35. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+36. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
 
     "gzip" is the gzip format, and "deflate" is the zlib format. They should
     probably have called the second one "zlib" instead to avoid confusion
@@ -250,14 +279,14 @@
     for), using the "gzip" transfer encoding is probably more reliable due to
     an unfortunate choice of name on the part of the HTTP 1.1 authors.
 
-36. Does zlib support the new "Deflate64" format introduced by PKWare?
+37. Does zlib support the new "Deflate64" format introduced by PKWare?
 
     No. PKWare has apparently decided to keep that format proprietary, since
     they have not documented it as they have previous compression formats.
     In any case, the compression improvements are so modest compared to other
     more modern approaches, that it's not worth the effort to implement.
 
-37. Can you please sign these lengthy legal documents and fax them back to us
+38. Can you please sign these lengthy legal documents and fax them back to us
     so that we can use your software in our product?
 
-    No.
+    No. Go away.
diff --git a/INDEX b/INDEX
index 87df959..a1463ce 100644
--- a/INDEX
+++ b/INDEX
@@ -1,22 +1,24 @@
-ChangeLog		history of changes
-FAQ			Frequently Asked Questions about zlib
-INDEX			this file
-Makefile		makefile for Unix (generated by configure)
-Makefile.in		makefile for Unix (template for configure)
-README			guess what
-algorithm.txt		description of the (de)compression algorithm
-configure		configure script for Unix
-zconf.in.h		template for zconf.h (used by configure)
+ChangeLog       history of changes
+FAQ             Frequently Asked Questions about zlib
+INDEX           this file
+Makefile        makefile for Unix (generated by configure)
+Makefile.in     makefile for Unix (template for configure)
+README          guess what
+algorithm.txt   description of the (de)compression algorithm
+configure       configure script for Unix
+zconf.in.h      template for zconf.h (used by configure)
 
-aix/			instructions for building an AIX shared library
-old/			makefiles for various architectures and zlib documentation
-			that has not yet been updated for zlib 1.2.x
+aix/            instructions for building an AIX shared library
+msdos/		makefiles for MSDOS
+old/            makefiles for various architectures and zlib documentation
+                files that have not yet been updated for zlib 1.2.x
+win32/		makefiles for Windows
 
-		zlib public header files (must be kept):
+                zlib public header files (must be kept):
 zconf.h
 zlib.h
 
-		private source files used to build the zlib library:
+                private source files used to build the zlib library:
 adler32.c
 compress.c
 crc32.c
@@ -38,9 +40,9 @@
 zutil.c
 zutil.h
 
-		source files for sample programs:
+                source files for sample programs:
 example.c
 minigzip.c
 
-		unsupported contribution by third parties
+                unsupported contribution by third parties
 See contrib/README.contrib
diff --git a/Makefile b/Makefile
index 087e388..05540e9 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@
 LDSHARED=$(CC)
 CPP=$(CC) -E
 
-VER=1.2.0
+VER=1.2.0.1
 LIBS=libz.a
 SHAREDLIB=libz.so
 
@@ -61,6 +61,7 @@
 
 all: example minigzip
 
+check: test
 test: all
 	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
 	echo hello world | ./minigzip | ./minigzip -d || \
@@ -123,10 +124,12 @@
 	  rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
 	fi
 
+mostlyclean: clean
 clean:
 	rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \
 	   _match.s maketree
 
+maintainer-clean: distclean
 distclean:	clean
 	cp -p Makefile.in Makefile
 	cp -p zconf.in.h zconf.h
diff --git a/Makefile.in b/Makefile.in
index 087e388..05540e9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -24,7 +24,7 @@
 LDSHARED=$(CC)
 CPP=$(CC) -E
 
-VER=1.2.0
+VER=1.2.0.1
 LIBS=libz.a
 SHAREDLIB=libz.so
 
@@ -61,6 +61,7 @@
 
 all: example minigzip
 
+check: test
 test: all
 	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
 	echo hello world | ./minigzip | ./minigzip -d || \
@@ -123,10 +124,12 @@
 	  rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
 	fi
 
+mostlyclean: clean
 clean:
 	rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \
 	   _match.s maketree
 
+maintainer-clean: distclean
 distclean:	clean
 	cp -p Makefile.in Makefile
 	cp -p zconf.in.h zconf.h
diff --git a/README b/README
index 26ab2b6..8ac79a1 100644
--- a/README
+++ b/README
@@ -1,38 +1,40 @@
-zlib 1.2.0 is a general purpose data compression library.  All the code
-is thread safe.  The data format used by the zlib library
-is described by RFCs (Request for Comments) 1950 to 1952 in the files 
-http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
-format) and rfc1952.txt (gzip format). These documents are also available in
-other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.0.1 is a general purpose data compression library.  All the code is
+thread safe.  The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format). These documents are also available in other
+formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
 
 All functions of the compression library are documented in the file zlib.h
-(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
-example of the library is given in the file example.c which also tests that
-the library is working correctly. Another example is given in the file
-minigzip.c. The compression library itself is composed of all source files
-except example.c and minigzip.c.
+(volunteer to write man pages welcome, contact jloup@gzip.org). A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly. Another example is given in the file minigzip.c. The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
 
-To compile all files and run the test program, follow the instructions
-given at the top of Makefile. In short "make test; make install"
-should work for most machines. For Unix: "./configure; make test; make install"
-For MSDOS, use one of the special makefiles such as Makefile.msc.
-For VMS, use Make_vms.com or descrip.mms.
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile. In short "make test; make install" should work for most
+machines. For Unix: "./configure; make test; make install" For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or
+descrip.mms.
 
-Questions about zlib should be sent to <zlib@gzip.org>, or to
-Gilles Vollant <info@winimage.com> for the Windows DLL version.
-The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/
-Before reporting a problem, please check this site to verify that
-you have the latest version of zlib; otherwise get the latest version and
-check whether the problem still exists or not.
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version. The zlib home page is
+http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
+please check this site to verify that you have the latest version of zlib;
+otherwise get the latest version and check whether the problem still exists or
+not.
 
-PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html
-before asking for help.
+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
+for help.
 
 Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
 issue of  Dr. Dobb's Journal; a copy of the article is available in
 http://dogma.net/markn/articles/zlibtool/zlibtool.htm
 
-The changes made in version 1.2.0 are documented in the file ChangeLog.
+The changes made in version 1.2.0.1 are documented in the file ChangeLog.
 
 Unsupported third party contributions are provided in directory "contrib".
 
@@ -40,56 +42,56 @@
 http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
 See the zlib home page http://www.zlib.org for details.
 
-A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org>
-is in the CPAN (Comprehensive Perl Archive Network) sites
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
+CPAN (Comprehensive Perl Archive Network) sites
 http://www.cpan.org/modules/by-module/Compress/
 
-A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
-is available in Python 1.5 and later versions, see
+A Python interface to zlib written by A.M. Kuchling <amk@magnet.com> is
+available in Python 1.5 and later versions, see
 http://www.python.org/doc/lib/module-zlib.html
 
-A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
-is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
+A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
+availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
 
-An experimental package to read and write files in .zip format,
-written on top of zlib by Gilles Vollant <info@winimage.com>, is
-available at http://www.winimage.com/zLibDll/unzip.html
-and also in the contrib/minizip directory of zlib.
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available at
+http://www.winimage.com/zLibDll/unzip.html and also in the contrib/minizip
+directory of zlib.
 
 
 Notes for some targets:
 
 - To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
-  and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
-  The zlib DLL support was initially done by Alessandro Iacopetti and is
-  now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
-  home page at http://www.winimage.com/zLibDll
+  and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL The
+  zlib DLL support was initially done by Alessandro Iacopetti and is now
+  maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL home
+  page at http://www.winimage.com/zLibDll
 
-  From Visual Basic, you can call the DLL functions which do not take
-  a structure as argument: compress, uncompress and all gz* functions.
-  See contrib/visual-basic.txt for more information, or get
+  From Visual Basic, you can call the DLL functions which do not take a
+  structure as argument: compress, uncompress and all gz* functions. See
+  contrib/visual-basic.txt for more information, or get
   http://www.tcfb.com/dowseware/cmp-z-it.zip
 
-- For 64-bit Irix, deflate.c must be compiled without any optimization.
-  With -O, one libpng test fails. The test works in 32 bit mode (with
-  the -n32 compiler flag). The compiler bug has been reported to SGI.
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+  compiler flag). The compiler bug has been reported to SGI.
 
-- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1   
-  it works when compiled with cc.
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+  when compiled with cc.
 
-- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
-  is necessary to get gzprintf working correctly. This is done by configure.
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+  necessary to get gzprintf working correctly. This is done by configure.
 
-- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
-  with other compilers. Use "make test" to check your compiler.
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+  other compilers. Use "make test" to check your compiler.
 
 - gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
 
 - For Turbo C the small model is supported only with reduced performance to
   avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
 
-- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
-  Per Harald Myrvang <perm@stud.cs.uit.no>
+- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html Per
+  Harald Myrvang <perm@stud.cs.uit.no>
 
 
 Acknowledgments:
@@ -129,4 +131,6 @@
 include third-party code.
 
 If you redistribute modified sources, we would appreciate that you include
-in the file ChangeLog history information documenting your changes.
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
diff --git a/adler32.c b/adler32.c
index 319603c..28c65ba 100644
--- a/adler32.c
+++ b/adler32.c
@@ -34,12 +34,12 @@
         len -= k;
         while (k >= 16) {
             DO16(buf);
-	    buf += 16;
+            buf += 16;
             k -= 16;
         }
         if (k != 0) do {
             s1 += *buf++;
-	    s2 += s1;
+            s2 += s1;
         } while (--k);
         s1 %= BASE;
         s2 %= BASE;
diff --git a/contrib/README.contrib b/contrib/README.contrib
index fcee020..3579d43 100644
--- a/contrib/README.contrib
+++ b/contrib/README.contrib
@@ -12,7 +12,7 @@
         See http://www.muppetlabs.com/~breadbox/software/assembly.html
 
 blast/      by Mark Adler <madler@alumni.caltech.edu>
-	Decompressor for output of PKWare Data Compression Library
+	Decompressor for output of PKWare Data Compression Library (DCL)
 
 delphi/     by Bob Dellaca <bobdl@xtra.co.nz>
 	Support for Delphi
@@ -33,8 +33,15 @@
 iostream2/  by Tyge Løvset <Tyge.Lovset@cmr.no>
 	Another C++ I/O streams interface
 
+testzlib/    by Gilles Vollant <info@winimage.com>
+	Example of the use of zlib
+
 untgz/      by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
 	A very simple tar.gz file extractor using zlib
 
 visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
         How to use compress(), uncompress() and the gz* functions from VB.
+
+vstudio/    by Gilles Vollant <info@winimage.com>
+	Building zlib DLL with Visual Studio .NET
+	Includes x86 inffast.asm for MASM
diff --git a/contrib/inflate86/inffas86.c b/contrib/inflate86/inffas86.c
new file mode 100644
index 0000000..4534693
--- /dev/null
+++ b/contrib/inflate86/inffas86.c
@@ -0,0 +1,783 @@
+/* inffas86.c is a hand tuned assembler version of
+ *
+ * inffast.c -- fast decoding
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+ * Please use the copyright conditions above.
+ *
+ * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
+ * the gcc -S output of zlib-1.2.0/inffast.c.  Zlib-1.2.0 is in beta release at
+ * the moment.  I have successfully compiled and tested this code with gcc2.96,
+ * gcc3.2, icc5.0, msvc6.0.  It is very close to the speed of inffast.S
+ * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
+ * enabled.  I will attempt to merge the MMX code into this version.  Newer
+ * versions of this and inffast.S can be found at
+ * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* Mark Adler's comments from inffast.c: */
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    struct inffast_ar {
+      void *esp;                  /* esp save */
+      unsigned char FAR *in;      /* local strm->next_in */
+      unsigned char FAR *last;    /* while in < last, enough input available */
+      unsigned char FAR *out;     /* local strm->next_out */
+      unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+      unsigned char FAR *end;     /* while out < end, enough space available */
+      unsigned wsize;             /* window size or zero if not using window */
+      unsigned write;             /* window write index */
+      unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+      unsigned long hold;         /* local strm->hold */
+      unsigned bits;              /* local strm->bits */
+      code const FAR *lcode;      /* local strm->lencode */
+      code const FAR *dcode;      /* local strm->distcode */
+      unsigned lmask;             /* mask for first level of length codes */
+      unsigned dmask;             /* mask for first level of distance codes */
+      unsigned len;               /* match length, unused bytes */
+      unsigned dist;              /* match distance */
+      unsigned status;            /* this is set when state changes */
+    } ar;
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    ar.in = strm->next_in;
+    ar.last = ar.in + (strm->avail_in - 5);
+    ar.out = strm->next_out;
+    ar.beg = ar.out - (start - strm->avail_out);
+    ar.end = ar.out + (strm->avail_out - 257);
+    ar.wsize = state->wsize;
+    ar.write = state->write;
+    ar.window = state->window;
+    ar.hold = state->hold;
+    ar.bits = state->bits;
+    ar.lcode = state->lencode;
+    ar.dcode = state->distcode;
+    ar.lmask = (1U << state->lenbits) - 1;
+    ar.dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+
+    /* align in on 2 byte boundary */
+    if (((unsigned long)(void *)ar.in & 0x1) != 0) {
+        ar.hold += (unsigned long)*ar.in++ << ar.bits;
+        ar.bits += 8;
+    }
+
+#if defined( __GNUC__ ) || defined( __ICC )
+    __asm__ __volatile__ (
+"        leal    %0, %%eax\n"
+"        pushf\n"
+"        pushl   %%ebp\n"
+"        movl    %%esp, (%%eax)\n"
+"        movl    %%eax, %%esp\n"
+"        movl    4(%%esp), %%esi\n"       /* esi = in */
+"        movl    12(%%esp), %%edi\n"      /* edi = out */
+"        movl    36(%%esp), %%edx\n"      /* edx = hold */
+"        movl    40(%%esp), %%ebx\n"      /* ebx = bits */
+"        movl    44(%%esp), %%ebp\n"      /* ebp = lcode */
+
+"        cld\n"
+"        jmp     .L_do_loop\n"
+
+".L_while_test:\n"
+"        cmpl    %%edi, 20(%%esp)\n"
+"        jbe     .L_break_loop\n"
+"        cmpl    %%esi, 8(%%esp)\n"
+"        jbe     .L_break_loop\n"
+
+".L_do_loop:\n"
+"        cmpb    $15, %%bl\n"
+"        ja      .L_get_length_code\n"    /* if (15 < bits) */
+
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
+
+".L_get_length_code:\n"
+"        movl    52(%%esp), %%eax\n"      /* eax = lmask */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */
+
+".L_dolen:\n"
+"        movb    %%ah, %%cl\n"            /* cl = this.bits */
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
+
+"        testb   %%al, %%al\n"
+"        jnz     .L_test_for_length_base\n" /* if (op != 0) 45.7% */
+
+"        shrl    $16, %%eax\n"            /* output this.val char */
+"        stosb\n"
+"        jmp     .L_while_test\n"
+
+".L_test_for_length_base:\n"
+"        movl    %%eax, %%ecx\n"          /* len = this */
+"        shrl    $16, %%ecx\n"            /* len = this.val */
+"        movl    %%ecx, 60(%%esp)\n"      /* len = this */
+"        movb    %%al, %%cl\n"
+
+"        testb   $16, %%al\n"
+"        jz      .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_decode_distance\n"    /* if (!op) */
+"        cmpb    %%cl, %%bl\n"
+"        jae     .L_add_bits_to_len\n"    /* if (op <= bits) */
+
+"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
+"        movb    %%ch, %%cl\n"            /* move op back to ecx */
+
+".L_add_bits_to_len:\n"
+"        movl    $1, %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        subb    %%cl, %%bl\n"
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrl    %%cl, %%edx\n"
+"        addl    %%eax, 60(%%esp)\n"      /* len += hold & mask[op] */
+
+".L_decode_distance:\n"
+"        cmpb    $15, %%bl\n"
+"        ja      .L_get_distance_code\n"  /* if (15 < bits) */
+
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"         /* hold |= *((ushort *)in)++ << bits */
+
+".L_get_distance_code:\n"
+"        movl    56(%%esp), %%eax\n"      /* eax = dmask */
+"        movl    48(%%esp), %%ecx\n"      /* ecx = dcode */
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        movl    (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */
+
+".L_dodist:\n"
+"        movl    %%eax, %%ebp\n"          /* dist = this */
+"        shrl    $16, %%ebp\n"            /* dist = this.val */
+"        movb    %%ah, %%cl\n"
+"        subb    %%ah, %%bl\n"            /* bits -= this.bits */
+"        shrl    %%cl, %%edx\n"           /* hold >>= this.bits */
+"        movb    %%al, %%cl\n"            /* cl = this.op */
+
+"        testb   $16, %%al\n"             /* if ((op & 16) == 0) */
+"        jz      .L_test_for_second_level_dist\n"
+"        andb    $15, %%cl\n"             /* op &= 15 */
+"        jz      .L_check_dist_one\n"
+"        cmpb    %%cl, %%bl\n"
+"        jae     .L_add_bits_to_dist\n"   /* if (op <= bits) 97.6% */
+
+"        movb    %%cl, %%ch\n"            /* stash op in ch, freeing cl */
+"        xorl    %%eax, %%eax\n"
+"        lodsw\n"                         /* al = *(ushort *)in++ */
+"        movb    %%bl, %%cl\n"            /* cl = bits, needs it for shifting */
+"        addb    $16, %%bl\n"             /* bits += 16 */
+"        shll    %%cl, %%eax\n"
+"        orl     %%eax, %%edx\n"        /* hold |= *((ushort *)in)++ << bits */
+"        movb    %%ch, %%cl\n"            /* move op back to ecx */
+
+".L_add_bits_to_dist:\n"
+"        movl    $1, %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"                 /* (1 << op) - 1 */
+"        subb    %%cl, %%bl\n"
+"        andl    %%edx, %%eax\n"          /* eax &= hold */
+"        shrl    %%cl, %%edx\n"
+"        addl    %%eax, %%ebp\n"          /* dist += hold & ((1 << op) - 1) */
+
+".L_check_window:\n"
+"        movl    %%esi, 4(%%esp)\n"       /* save in so from can use it's reg */
+"        movl    %%edi, %%eax\n"
+"        subl    16(%%esp), %%eax\n"      /* nbytes = out - beg */
+
+"        cmpl    %%ebp, %%eax\n"
+"        jb      .L_clip_window\n"        /* if (dist > nbytes) 4.2% */
+
+"        movl    60(%%esp), %%ecx\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"          /* from = out - dist */
+
+"        subl    $3, %%ecx\n"             /* copy from to out */
+"        movb    (%%esi), %%al\n"
+"        movb    %%al, (%%edi)\n"
+"        movb    1(%%esi), %%al\n"
+"        movb    2(%%esi), %%ah\n"
+"        addl    $3, %%esi\n"
+"        movb    %%al, 1(%%edi)\n"
+"        movb    %%ah, 2(%%edi)\n"
+"        addl    $3, %%edi\n"
+"        rep     movsb\n"
+
+"        movl    4(%%esp), %%esi\n"      /* move in back to %esi, toss from */
+"        movl    44(%%esp), %%ebp\n"     /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".L_check_dist_one:\n"
+"        cmpl    $1, %%ebp\n"            /* if dist 1, is a memset */
+"        jne     .L_check_window\n"
+"        cmpl    %%edi, 16(%%esp)\n"
+"        je      .L_check_window\n"
+
+"        decl    %%edi\n"
+"        movl    60(%%esp), %%ecx\n"
+"        movb    (%%edi), %%al\n"
+"        subl    $3, %%ecx\n"
+
+"        movb    %%al, 1(%%edi)\n"       /* memset out with from[-1] */
+"        movb    %%al, 2(%%edi)\n"
+"        movb    %%al, 3(%%edi)\n"
+"        addl    $4, %%edi\n"
+"        rep     stosb\n"
+"        movl    44(%%esp), %%ebp\n"      /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".L_test_for_second_level_length:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */
+
+"        movl    $1, %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    60(%%esp), %%eax\n"     /* eax += this.val */
+"        movl    (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/
+"        jmp     .L_dolen\n"
+
+".L_test_for_second_level_dist:\n"
+"        testb   $64, %%al\n"
+"        jnz     .L_invalid_distance_code\n" /* if ((op & 64) != 0) */
+
+"        movl    $1, %%eax\n"
+"        shll    %%cl, %%eax\n"
+"        decl    %%eax\n"
+"        andl    %%edx, %%eax\n"         /* eax &= hold */
+"        addl    %%ebp, %%eax\n"         /* eax += this.val */
+"        movl    48(%%esp), %%ecx\n"     /* ecx = dcode */
+"        movl    (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/
+"        jmp     .L_dodist\n"
+
+".L_clip_window:\n"
+"        movl    %%eax, %%ecx\n"
+"        movl    24(%%esp), %%eax\n"     /* prepare for dist compare */
+"        negl    %%ecx\n"                /* nbytes = -nbytes */
+"        movl    32(%%esp), %%esi\n"     /* from = window */
+
+"        cmpl    %%ebp, %%eax\n"
+"        jb      .L_invalid_distance_too_far\n" /* if (dist > wsize) */
+
+"        addl    %%ebp, %%ecx\n"         /* nbytes = dist - nbytes */
+"        cmpl    $0, 28(%%esp)\n"
+"        jne     .L_wrap_around_window\n" /* if (write != 0) */
+
+"        subl    %%ecx, %%eax\n"
+"        addl    %%eax, %%esi\n"         /* from += wsize - nbytes */
+
+"        movl    60(%%esp), %%eax\n"
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy1\n"
+
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy1\n"
+
+".L_wrap_around_window:\n"
+"        movl    28(%%esp), %%eax\n"
+"        cmpl    %%eax, %%ecx\n"
+"        jbe     .L_contiguous_in_window\n" /* if (write >= nbytes) */
+
+"        addl    24(%%esp), %%esi\n"
+"        addl    %%eax, %%esi\n"
+"        subl    %%ecx, %%esi\n"         /* from += wsize + write - nbytes */
+"        subl    %%eax, %%ecx\n"         /* nbytes -= write */
+
+"        movl    60(%%esp), %%eax\n"
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    32(%%esp), %%esi\n"     /* from = window */
+"        movl    28(%%esp), %%ecx\n"     /* nbytes = write */
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+"        jmp     .L_do_copy1\n"
+
+".L_contiguous_in_window:\n"
+"        addl    %%eax, %%esi\n"
+"        subl    %%ecx, %%esi\n"         /* from += write - nbytes */
+
+"        movl    60(%%esp), %%eax\n"
+"        cmpl    %%ecx, %%eax\n"
+"        jbe     .L_do_copy1\n"          /* if (nbytes >= len) */
+
+"        subl    %%ecx, %%eax\n"         /* len -= nbytes */
+"        rep     movsb\n"
+"        movl    %%edi, %%esi\n"
+"        subl    %%ebp, %%esi\n"         /* from = out - dist */
+
+".L_do_copy1:\n"
+"        movl    %%eax, %%ecx\n"
+"        rep     movsb\n"
+
+"        movl    4(%%esp), %%esi\n"      /* move in back to %esi, toss from */
+"        movl    44(%%esp), %%ebp\n"     /* ebp = lcode */
+"        jmp     .L_while_test\n"
+
+".L_test_for_end_of_block:\n"
+"        testb   $32, %%al\n"
+"        jz      .L_invalid_literal_length_code\n"
+"        movl    $1, 68(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_literal_length_code:\n"
+"        movl    $2, 68(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_code:\n"
+"        movl    $3, 68(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_invalid_distance_too_far:\n"
+"        movl    4(%%esp), %%esi\n"
+"        movl    $4, 68(%%esp)\n"
+"        jmp     .L_break_loop_with_status\n"
+
+".L_break_loop:\n"
+"        movl    $0, 68(%%esp)\n"
+
+".L_break_loop_with_status:\n"
+/* put in, out, bits, and hold back into ar and pop esp */
+"        movl    %%esi, 4(%%esp)\n"
+"        movl    %%edi, 12(%%esp)\n"
+"        movl    %%ebx, 40(%%esp)\n"
+"        movl    %%edx, 36(%%esp)\n"
+"        movl    (%%esp), %%esp\n"
+"        popl    %%ebp\n"
+"        popf\n"
+          :
+          : "m" (ar)
+          : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"
+    );
+#elif defined( _MSC_VER )
+    __asm {
+	lea	eax, ar
+	pushfd
+	push	ebp
+	mov	[eax], esp
+	mov	esp, eax
+	mov	esi, [esp+4]       /* esi = in */
+	mov	edi, [esp+12]      /* edi = out */
+	mov	edx, [esp+36]      /* edx = hold */
+	mov	ebx, [esp+40]      /* ebx = bits */
+	mov	ebp, [esp+44]      /* ebp = lcode */
+
+	cld
+	jmp	L_do_loop
+
+L_while_test:
+	cmp	[esp+20], edi
+	jbe	L_break_loop
+	cmp	[esp+8], esi
+	jbe	L_break_loop
+
+L_do_loop:
+	cmp	bl, 15
+	ja	L_get_length_code    /* if (15 < bits) */
+
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
+
+L_get_length_code:
+	mov	eax, [esp+52]      /* eax = lmask */
+	and	eax, edx          /* eax &= hold */
+	mov	eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */
+
+L_dolen:
+	mov	cl, ah            /* cl = this.bits */
+	sub	bl, ah            /* bits -= this.bits */
+	shr	edx, cl           /* hold >>= this.bits */
+
+	test	al, al
+	jnz	L_test_for_length_base /* if (op != 0) 45.7% */
+
+	shr	eax, 16            /* output this.val char */
+	stosb
+	jmp	L_while_test
+
+L_test_for_length_base:
+	mov	ecx, eax          /* len = this */
+	shr	ecx, 16            /* len = this.val */
+	mov	[esp+60], ecx      /* len = this */
+	mov	cl, al
+
+	test	al, 16
+	jz	L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
+	and	cl, 15             /* op &= 15 */
+	jz	L_decode_distance    /* if (!op) */
+	cmp	bl, cl
+	jae	L_add_bits_to_len    /* if (op <= bits) */
+
+	mov	ch, cl            /* stash op in ch, freeing cl */
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
+	mov	cl, ch            /* move op back to ecx */
+
+L_add_bits_to_len:
+	mov	eax, 1
+	shl	eax, cl
+	dec	eax
+	sub	bl, cl
+	and	eax, edx          /* eax &= hold */
+	shr	edx, cl
+	add	[esp+60], eax      /* len += hold & mask[op] */
+
+L_decode_distance:
+	cmp	bl, 15
+	ja	L_get_distance_code  /* if (15 < bits) */
+
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax         /* hold |= *((ushort *)in)++ << bits */
+
+L_get_distance_code:
+	mov	eax, [esp+56]      /* eax = dmask */
+	mov	ecx, [esp+48]      /* ecx = dcode */
+	and	eax, edx          /* eax &= hold */
+	mov	eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */
+
+L_dodist:
+	mov	ebp, eax          /* dist = this */
+	shr	ebp, 16            /* dist = this.val */
+	mov	cl, ah
+	sub	bl, ah            /* bits -= this.bits */
+	shr	edx, cl           /* hold >>= this.bits */
+	mov	cl, al            /* cl = this.op */
+
+	test	al, 16             /* if ((op & 16) == 0) */
+	jz	L_test_for_second_level_dist
+	and	cl, 15             /* op &= 15 */
+	jz	L_check_dist_one
+	cmp	bl, cl
+	jae	L_add_bits_to_dist   /* if (op <= bits) 97.6% */
+
+	mov	ch, cl            /* stash op in ch, freeing cl */
+	xor	eax, eax
+	lodsw                         /* al = *(ushort *)in++ */
+	mov	cl, bl            /* cl = bits, needs it for shifting */
+	add	bl, 16             /* bits += 16 */
+	shl	eax, cl
+	or	edx, eax        /* hold |= *((ushort *)in)++ << bits */
+	mov	cl, ch            /* move op back to ecx */
+
+L_add_bits_to_dist:
+	mov	eax, 1
+	shl	eax, cl
+	dec	eax                 /* (1 << op) - 1 */
+	sub	bl, cl
+	and	eax, edx          /* eax &= hold */
+	shr	edx, cl
+	add	ebp, eax          /* dist += hold & ((1 << op) - 1) */
+
+L_check_window:
+	mov	[esp+4], esi       /* save in so from can use it's reg */
+	mov	eax, edi
+	sub	eax, [esp+16]      /* nbytes = out - beg */
+
+	cmp	eax, ebp
+	jb	L_clip_window        /* if (dist > nbytes) 4.2% */
+
+	mov	ecx, [esp+60]
+	mov	esi, edi
+	sub	esi, ebp          /* from = out - dist */
+
+	sub	ecx, 3             /* copy from to out */
+	mov	al, [esi]
+	mov	[edi], al
+	mov	al, [esi+1]
+	mov	ah, [esi+2]
+	add	esi, 3
+	mov	[edi+1], al
+	mov	[edi+2], ah
+	add	edi, 3
+	rep     movsb
+
+	mov	esi, [esp+4]      /* move in back to %esi, toss from */
+	mov	ebp, [esp+44]     /* ebp = lcode */
+	jmp	L_while_test
+
+L_check_dist_one:
+	cmp	ebp, 1            /* if dist 1, is a memset */
+	jne	L_check_window
+	cmp	[esp+16], edi
+	je	L_check_window
+
+	dec	edi
+	mov	ecx, [esp+60]
+	mov	al, [edi]
+	sub	ecx, 3
+
+	mov	[edi+1], al       /* memset out with from[-1] */
+	mov	[edi+2], al
+	mov	[edi+3], al
+	add	edi, 4
+	rep     stosb
+	mov	ebp, [esp+44]      /* ebp = lcode */
+	jmp	L_while_test
+
+L_test_for_second_level_length:
+	test	al, 64
+	jnz	L_test_for_end_of_block /* if ((op & 64) != 0) */
+
+	mov	eax, 1
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         /* eax &= hold */
+	add	eax, [esp+60]     /* eax += this.val */
+	mov	eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/
+	jmp	L_dolen
+
+L_test_for_second_level_dist:
+	test	al, 64
+	jnz	L_invalid_distance_code /* if ((op & 64) != 0) */
+
+	mov	eax, 1
+	shl	eax, cl
+	dec	eax
+	and	eax, edx         /* eax &= hold */
+	add	eax, ebp         /* eax += this.val */
+	mov	ecx, [esp+48]     /* ecx = dcode */
+	mov	eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/
+	jmp	L_dodist
+
+L_clip_window:
+	mov	ecx, eax
+	mov	eax, [esp+24]     /* prepare for dist compare */
+	neg	ecx                /* nbytes = -nbytes */
+	mov	esi, [esp+32]     /* from = window */
+
+	cmp	eax, ebp
+	jb	L_invalid_distance_too_far /* if (dist > wsize) */
+
+	add	ecx, ebp         /* nbytes = dist - nbytes */
+	cmp	dword ptr [esp+28], 0
+	jne	L_wrap_around_window /* if (write != 0) */
+
+	sub	eax, ecx
+	add	esi, eax         /* from += wsize - nbytes */
+
+	mov	eax, [esp+60]
+	cmp	eax, ecx
+	jbe	L_do_copy1          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy1
+
+	cmp	eax, ecx
+	jbe	L_do_copy1          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy1
+
+L_wrap_around_window:
+	mov	eax, [esp+28]
+	cmp	ecx, eax
+	jbe	L_contiguous_in_window /* if (write >= nbytes) */
+
+	add	esi, [esp+24]
+	add	esi, eax
+	sub	esi, ecx         /* from += wsize + write - nbytes */
+	sub	ecx, eax         /* nbytes -= write */
+
+	mov	eax, [esp+60]
+	cmp	eax, ecx
+	jbe	L_do_copy1          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, [esp+32]     /* from = window */
+	mov	ecx, [esp+28]     /* nbytes = write */
+	cmp	eax, ecx
+	jbe	L_do_copy1          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+	jmp	L_do_copy1
+
+L_contiguous_in_window:
+	add	esi, eax
+	sub	esi, ecx         /* from += write - nbytes */
+
+	mov	eax, [esp+60]
+	cmp	eax, ecx
+	jbe	L_do_copy1          /* if (nbytes >= len) */
+
+	sub	eax, ecx         /* len -= nbytes */
+	rep     movsb
+	mov	esi, edi
+	sub	esi, ebp         /* from = out - dist */
+
+L_do_copy1:
+	mov	ecx, eax
+	rep     movsb
+
+	mov	esi, [esp+4]      /* move in back to %esi, toss from */
+	mov	ebp, [esp+44]     /* ebp = lcode */
+	jmp	L_while_test
+
+L_test_for_end_of_block:
+	test	al, 32
+	jz	L_invalid_literal_length_code
+	mov	dword ptr [esp+68], 1
+	jmp	L_break_loop_with_status
+
+L_invalid_literal_length_code:
+	mov	dword ptr [esp+68], 2
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_code:
+	mov	dword ptr [esp+68], 3
+	jmp	L_break_loop_with_status
+
+L_invalid_distance_too_far:
+	mov	esi, [esp+4]
+	mov	dword ptr [esp+68], 4
+	jmp	L_break_loop_with_status
+
+L_break_loop:
+	mov	dword ptr [esp+68], 0
+
+L_break_loop_with_status:
+/* put in, out, bits, and hold back into ar and pop esp */
+	mov	[esp+4], esi
+	mov	[esp+12], edi
+	mov	[esp+40], ebx
+	mov	[esp+36], edx
+	mov	esp, [esp]
+	pop	ebp
+	popfd
+    }
+#endif
+
+    if (ar.status > 1) {
+        if (ar.status == 2)
+            strm->msg = "invalid literal/length code";
+        else if (ar.status == 3)
+            strm->msg = "invalid distance code";
+        else
+            strm->msg = "invalid distance too far back";
+        state->mode = BAD;
+    }
+    else if ( ar.status == 1 ) {
+        state->mode = TYPE;
+    }
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    ar.len = ar.bits >> 3;
+    ar.in -= ar.len;
+    ar.bits -= ar.len << 3;
+    ar.hold &= (1U << ar.bits) - 1;
+
+    /* update state and return */
+    strm->next_in = ar.in;
+    strm->next_out = ar.out;
+    strm->avail_in = (unsigned)(ar.in < ar.last ? 5 + (ar.last - ar.in) :
+                                                  5 - (ar.in - ar.last));
+    strm->avail_out = (unsigned)(ar.out < ar.end ? 257 + (ar.end - ar.out) :
+                                                   257 - (ar.out - ar.end));
+    state->hold = ar.hold;
+    state->bits = ar.bits;
+    return;
+}
+
diff --git a/contrib/inflate86/inffast.S b/contrib/inflate86/inffast.S
index d1e80ef..3602907 100644
--- a/contrib/inflate86/inffast.S
+++ b/contrib/inflate86/inffast.S
@@ -1,1095 +1,1377 @@
-/*

- * inffast.S is a hand tuned assembler version of:

- *

- * inffast.c -- fast decoding

- * Copyright (C) 1995-2003 Mark Adler

- * For conditions of distribution and use, see copyright notice in zlib.h 

- *

- * Copyright (C) 2003 Chris Anderson <christop@charm.net>

- * Please use the copyright conditions above.

- * 

- * This version (Jan-23-2003) of inflate_fast was coded and tested under

- * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution.  On that

- * machine, I found that gzip style archives decompressed about 20% faster than

- * the gcc-3.2 -O3 -fomit-frame-pointer compiled version.  Your results will

- * depend on how large of a buffer is used for z_stream.next_in & next_out

- * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in

- * stream processing I/O and crc32/addler32.  In my case, this routine used

- * 70% of the cpu time and crc32 used 20%.

- *

- * I am confident that this version will work in the general case, but I have

- * not tested a wide variety of datasets or a wide variety of platforms.

- *

- * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating.

- * It should be a runtime flag instead of compile time flag...

- */

-

-.file "inffast.S"

-

-.globl inflate_fast

-

-.text

-.align 4,0

-.L_invalid_literal_length_code_msg:

-.string "invalid literal/length code"

-

-.align 4,0

-.L_invalid_distance_code_msg:

-.string "invalid distance code"

-

-.align 4,0

-.L_invalid_distance_too_far_msg:

-.string "invalid distance too far back"

-

-#if defined( USE_MMX )

-.align 4,0

-.L_mask: /* mask[N] = ( 1 << N ) - 1 */

-.long 0

-.long 1

-.long 3

-.long 7

-.long 15

-.long 31

-.long 63

-.long 127

-.long 255

-.long 511

-.long 1023

-.long 2047

-.long 4095

-.long 8191

-.long 16383

-.long 32767

-.long 65535

-.long 131071

-.long 262143

-.long 524287

-.long 1048575

-.long 2097151

-.long 4194303

-.long 8388607

-.long 16777215

-.long 33554431

-.long 67108863

-.long 134217727

-.long 268435455

-.long 536870911

-.long 1073741823

-.long 2147483647

-.long 4294967295

-#endif

-

-.text

-

-/*

- * struct z_stream offsets, in zlib.h

- */

-#define next_in_strm   0   /* strm->next_in */

-#define avail_in_strm  4   /* strm->avail_in */

-#define next_out_strm  12  /* strm->next_out */

-#define avail_out_strm 16  /* strm->avail_out */

-#define msg_strm       24  /* strm->msg */

-#define state_strm     28  /* strm->state */

-

-/*

- * struct inflate_state offsets, in inflate.h

- */

-#define mode_state     0   /* state->mode */

-#define wsize_state    32  /* state->wsize */

-#define write_state    36  /* state->write */

-#define window_state   40  /* state->window */

-#define hold_state     44  /* state->hold */

-#define bits_state     48  /* state->bits */

-#define lencode_state  64  /* state->lencode */

-#define distcode_state 68  /* state->distcode */

-#define lenbits_state  72  /* state->lenbits */

-#define distbits_state 76  /* state->distbits */

-

-/*

- * inflate_fast's activation record

- */

-#define local_var_size 56 /* how much local space for vars */

-#define strm_sp        80 /* first arg: z_stream * (local_var_size + 24) */

-#define start_sp       84 /* second arg: unsigned int (local_var_size + 28) */

-

-/*

- * offsets for local vars on stack

- */

-#define out            52  /* unsigned char* */

-#define window         48  /* unsigned char* */

-#define wsize          44  /* unsigned int */

-#define write          40  /* unsigned int */

-#define in             36  /* unsigned char* */

-#define beg            32  /* unsigned char* */

-#define dist           28  /* unsigned int */

-#define len            24  /* unsigned int */

-#define last           20  /* unsigned char* */

-#define end            16  /* unsigned char* */

-#define dcode          12  /* code* */

-#define lcode           8  /* code* */

-#define dmask           4  /* unsigned int */

-#define lmask           0  /* unsigned int */

-

-/*

- * typedef enum inflate_mode consts, in inflate.h

- */

-#ifndef NO_GUNZIP

-#define GUNZIP

-#endif

-

-#ifdef GUNZIP

-#define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */

-#define INFLATE_MODE_BAD  26

-#else

-#define INFLATE_MODE_TYPE 3

-#define INFLATE_MODE_BAD  17

-#endif

-

-

-.align 16,0x90

-inflate_fast:

-        pushl   %edi

-        pushl   %esi

-        pushl   %ebp

-        pushl   %ebx

-        pushf   /* save eflags (strm_sp, state_sp assumes this is 32 bits) */

-        subl    $local_var_size, %esp

-        cld

-#if defined( USE_MMX )

-        emms

-#endif

-

-#define strm_r  %esi

-#define state_r %edi

-

-        movl    strm_sp(%esp), strm_r

-        movl    state_strm(strm_r), state_r

-

-        /* in = strm->next_in;

-         * out = strm->next_out;

-         * last = in + strm->avail_in - 5;

-         * beg = out - (start - strm->avail_out);

-         * end = out + (strm->avail_out - 257);

-         */

-        movl    next_in_strm(strm_r), %eax

-        movl    next_out_strm(strm_r), %ebx

-        movl    avail_in_strm(strm_r), %edx

-        movl    avail_out_strm(strm_r), %ecx

-        movl    start_sp(%esp), %ebp

-

-        addl    %eax, %edx      /* avail_in += next_in */

-        subl    $5, %edx        /* avail_in -= 5 */

-

-        subl    %ecx, %ebp      /* start -= avail_out */

-        negl    %ebp            /* start = -start */

-        addl    %ebx, %ebp      /* start += next_out */

-

-        subl    $257, %ecx      /* avail_out -= 257 */

-        addl    %ebx, %ecx      /* avail_out += out */

-

-        movl    %eax, in(%esp)

-        movl    %ebx, out(%esp)

-        movl    %edx, last(%esp)

-        movl    %ebp, beg(%esp)

-        movl    %ecx, end(%esp)

-

-        /* wsize = state->wsize;

-         * write = state->write;

-         * window = state->window;

-         * hold = state->hold;

-         * bits = state->bits;

-         * lcode = state->lencode;

-         * dcode = state->distcode;

-         * lmask = ( 1 << state->lenbits ) - 1;

-         * dmask = ( 1 << state->distbits ) - 1;

-         */

-

-        movl    lencode_state(state_r), %eax

-        movl    distcode_state(state_r), %ecx

-

-        movl    %eax, lcode(%esp)

-        movl    %ecx, dcode(%esp)

-

-        movl    $1, %eax

-        movl    lenbits_state(state_r), %ecx

-        shll    %cl, %eax

-        decl    %eax

-        movl    %eax, lmask(%esp)

-

-        movl    $1, %eax

-        movl    distbits_state(state_r), %ecx

-        shll    %cl, %eax

-        decl    %eax

-        movl    %eax, dmask(%esp)

-

-        movl    wsize_state(state_r), %eax

-        movl    write_state(state_r), %ecx

-        movl    window_state(state_r), %edx

-

-        movl    %eax, wsize(%esp)

-        movl    %ecx, write(%esp)

-        movl    %edx, window(%esp)

-

-#if ! defined( USE_MMX )

-

-#define hold_r     %ebp

-#define bits_r     %bl

-#define bitslong_r %ebx

-

-        movl    hold_state(state_r), hold_r

-        movl    bits_state(state_r), bitslong_r

-

-#else /* USE_MMX */

-

-#define hold_mm    %mm0

-#define bits_r     %ebp

-#define bitslong_r %ebp

-

-        movl    hold_state(state_r), %ebx

-        movl    bits_state(state_r), bitslong_r

-

-#endif

-

-#undef strm_r

-#undef state_r

-#define in_r       %esi

-#define from_r     %esi

-#define out_r      %edi

-

-        movl    in(%esp), in_r

-

-#if ! defined ( USE_MMX )

-

-        /* align in_r on word boundary */

-        testl   $1, in_r

-        jz      .L_is_aligned

-        xorl    %eax, %eax

-        movb    (in_r), %al

-        incl    in_r

-        movb    bits_r, %cl

-        addb    $8, bits_r

-        shll    %cl, %eax

-        orl     %eax, hold_r

-

-#else

-        /* align in_r on long boundary */

-.L_align_long:

-        testl   $3, in_r

-        jz      .L_is_aligned

-        xorl    %eax, %eax

-        movb    (in_r), %al

-        incl    in_r

-        movl    bits_r, %ecx

-        addl    $8, bits_r

-        shll    %cl, %eax

-        orl     %eax, %ebx

-        jmp     .L_align_long

-

-#endif

-

-.L_is_aligned:

-        movl    out(%esp), out_r

-

-#if defined ( USE_MMX )

-

-#define used_mm   %mm1

-#define dmask2_mm %mm2

-#define lmask2_mm %mm3

-#define lmask_mm  %mm4

-#define dmask_mm  %mm5

-#define tmp_mm    %mm6

-

-        movl    out(%esp), out_r

-        movd    lmask(%esp), lmask_mm 

-        movq    lmask_mm, lmask2_mm

-        movd    dmask(%esp), dmask_mm

-        movq    dmask_mm, dmask2_mm

-        movd    %ebx, hold_mm

-        pxor    used_mm, used_mm

-        movl    lcode(%esp), %ebx       /* ebx = lcode */

-#endif

-

-        jmp     .L_do_loop

-

-.align 16,0x90

-

-#if ! defined ( USE_MMX )

-

-.L_do_loop:

-        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out

-         *

-         * do { 

-         *   if (bits < 15) {

-         *     hold |= *((unsigned short *)in)++ << bits;

-         *     bits += 16

-         *   }

-         *   this = lcode[hold & lmask]

-         */

-        cmpb    $15, bits_r

-        ja      .L_get_length_code      /* if (15 < bits) */

-

-        xorl    %eax, %eax

-        lodsw                           /* al = *(ushort *)in++ */

-        movb    bits_r, %cl             /* cl = bits, needs it for shifting */

-        addb    $16, bits_r             /* bits += 16 */

-        shll    %cl, %eax

-        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

-

-.L_get_length_code:

-        movl    lmask(%esp), %edx       /* edx = lmask */

-        movl    lcode(%esp), %ecx       /* ecx = lcode */

-        andl    hold_r, %edx            /* edx &= hold */

-        movl    (%ecx,%edx,4), %eax     /* eax = lcode[hold & lmask] */

-

-#else /* USE_MMX */

-

-.L_do_loop:

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-

-        cmpl    $32, bits_r

-        ja      .L_get_length_code      /* if (32 < bits) */

-

-        movd    bits_r, tmp_mm

-        movd    (in_r), %mm7

-        addl    $4, in_r

-        psllq   tmp_mm, %mm7

-        addl    $32, bits_r

-        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */

-

-.L_get_length_code:

-        pand    hold_mm, lmask_mm

-        movd    lmask_mm, %eax

-        movq    lmask2_mm, lmask_mm

-        movl    (%ebx,%eax,4), %eax     /* eax = lcode[hold & lmask] */

-

-#endif

-

-#if ! defined( USE_MMX )

-

-.L_dolen:

-        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out

-         *

-         * dolen:

-         *    bits -= this.bits;

-         *    hold >>= this.bits

-         */

-        movb    %ah, %cl                /* cl = this.bits */

-        subb    %ah, bits_r             /* bits -= this.bits */

-        shrl    %cl, hold_r             /* hold >>= this.bits */

-

-        /* check if op is a literal

-         * if (op == 0) {

-         *    PUP(out) = this.val;

-         *  }

-         */

-        testb   %al, %al

-        jnz     .L_test_for_length_base /* if (op != 0) 45.7% */

-

-        shrl    $16, %eax               /* output this.val char */

-        stosb

-

-#else /* USE_MMX */

-

-#define len_r  %edx

-

-.L_dolen:

-        movzbl  %ah, %ecx               /* ecx = this.bits */

-        movl    %eax, len_r             /* len = this */

-        shrl    $16, len_r              /* len = this.val */

-        movd    %ecx, used_mm

-        subl    %ecx, bits_r            /* bits -= this.bits */

-

-        testb   %al, %al

-        jnz     .L_test_for_length_base /* if (op != 0) 45.7% */

-

-        movb    %dl, (out_r)

-        incl    out_r

-

-#endif

-

-.L_while_test:

-        /* while (in < last && out < end)

-         */

-        cmpl    out_r, end(%esp)

-        jbe     .L_break_loop           /* if (out >= end) */

-

-        cmpl    in_r, last(%esp)

-        ja      .L_do_loop              /* if (in < last) */

-        jmp     .L_break_loop

-

-#if ! defined( USE_MMX )

-

-.L_test_for_length_base:

-        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len

-         *

-         * else if (op & 16) {

-         *   len = this.val

-         *   op &= 15

-         *   if (op) {

-         *     if (op > bits) {

-         *       hold |= *((unsigned short *)in)++ << bits;

-         *       bits += 16

-         *     }

-         *     len += hold & mask[op];

-         *     bits -= op;

-         *     hold >>= op;

-         *   }

-         */

-#define len_r %edx

-        movl    %eax, len_r             /* len = this */

-        shrl    $16, len_r              /* len = this.val */

-        movb    %al, %cl

-

-        testb   $16, %al

-        jz      .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */

-        andb    $15, %cl                /* op &= 15 */

-        jz      .L_save_len             /* if (!op) */

-        cmpb    %cl, bits_r

-        jae     .L_add_bits_to_len      /* if (op <= bits) */

-

-        movb    %cl, %ch                /* stash op in ch, freeing cl */

-        xorl    %eax, %eax

-        lodsw                           /* al = *(ushort *)in++ */

-        movb    bits_r, %cl             /* cl = bits, needs it for shifting */

-        addb    $16, bits_r             /* bits += 16 */

-        shll    %cl, %eax

-        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

-        movb    %ch, %cl                /* move op back to ecx */

-

-.L_add_bits_to_len:

-        movl    $1, %eax

-        shll    %cl, %eax

-        decl    %eax

-        subb    %cl, bits_r

-        andl    hold_r, %eax            /* eax &= hold */

-        shrl    %cl, hold_r

-        addl    %eax, len_r             /* len += hold & mask[op] */

-

-.L_save_len:

-        movl    len_r, len(%esp)        /* save len */

-#undef  len_r

-

-.L_decode_distance:

-        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *

-         *   if (bits < 15) {

-         *     hold |= *((unsigned short *)in)++ << bits;

-         *     bits += 16

-         *   }

-         *   this = dcode[hold & dmask];

-         * dodist:

-         *   bits -= this.bits;

-         *   hold >>= this.bits;

-         *   op = this.op;

-         */

-

-        cmpb    $15, bits_r

-        ja      .L_get_distance_code    /* if (15 < bits) */

-

-        xorl    %eax, %eax

-        lodsw                           /* al = *(ushort *)in++ */

-        movb    bits_r, %cl             /* cl = bits, needs it for shifting */

-        addb    $16, bits_r             /* bits += 16 */

-        shll    %cl, %eax

-        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

-

-.L_get_distance_code:

-        movl    dmask(%esp), %edx       /* edx = dmask */

-        movl    dcode(%esp), %ecx       /* ecx = dcode */

-        andl    hold_r, %edx            /* edx &= hold */

-        movl    (%ecx,%edx,4), %eax     /* eax = dcode[hold & dmask] */

-

-#else /* USE_MMX */

-

-.L_test_for_length_base:

-        testb   $16, %al

-        jz      .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */

-        andl    $15, %eax               /* op &= 15 */

-        jz      .L_decode_distance      /* if (!op) */

-

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-        movd    %eax, used_mm

-        movd    hold_mm, %ecx

-        subl    %eax, bits_r

-        andl    .L_mask(,%eax,4), %ecx

-        addl    %ecx, len_r             /* len += hold & mask[op] */

-

-.L_decode_distance:

-

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-

-        cmpl    $32, bits_r

-        ja      .L_get_dist_code        /* if (32 < bits) */

-

-        movd    bits_r, tmp_mm

-        movd    (in_r), %mm7

-        addl    $4, in_r

-        psllq   tmp_mm, %mm7

-        addl    $32, bits_r

-        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */

-

-.L_get_dist_code:

-        movl    dcode(%esp), %ebx       /* ebx = dcode */

-        pand    hold_mm, dmask_mm

-        movd    dmask_mm, %eax

-        movq    dmask2_mm, dmask_mm

-        movl    (%ebx,%eax,4), %eax     /* eax = dcode[hold & lmask] */

-

-#endif

-

-#if ! defined( USE_MMX )

-

-#define dist_r %edx

-.L_dodist:

-        movl    %eax, dist_r            /* dist = this */

-        shrl    $16, dist_r             /* dist = this.val */

-        movb    %ah, %cl

-        subb    %ah, bits_r             /* bits -= this.bits */

-        shrl    %cl, hold_r             /* hold >>= this.bits */

-

-        /* if (op & 16) {

-         *   dist = this.val

-         *   op &= 15

-         *   if (op > bits) {

-         *     hold |= *((unsigned short *)in)++ << bits;

-         *     bits += 16

-         *   }

-         *   dist += hold & mask[op];

-         *   bits -= op;

-         *   hold >>= op;

-         */

-        movb    %al, %cl                /* cl = this.op */

-

-        testb   $16, %al                /* if ((op & 16) == 0) */

-        jz      .L_test_for_second_level_dist

-        andb    $15, %cl                /* op &= 15 */

-        jz      .L_check_dist_one

-        cmpb    %cl, bits_r

-        jae     .L_add_bits_to_dist     /* if (op <= bits) 97.6% */

-

-        movb    %cl, %ch                /* stash op in ch, freeing cl */

-        xorl    %eax, %eax

-        lodsw                           /* al = *(ushort *)in++ */

-        movb    bits_r, %cl             /* cl = bits, needs it for shifting */

-        addb    $16, bits_r             /* bits += 16 */

-        shll    %cl, %eax

-        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */

-        movb    %ch, %cl                /* move op back to ecx */

-

-.L_add_bits_to_dist:

-        movl    $1, %eax

-        shll    %cl, %eax

-        decl    %eax                    /* (1 << op) - 1 */

-        subb    %cl, bits_r

-        andl    hold_r, %eax            /* eax &= hold */

-        shrl    %cl, hold_r

-        addl    %eax, dist_r            /* dist += hold & ((1 << op) - 1) */

-        jmp     .L_check_window

-

-#else /* USE_MMX */

-

-#define dist_r %ebx

-.L_dodist:

-        movzbl  %ah, %ecx               /* ecx = this.bits */

-        movl    %eax, dist_r

-        shrl    $16, dist_r             /* dist  = this.val */

-        subl    %ecx, bits_r            /* bits -= this.bits */

-        movd    %ecx, used_mm

-

-        testb   $16, %al                /* if ((op & 16) == 0) */

-        jz      .L_test_for_second_level_dist 

-        andl    $15, %eax               /* op &= 15 */

-        jz      .L_check_dist_one

-

-.L_add_bits_to_dist:

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-        movd    %eax, used_mm           /* save bit length of current op */

-        movd    hold_mm, %ecx           /* get the next bits on input stream */

-        subl    %eax, bits_r            /* bits -= op bits */

-        andl    .L_mask(,%eax,4), %ecx  /* ecx   = hold & mask[op] */

-        addl    %ecx, dist_r            /* dist += hold & mask[op] */

-        jmp     .L_check_window

-

-#endif

-

-.align 16,0x90

-

-.L_check_dist_one:

-        cmpl    $1, dist_r

-        jne     .L_check_window

-        cmpl    out_r, beg(%esp)

-        je      .L_check_window

-

-        decl    out_r

-#if ! defined( USE_MMX )

-        movl    len(%esp), %ecx

-#else

-        movl    len_r, %ecx

-#endif

-        movb    (out_r), %al

-        subl    $3, %ecx

-

-        movb    %al, 1(out_r)

-        movb    %al, 2(out_r)

-        movb    %al, 3(out_r)

-        addl    $4, out_r

-        rep     stosb

-

-#if defined( USE_MMX )

-        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */

-#endif

-        jmp     .L_while_test

-

-.align 16,0x90

-

-.L_check_window:

-        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *       %ecx = nbytes

-         *

-         * nbytes = out - beg;

-         * if (dist <= nbytes) {

-         *   from = out - dist;

-         *   do {

-         *     PUP(out) = PUP(from);

-         *   } while (--len > 0) {

-         * }

-         */

-

-        movl    in_r, in(%esp)          /* save in so from can use it's reg */

-        movl    out_r, %eax

-        subl    beg(%esp), %eax         /* nbytes = out - beg */

-

-        cmpl    dist_r, %eax

-        jb      .L_clip_window          /* if (dist > nbytes) 4.2% */

-

-#if ! defined( USE_MMX )

-        movl    len(%esp), %ecx

-#else

-        movl    len_r, %ecx

-#endif

-        movl    out_r, from_r

-        subl    dist_r, from_r          /* from = out - dist */

-

-        subl    $3, %ecx

-        movb    (from_r), %al

-        movb    %al, (out_r)

-        movb    1(from_r), %al

-        movb    2(from_r), %dl

-        addl    $3, from_r

-        movb    %al, 1(out_r)

-        movb    %dl, 2(out_r)

-        addl    $3, out_r

-        rep     movsb

-

-        movl    in(%esp), in_r          /* move in back to %esi, toss from */

-#if defined( USE_MMX )

-        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */

-#endif

-        jmp     .L_while_test

-

-.align 16,0x90

-

-#if ! defined( USE_MMX )

-

-.L_test_for_second_level_length:

-        /* else if ((op & 64) == 0) {

-         *   this = lcode[this.val + (hold & mask[op])];

-         * }

-         */

-        testb   $64, %al

-        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */

-

-        movl    $1, %eax

-        shll    %cl, %eax

-        decl    %eax

-        andl    hold_r, %eax            /* eax &= hold */

-        addl    %edx, %eax              /* eax += this.val */

-        movl    lcode(%esp), %edx       /* edx = lcode */

-        movl    (%edx,%eax,4), %eax     /* eax = lcode[val + (hold&mask[op])] */

-        jmp     .L_dolen

-

-#else /* USE_MMX */

-

-.L_test_for_second_level_length: 

-        testb   $64, %al

-        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */

-

-        andl    $15, %eax

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-        movd    hold_mm, %ecx

-        andl    .L_mask(,%eax,4), %ecx

-        addl    len_r, %ecx

-        movl    (%ebx,%ecx,4), %eax     /* eax = lcode[hold & lmask] */

-        jmp     .L_dolen

-

-#endif

-

-.align 16,0x90

-

-#if ! defined( USE_MMX )

-

-.L_test_for_second_level_dist:

-        /* else if ((op & 64) == 0) {

-         *   this = dcode[this.val + (hold & mask[op])];

-         * }

-         */

-        testb   $64, %al

-        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */

-

-        movl    $1, %eax

-        shll    %cl, %eax

-        decl    %eax

-        andl    hold_r, %eax            /* eax &= hold */

-        addl    %edx, %eax              /* eax += this.val */

-        movl    dcode(%esp), %edx       /* edx = dcode */

-        movl    (%edx,%eax,4), %eax     /* eax = dcode[val + (hold&mask[op])] */

-        jmp     .L_dodist

-

-#else /* USE_MMX */

-

-.L_test_for_second_level_dist:

-        testb   $64, %al

-        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */

-

-        andl    $15, %eax

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-        movd    hold_mm, %ecx

-        andl    .L_mask(,%eax,4), %ecx

-        movl    dcode(%esp), %eax       /* ecx = dcode */

-        addl    dist_r, %ecx

-        movl    (%eax,%ecx,4), %eax     /* eax = lcode[hold & lmask] */

-        jmp     .L_dodist

-

-#endif

-

-.align 16,0x90

-.L_clip_window:

-        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *       %ecx = nbytes

-         *

-         * else {

-         *   if (dist > wsize) {

-         *     invalid distance

-         *   }

-         *   from = window;

-         *   nbytes = dist - nbytes;

-         *   if (write == 0) {

-         *     from += wsize - nbytes;

-         */

-#define nbytes_r %ecx

-

-        movl    %eax, nbytes_r

-        movl    wsize(%esp), %eax       /* prepare for dist compare */

-        negl    nbytes_r                /* nbytes = -nbytes */

-        movl    window(%esp), from_r    /* from = window */

-

-        cmpl    dist_r, %eax

-        jb      .L_invalid_distance_too_far /* if (dist > wsize) */

-

-        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */

-        cmpl    $0, write(%esp)

-        jne     .L_wrap_around_window   /* if (write != 0) */

-

-        subl    nbytes_r, %eax

-        addl    %eax, from_r            /* from += wsize - nbytes */

-

-        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *       %ecx = nbytes, %eax = len

-         *

-         *     if (nbytes < len) {

-         *       len -= nbytes;

-         *       do {

-         *         PUP(out) = PUP(from);

-         *       } while (--nbytes);

-         *       from = out - dist;

-         *     }

-         *   }

-         */

-

-#if ! defined( USE_MMX )

-#define len_r %eax

-        movl    len(%esp), len_r

-#endif

-        cmpl    nbytes_r, len_r

-        jbe     .L_do_copy1             /* if (nbytes >= len) */

-

-        subl    nbytes_r, len_r         /* len -= nbytes */

-        rep     movsb

-        movl    out_r, from_r

-        subl    dist_r, from_r          /* from = out - dist */

-        jmp     .L_do_copy1

-

-        cmpl    nbytes_r, len_r

-        jbe     .L_do_copy1             /* if (nbytes >= len) */

-

-        subl    nbytes_r, len_r         /* len -= nbytes */

-        rep     movsb

-        movl    out_r, from_r

-        subl    dist_r, from_r          /* from = out - dist */

-        jmp     .L_do_copy1

-

-.L_wrap_around_window:

-        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *       %ecx = nbytes, %eax = write, %eax = len

-         *

-         *   else if (write < nbytes) {

-         *     from += wsize + write - nbytes;

-         *     nbytes -= write;

-         *     if (nbytes < len) {

-         *       len -= nbytes;

-         *       do {

-         *         PUP(out) = PUP(from);

-         *       } while (--nbytes);

-         *       from = window;

-         *       nbytes = write;

-         *       if (nbytes < len) {

-         *         len -= nbytes;

-         *         do {

-         *           PUP(out) = PUP(from);

-         *         } while(--nbytes);

-         *         from = out - dist;

-         *       }

-         *     }

-         *   }

-         */

-#define write_r %eax

-

-        movl    write(%esp), write_r

-        cmpl    write_r, nbytes_r

-        jbe     .L_contiguous_in_window /* if (write >= nbytes) */

-

-        addl    wsize(%esp), from_r

-        addl    write_r, from_r

-        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */

-        subl    write_r, nbytes_r       /* nbytes -= write */

-#undef write_r

-

-#if ! defined( USE_MMX )

-        movl    len(%esp), len_r

-#endif

-        cmpl    nbytes_r, len_r

-        jbe     .L_do_copy1             /* if (nbytes >= len) */

-

-        subl    nbytes_r, len_r         /* len -= nbytes */

-        rep     movsb

-        movl    window(%esp), from_r    /* from = window */

-        movl    write(%esp), nbytes_r   /* nbytes = write */

-        cmpl    nbytes_r, len_r

-        jbe     .L_do_copy1             /* if (nbytes >= len) */

-

-        subl    nbytes_r, len_r         /* len -= nbytes */

-        rep     movsb

-        movl    out_r, from_r

-        subl    dist_r, from_r          /* from = out - dist */

-        jmp     .L_do_copy1

-

-.L_contiguous_in_window:

-        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist

-         *       %ecx = nbytes, %eax = write, %eax = len

-         *

-         *   else {

-         *     from += write - nbytes;

-         *     if (nbytes < len) {

-         *       len -= nbytes;

-         *       do {

-         *         PUP(out) = PUP(from);

-         *       } while (--nbytes);

-         *       from = out - dist;

-         *     }

-         *   }

-         */

-#define write_r %eax

-

-        addl    write_r, from_r

-        subl    nbytes_r, from_r        /* from += write - nbytes */

-#undef write_r

-

-#if ! defined( USE_MMX )

-        movl    len(%esp), len_r

-#endif

-        cmpl    nbytes_r, len_r

-        jbe     .L_do_copy1             /* if (nbytes >= len) */

-

-        subl    nbytes_r, len_r         /* len -= nbytes */

-        rep     movsb

-        movl    out_r, from_r

-        subl    dist_r, from_r          /* from = out - dist */

-

-.L_do_copy1:

-        /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out

-         *       %eax = len

-         *

-         *     while (len > 0) {

-         *       PUP(out) = PUP(from);

-         *       len--;

-         *     }

-         *   }

-         * } while (in < last && out < end);

-         */

-#undef nbytes_r

-#define in_r %esi

-

-        movl    len_r, %ecx

-        rep     movsb

-

-        movl    in(%esp), in_r          /* move in back to %esi, toss from */

-#if defined( USE_MMX )

-        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */

-#endif

-        jmp     .L_while_test

-

-#undef len_r

-#undef from_r

-#undef dist_r

-

-.L_invalid_distance_code:

-        /* else {

-         *   strm->msg = "invalid distance code";

-         *   state->mode = BAD;

-         * }

-         */

-        movl    $.L_invalid_distance_code_msg, %ecx

-        movl    $INFLATE_MODE_BAD, %edx

-        jmp     .L_update_stream_state

-

-.L_test_for_end_of_block:

-        /* else if (op & 32) {

-         *   state->mode = TYPE;

-         *   break;

-         * }

-         */

-        testb   $32, %al

-        jz      .L_invalid_literal_length_code  /* if ((op & 32) == 0) */

-

-        movl    $0, %ecx

-        movl    $INFLATE_MODE_TYPE, %edx

-        jmp     .L_update_stream_state

-

-.L_invalid_literal_length_code:

-        /* else {

-         *   strm->msg = "invalid literal/length code";

-         *   state->mode = BAD;

-         * }

-         */

-        movl    $.L_invalid_literal_length_code_msg, %ecx

-        movl    $INFLATE_MODE_BAD, %edx

-        jmp     .L_update_stream_state

-

-.L_invalid_distance_too_far:

-        /* strm->msg = "invalid distance too far back";

-         * state->mode = BAD;

-         */

-        movl    in(%esp), in_r          /* from_r has in's reg, put in back */

-        movl    $.L_invalid_distance_too_far_msg, %ecx

-        movl    $INFLATE_MODE_BAD, %edx

-        jmp     .L_update_stream_state

-

-.L_update_stream_state:

-        /* set strm->msg = %ecx, strm->state->mode = %edx */

-        movl    strm_sp(%esp), %eax

-        testl   %ecx, %ecx              /* if (msg != NULL) */

-        jz      .L_skip_msg

-        movl    %ecx, msg_strm(%eax)    /* strm->msg = msg */

-.L_skip_msg:

-        movl    state_strm(%eax), %eax  /* state = strm->state */

-        movl    %edx, mode_state(%eax)  /* state->mode = edx (BAD | TYPE) */

-

-.L_break_loop:

-

-#define strm_r  %eax

-#define state_r %edx

-

-        /* len = bits >> 3;

-         * in -= len;

-         * bits -= len << 3;

-         * hold &= (1U << bits) - 1;

-         * state->hold = hold;

-         * state->bits = bits;

-         * strm->next_in = in;

-         * strm->next_out = out;

-         */

-        movl    strm_sp(%esp), strm_r

-        movl    bitslong_r, %ecx

-        movl    state_strm(strm_r), state_r

-        shrl    $3, %ecx

-        subl    %ecx, in_r

-        shll    $3, %ecx

-        subl    %ecx, bitslong_r

-        movl    out_r, next_out_strm(strm_r)

-        movl    in_r, next_in_strm(strm_r)

-        movl    bitslong_r, bits_state(state_r)

-

-        movl    bitslong_r, %ecx

-        movl    $1, %ebx                /* overwrites bitslong_r, %bl */

-        shll    %cl, %ebx

-        decl    %ebx

-

-#undef bits_r

-#undef bitslong_r

-

-#if ! defined( USE_MMX )

-

-        andl    %ebx, hold_r

-        movl    hold_r, hold_state(state_r)

-

-#else /* USE_MMX */

-

-        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */

-        movd    hold_mm, %ecx

-        andl    %ebx, %ecx

-        movl    %ecx, hold_state(state_r)

-

-#endif

-

-#define last_r %ebx

-

-        /* strm->avail_in = in < last ? 5 + (last - in) : 5 - (in - last) */

-        movl    last(%esp), last_r

-        cmpl    in_r, last_r

-        jbe     .L_last_is_smaller     /* if (in >= last) */

-

-        subl    in_r, last_r           /* last -= in */

-        addl    $5, last_r             /* last += 5 */

-        movl    last_r, avail_in_strm(strm_r)

-        jmp     .L_fixup_out

-.L_last_is_smaller:

-        subl    last_r, in_r           /* in -= last */

-        negl    in_r                   /* in = -in */

-        addl    $5, in_r               /* in += 5 */

-        movl    in_r, avail_in_strm(strm_r)

-

-#undef last_r

-#define end_r %ebx

-

-.L_fixup_out:

-        /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/

-        movl    end(%esp), end_r

-        cmpl    out_r, end_r

-        jbe     .L_end_is_smaller      /* if (out >= end) */

-

-        subl    out_r, end_r           /* end -= out */

-        addl    $257, end_r            /* end += 257 */

-        movl    end_r, avail_out_strm(strm_r)

-        jmp     .L_done

-.L_end_is_smaller:

-        subl    end_r, out_r           /* out -= end */

-        negl    out_r                  /* out = -out */

-        addl    $257, out_r            /* out += 257 */

-        movl    out_r, avail_out_strm(strm_r)

-

-#undef end_r

-

-.L_done:

-#if defined( USE_MMX )

-        emms

-#endif

-        addl    $local_var_size, %esp

-        popf

-        popl    %ebx

-        popl    %ebp

-        popl    %esi

-        popl    %edi

-        ret

-

-.type inflate_fast,@function

-.size inflate_fast,.-inflate_fast

+/*
+ * inffast.S is a hand tuned assembler version of:
+ *
+ * inffast.c -- fast decoding
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ *
+ * Copyright (C) 2003 Chris Anderson <christop@charm.net>
+ * Please use the copyright conditions above.
+ * 
+ * This version (Jan-23-2003) of inflate_fast was coded and tested under
+ * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution.  On that
+ * machine, I found that gzip style archives decompressed about 20% faster than
+ * the gcc-3.2 -O3 -fomit-frame-pointer compiled version.  Your results will
+ * depend on how large of a buffer is used for z_stream.next_in & next_out
+ * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in
+ * stream processing I/O and crc32/addler32.  In my case, this routine used
+ * 70% of the cpu time and crc32 used 20%.
+ *
+ * I am confident that this version will work in the general case, but I have
+ * not tested a wide variety of datasets or a wide variety of platforms.
+ *
+ * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating.
+ * It should be a runtime flag instead of compile time flag...
+ *
+ * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction.
+ * With -DUSE_MMX, only MMX code is compiled.  With -DNO_MMX, only non-MMX code
+ * is compiled.  Without either option, runtime detection is enabled.  Runtime
+ * detection should work on all modern cpus and the recomended algorithm (flip
+ * ID bit on eflags and then use the cpuid instruction) is used in many
+ * multimedia applications.  Tested under win2k with gcc-2.95 and gas-2.12
+ * distributed with cygwin3.  Compiling with gcc-2.95 -c inffast.S -o
+ * inffast.obj generates a COFF object which can then be linked with MSVC++
+ * compiled code.  Tested under FreeBSD 4.7 with gcc-2.95.
+ *
+ * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and
+ * slower than compiler generated code).  Adjusted cpuid check to use the MMX
+ * code only for Pentiums < P4 until I have more data on the P4.  Speed
+ * improvment is only about 15% on the Athlon when compared with code generated
+ * with MSVC++.  Not sure yet, but I think the P4 will also be slower using the
+ * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and
+ * have less latency than MMX ops.  Added code to buffer the last 11 bytes of
+ * the input stream since the MMX code grabs bits in chunks of 32, which
+ * differs from the inffast.c algorithm.  I don't think there would have been
+ * read overruns where a page boundary was crossed (a segfault), but there
+ * could have been overruns when next_in ends on unaligned memory (unintialized
+ * memory read).
+ *
+ * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX.  I created a C
+ * version of the non-MMX code so that it doesn't depend on zstrm and zstate
+ * structure offsets which are hard coded in this file.  This was last tested
+ * with zlib-1.2.0 which is currently in beta testing, newer versions of this
+ * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and
+ * http://www.charm.net/~christop/zlib/
+ */
+
+
+/*
+ * if you have underscore linking problems (_inflate_fast undefined), try
+ * using -DGAS_COFF
+ */
+#if ! defined( GAS_COFF ) && ! defined( GAS_ELF )
+
+#if defined( __CYGWIN__ )
+#define GAS_COFF /* windows object format */
+#else
+#define GAS_ELF
+#endif
+
+#endif /* ! GAS_COFF && ! GAS_ELF */
+
+
+#if defined( GAS_COFF )
+
+/* coff externals have underscores */
+#define inflate_fast _inflate_fast
+#define inflate_fast_use_mmx _inflate_fast_use_mmx
+
+#endif /* GAS_COFF */
+
+
+.file "inffast.S"
+
+.globl inflate_fast
+
+.text
+.align 4,0
+.L_invalid_literal_length_code_msg:
+.string "invalid literal/length code"
+
+.align 4,0
+.L_invalid_distance_code_msg:
+.string "invalid distance code"
+
+.align 4,0
+.L_invalid_distance_too_far_msg:
+.string "invalid distance too far back"
+
+#if ! defined( NO_MMX )
+.align 4,0
+.L_mask: /* mask[N] = ( 1 << N ) - 1 */
+.long 0
+.long 1
+.long 3
+.long 7
+.long 15
+.long 31
+.long 63
+.long 127
+.long 255
+.long 511
+.long 1023
+.long 2047
+.long 4095
+.long 8191
+.long 16383
+.long 32767
+.long 65535
+.long 131071
+.long 262143
+.long 524287
+.long 1048575
+.long 2097151
+.long 4194303
+.long 8388607
+.long 16777215
+.long 33554431
+.long 67108863
+.long 134217727
+.long 268435455
+.long 536870911
+.long 1073741823
+.long 2147483647
+.long 4294967295
+#endif /* NO_MMX */
+
+.text
+
+/*
+ * struct z_stream offsets, in zlib.h
+ */
+#define next_in_strm   0   /* strm->next_in */
+#define avail_in_strm  4   /* strm->avail_in */
+#define next_out_strm  12  /* strm->next_out */
+#define avail_out_strm 16  /* strm->avail_out */
+#define msg_strm       24  /* strm->msg */
+#define state_strm     28  /* strm->state */
+
+/*
+ * struct inflate_state offsets, in inflate.h
+ */
+#define mode_state     0   /* state->mode */
+#define wsize_state    32  /* state->wsize */
+#define write_state    36  /* state->write */
+#define window_state   40  /* state->window */
+#define hold_state     44  /* state->hold */
+#define bits_state     48  /* state->bits */
+#define lencode_state  64  /* state->lencode */
+#define distcode_state 68  /* state->distcode */
+#define lenbits_state  72  /* state->lenbits */
+#define distbits_state 76  /* state->distbits */
+
+/*
+ * inflate_fast's activation record
+ */
+#define local_var_size 64 /* how much local space for vars */
+#define strm_sp        88 /* first arg: z_stream * (local_var_size + 24) */
+#define start_sp       92 /* second arg: unsigned int (local_var_size + 28) */
+
+/*
+ * offsets for local vars on stack
+ */
+#define out            60  /* unsigned char* */
+#define window         56  /* unsigned char* */
+#define wsize          52  /* unsigned int */
+#define write          48  /* unsigned int */
+#define in             44  /* unsigned char* */
+#define beg            40  /* unsigned char* */
+#define buf            28  /* char[ 12 ] */
+#define len            24  /* unsigned int */
+#define last           20  /* unsigned char* */
+#define end            16  /* unsigned char* */
+#define dcode          12  /* code* */
+#define lcode           8  /* code* */
+#define dmask           4  /* unsigned int */
+#define lmask           0  /* unsigned int */
+
+/*
+ * typedef enum inflate_mode consts, in inflate.h
+ */
+#ifndef NO_GUNZIP
+#define GUNZIP
+#endif
+
+#ifdef GUNZIP
+#define INFLATE_MODE_TYPE 11  /* state->mode flags enum-ed in inflate.h */
+#define INFLATE_MODE_BAD  26
+#else
+#define INFLATE_MODE_TYPE 3
+#define INFLATE_MODE_BAD  17
+#endif
+
+
+#if ! defined( USE_MMX ) && ! defined( NO_MMX )
+
+#define RUN_TIME_MMX
+
+#define CHECK_MMX    1
+#define DO_USE_MMX   2
+#define DONT_USE_MMX 3
+
+.globl inflate_fast_use_mmx
+
+.data
+
+.align 4,0
+inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */
+.long CHECK_MMX
+
+#if defined( GAS_ELF )
+/* elf info */
+.type   inflate_fast_use_mmx,@object
+.size   inflate_fast_use_mmx,4
+#endif
+
+#endif /* RUN_TIME_MMX */
+
+#if defined( GAS_COFF )
+/* coff info: scl 2 = extern, type 32 = function */
+.def inflate_fast; .scl 2; .type 32; .endef
+#endif
+
+.text
+
+.align 32,0x90
+inflate_fast:
+        pushl   %edi
+        pushl   %esi
+        pushl   %ebp
+        pushl   %ebx
+        pushf   /* save eflags (strm_sp, state_sp assumes this is 32 bits) */
+        subl    $local_var_size, %esp
+        cld
+
+#define strm_r  %esi
+#define state_r %edi
+
+        movl    strm_sp(%esp), strm_r
+        movl    state_strm(strm_r), state_r
+
+        /* in = strm->next_in;
+         * out = strm->next_out;
+         * last = in + strm->avail_in - 11;
+         * beg = out - (start - strm->avail_out);
+         * end = out + (strm->avail_out - 257);
+         */
+        movl    avail_in_strm(strm_r), %edx
+        movl    next_in_strm(strm_r), %eax
+
+        addl    %eax, %edx      /* avail_in += next_in */
+        subl    $11, %edx       /* avail_in -= 11 */
+
+        movl    %eax, in(%esp)
+        movl    %edx, last(%esp)
+
+        movl    start_sp(%esp), %ebp
+        movl    avail_out_strm(strm_r), %ecx
+        movl    next_out_strm(strm_r), %ebx
+
+        subl    %ecx, %ebp      /* start -= avail_out */
+        negl    %ebp            /* start = -start */
+        addl    %ebx, %ebp      /* start += next_out */
+
+        subl    $257, %ecx      /* avail_out -= 257 */
+        addl    %ebx, %ecx      /* avail_out += out */
+
+        movl    %ebx, out(%esp)
+        movl    %ebp, beg(%esp)
+        movl    %ecx, end(%esp)
+
+        /* wsize = state->wsize;
+         * write = state->write;
+         * window = state->window;
+         * hold = state->hold;
+         * bits = state->bits;
+         * lcode = state->lencode;
+         * dcode = state->distcode;
+         * lmask = ( 1 << state->lenbits ) - 1;
+         * dmask = ( 1 << state->distbits ) - 1;
+         */
+
+        movl    lencode_state(state_r), %eax
+        movl    distcode_state(state_r), %ecx
+
+        movl    %eax, lcode(%esp)
+        movl    %ecx, dcode(%esp)
+
+        movl    $1, %eax
+        movl    lenbits_state(state_r), %ecx
+        shll    %cl, %eax
+        decl    %eax
+        movl    %eax, lmask(%esp)
+
+        movl    $1, %eax
+        movl    distbits_state(state_r), %ecx
+        shll    %cl, %eax
+        decl    %eax
+        movl    %eax, dmask(%esp)
+
+        movl    wsize_state(state_r), %eax
+        movl    write_state(state_r), %ecx
+        movl    window_state(state_r), %edx
+
+        movl    %eax, wsize(%esp)
+        movl    %ecx, write(%esp)
+        movl    %edx, window(%esp)
+
+        movl    hold_state(state_r), %ebp
+        movl    bits_state(state_r), %ebx
+
+#undef strm_r
+#undef state_r
+
+#define in_r       %esi
+#define from_r     %esi
+#define out_r      %edi
+
+        movl    in(%esp), in_r
+        movl    last(%esp), %ecx
+        cmpl    in_r, %ecx
+        ja      .L_align_long           /* if in < last */
+
+        addl    $11, %ecx               /* ecx = &in[ avail_in ] */
+        subl    in_r, %ecx              /* ecx = avail_in */
+        movl    $12, %eax
+        subl    %ecx, %eax              /* eax = 12 - avail_in */
+        leal    buf(%esp), %edi
+        rep     movsb                   /* memcpy( buf, in, avail_in ) */
+        movl    %eax, %ecx
+        xorl    %eax, %eax
+        rep     stosb         /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */
+        leal    buf(%esp), in_r         /* in = buf */
+        movl    in_r, last(%esp)        /* last = in, do just one iteration */
+        jmp     .L_is_aligned
+
+        /* align in_r on long boundary */
+.L_align_long:
+        testl   $3, in_r
+        jz      .L_is_aligned
+        xorl    %eax, %eax
+        movb    (in_r), %al
+        incl    in_r
+        movl    %ebx, %ecx
+        addl    $8, %ebx
+        shll    %cl, %eax
+        orl     %eax, %ebp
+        jmp     .L_align_long
+
+.L_is_aligned:
+        movl    out(%esp), out_r
+
+#if defined( NO_MMX )
+        jmp     .L_do_loop
+#endif
+
+#if defined( USE_MMX )
+        jmp     .L_init_mmx
+#endif
+
+/*** Runtime MMX check ***/
+
+#if defined( RUN_TIME_MMX )
+.L_check_mmx:
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        je      .L_init_mmx
+        ja      .L_do_loop /* > 2 */
+
+        pushl   %eax
+        pushl   %ebx
+        pushl   %ecx
+        pushl   %edx
+        pushf
+        movl    (%esp), %eax      /* copy eflags to eax */
+        xorl    $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21)
+                                   * to see if cpu supports cpuid...
+                                   * ID bit method not supported by NexGen but
+                                   * bios may load a cpuid instruction and
+                                   * cpuid may be disabled on Cyrix 5-6x86 */
+        popf
+        pushf   
+        popl    %edx              /* copy new eflags to edx */
+        xorl    %eax, %edx        /* test if ID bit is flipped */
+        jz      .L_dont_use_mmx   /* not flipped if zero */
+        xorl    %eax, %eax
+        cpuid
+        cmpl    $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */
+        jne     .L_dont_use_mmx
+        cmpl    $0x6c65746e, %ecx
+        jne     .L_dont_use_mmx
+        cmpl    $0x49656e69, %edx
+        jne     .L_dont_use_mmx
+        movl    $1, %eax
+        cpuid                     /* get cpu features */
+        shrl    $8, %eax
+        andl    $15, %eax
+        cmpl    $6, %eax          /* check for Pentium family, is 0xf for P4 */
+        jne     .L_dont_use_mmx
+        testl   $0x800000, %edx   /* test if MMX feature is set (bit 23) */
+        jnz     .L_use_mmx
+        jmp     .L_dont_use_mmx
+.L_use_mmx:
+        movl    $DO_USE_MMX, inflate_fast_use_mmx
+        jmp     .L_check_mmx_pop
+.L_dont_use_mmx:
+        movl    $DONT_USE_MMX, inflate_fast_use_mmx
+.L_check_mmx_pop:
+        popl    %edx
+        popl    %ecx
+        popl    %ebx
+        popl    %eax
+        jmp     .L_check_mmx
+#endif
+        
+
+/*** Non-MMX code ***/
+
+#if defined ( NO_MMX ) || defined( RUN_TIME_MMX )
+
+#define hold_r     %ebp
+#define bits_r     %bl
+#define bitslong_r %ebx
+
+.align 32,0x90
+.L_while_test:
+        /* while (in < last && out < end)
+         */
+        cmpl    out_r, end(%esp)
+        jbe     .L_break_loop           /* if (out >= end) */
+
+        cmpl    in_r, last(%esp)
+        jbe     .L_break_loop
+
+.L_do_loop:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *
+         * do { 
+         *   if (bits < 15) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   this = lcode[hold & lmask]
+         */
+        cmpb    $15, bits_r
+        ja      .L_get_length_code      /* if (15 < bits) */
+
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+
+.L_get_length_code:
+        movl    lmask(%esp), %edx       /* edx = lmask */
+        movl    lcode(%esp), %ecx       /* ecx = lcode */
+        andl    hold_r, %edx            /* edx &= hold */
+        movl    (%ecx,%edx,4), %eax     /* eax = lcode[hold & lmask] */
+
+.L_dolen:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *
+         * dolen:
+         *    bits -= this.bits;
+         *    hold >>= this.bits
+         */
+        movb    %ah, %cl                /* cl = this.bits */
+        subb    %ah, bits_r             /* bits -= this.bits */
+        shrl    %cl, hold_r             /* hold >>= this.bits */
+
+        /* check if op is a literal
+         * if (op == 0) {
+         *    PUP(out) = this.val;
+         *  }
+         */
+        testb   %al, %al
+        jnz     .L_test_for_length_base /* if (op != 0) 45.7% */
+
+        shrl    $16, %eax               /* output this.val char */
+        stosb
+        jmp     .L_while_test
+
+.L_test_for_length_base:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len
+         *
+         * else if (op & 16) {
+         *   len = this.val
+         *   op &= 15
+         *   if (op) {
+         *     if (op > bits) {
+         *       hold |= *((unsigned short *)in)++ << bits;
+         *       bits += 16
+         *     }
+         *     len += hold & mask[op];
+         *     bits -= op;
+         *     hold >>= op;
+         *   }
+         */
+#define len_r %edx
+        movl    %eax, len_r             /* len = this */
+        shrl    $16, len_r              /* len = this.val */
+        movb    %al, %cl
+
+        testb   $16, %al
+        jz      .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */
+        andb    $15, %cl                /* op &= 15 */
+        jz      .L_save_len             /* if (!op) */
+        cmpb    %cl, bits_r
+        jae     .L_add_bits_to_len      /* if (op <= bits) */
+
+        movb    %cl, %ch                /* stash op in ch, freeing cl */
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+        movb    %ch, %cl                /* move op back to ecx */
+
+.L_add_bits_to_len:
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        subb    %cl, bits_r
+        andl    hold_r, %eax            /* eax &= hold */
+        shrl    %cl, hold_r
+        addl    %eax, len_r             /* len += hold & mask[op] */
+
+.L_save_len:
+        movl    len_r, len(%esp)        /* save len */
+#undef  len_r
+
+.L_decode_distance:
+        /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *
+         *   if (bits < 15) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   this = dcode[hold & dmask];
+         * dodist:
+         *   bits -= this.bits;
+         *   hold >>= this.bits;
+         *   op = this.op;
+         */
+
+        cmpb    $15, bits_r
+        ja      .L_get_distance_code    /* if (15 < bits) */
+
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+
+.L_get_distance_code:
+        movl    dmask(%esp), %edx       /* edx = dmask */
+        movl    dcode(%esp), %ecx       /* ecx = dcode */
+        andl    hold_r, %edx            /* edx &= hold */
+        movl    (%ecx,%edx,4), %eax     /* eax = dcode[hold & dmask] */
+
+#define dist_r %edx
+.L_dodist:
+        movl    %eax, dist_r            /* dist = this */
+        shrl    $16, dist_r             /* dist = this.val */
+        movb    %ah, %cl
+        subb    %ah, bits_r             /* bits -= this.bits */
+        shrl    %cl, hold_r             /* hold >>= this.bits */
+
+        /* if (op & 16) {
+         *   dist = this.val
+         *   op &= 15
+         *   if (op > bits) {
+         *     hold |= *((unsigned short *)in)++ << bits;
+         *     bits += 16
+         *   }
+         *   dist += hold & mask[op];
+         *   bits -= op;
+         *   hold >>= op;
+         */
+        movb    %al, %cl                /* cl = this.op */
+
+        testb   $16, %al                /* if ((op & 16) == 0) */
+        jz      .L_test_for_second_level_dist
+        andb    $15, %cl                /* op &= 15 */
+        jz      .L_check_dist_one
+        cmpb    %cl, bits_r
+        jae     .L_add_bits_to_dist     /* if (op <= bits) 97.6% */
+
+        movb    %cl, %ch                /* stash op in ch, freeing cl */
+        xorl    %eax, %eax
+        lodsw                           /* al = *(ushort *)in++ */
+        movb    bits_r, %cl             /* cl = bits, needs it for shifting */
+        addb    $16, bits_r             /* bits += 16 */
+        shll    %cl, %eax
+        orl     %eax, hold_r            /* hold |= *((ushort *)in)++ << bits */
+        movb    %ch, %cl                /* move op back to ecx */
+
+.L_add_bits_to_dist:
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax                    /* (1 << op) - 1 */
+        subb    %cl, bits_r
+        andl    hold_r, %eax            /* eax &= hold */
+        shrl    %cl, hold_r
+        addl    %eax, dist_r            /* dist += hold & ((1 << op) - 1) */
+        jmp     .L_check_window
+
+.L_check_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes
+         *
+         * nbytes = out - beg;
+         * if (dist <= nbytes) {
+         *   from = out - dist;
+         *   do {
+         *     PUP(out) = PUP(from);
+         *   } while (--len > 0) {
+         * }
+         */
+
+        movl    in_r, in(%esp)          /* save in so from can use it's reg */
+        movl    out_r, %eax
+        subl    beg(%esp), %eax         /* nbytes = out - beg */
+
+        cmpl    dist_r, %eax
+        jb      .L_clip_window          /* if (dist > nbytes) 4.2% */
+
+        movl    len(%esp), %ecx
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+        subl    $3, %ecx
+        movb    (from_r), %al
+        movb    %al, (out_r)
+        movb    1(from_r), %al
+        movb    2(from_r), %dl
+        addl    $3, from_r
+        movb    %al, 1(out_r)
+        movb    %dl, 2(out_r)
+        addl    $3, out_r
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        jmp     .L_while_test
+
+.align 16,0x90
+.L_check_dist_one:
+        cmpl    $1, dist_r
+        jne     .L_check_window
+        cmpl    out_r, beg(%esp)
+        je      .L_check_window
+
+        decl    out_r
+        movl    len(%esp), %ecx
+        movb    (out_r), %al
+        subl    $3, %ecx
+
+        movb    %al, 1(out_r)
+        movb    %al, 2(out_r)
+        movb    %al, 3(out_r)
+        addl    $4, out_r
+        rep     stosb
+
+        jmp     .L_while_test
+
+.align 16,0x90
+.L_test_for_second_level_length:
+        /* else if ((op & 64) == 0) {
+         *   this = lcode[this.val + (hold & mask[op])];
+         * }
+         */
+        testb   $64, %al
+        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */
+
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        andl    hold_r, %eax            /* eax &= hold */
+        addl    %edx, %eax              /* eax += this.val */
+        movl    lcode(%esp), %edx       /* edx = lcode */
+        movl    (%edx,%eax,4), %eax     /* eax = lcode[val + (hold&mask[op])] */
+        jmp     .L_dolen
+
+.align 16,0x90
+.L_test_for_second_level_dist:
+        /* else if ((op & 64) == 0) {
+         *   this = dcode[this.val + (hold & mask[op])];
+         * }
+         */
+        testb   $64, %al
+        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */
+
+        movl    $1, %eax
+        shll    %cl, %eax
+        decl    %eax
+        andl    hold_r, %eax            /* eax &= hold */
+        addl    %edx, %eax              /* eax += this.val */
+        movl    dcode(%esp), %edx       /* edx = dcode */
+        movl    (%edx,%eax,4), %eax     /* eax = dcode[val + (hold&mask[op])] */
+        jmp     .L_dodist
+
+.align 16,0x90
+.L_clip_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes
+         *
+         * else {
+         *   if (dist > wsize) {
+         *     invalid distance
+         *   }
+         *   from = window;
+         *   nbytes = dist - nbytes;
+         *   if (write == 0) {
+         *     from += wsize - nbytes;
+         */
+#define nbytes_r %ecx
+        movl    %eax, nbytes_r
+        movl    wsize(%esp), %eax       /* prepare for dist compare */
+        negl    nbytes_r                /* nbytes = -nbytes */
+        movl    window(%esp), from_r    /* from = window */
+
+        cmpl    dist_r, %eax
+        jb      .L_invalid_distance_too_far /* if (dist > wsize) */
+
+        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
+        cmpl    $0, write(%esp)
+        jne     .L_wrap_around_window   /* if (write != 0) */
+
+        subl    nbytes_r, %eax
+        addl    %eax, from_r            /* from += wsize - nbytes */
+
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = len
+         *
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = out - dist;
+         *     }
+         *   }
+         */
+#define len_r %eax
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+.L_wrap_around_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = write, %eax = len
+         *
+         *   else if (write < nbytes) {
+         *     from += wsize + write - nbytes;
+         *     nbytes -= write;
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = window;
+         *       nbytes = write;
+         *       if (nbytes < len) {
+         *         len -= nbytes;
+         *         do {
+         *           PUP(out) = PUP(from);
+         *         } while(--nbytes);
+         *         from = out - dist;
+         *       }
+         *     }
+         *   }
+         */
+#define write_r %eax
+        movl    write(%esp), write_r
+        cmpl    write_r, nbytes_r
+        jbe     .L_contiguous_in_window /* if (write >= nbytes) */
+
+        addl    wsize(%esp), from_r
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
+        subl    write_r, nbytes_r       /* nbytes -= write */
+#undef write_r
+
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    window(%esp), from_r    /* from = window */
+        movl    write(%esp), nbytes_r   /* nbytes = write */
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1
+
+.L_contiguous_in_window:
+        /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist
+         *       %ecx = nbytes, %eax = write, %eax = len
+         *
+         *   else {
+         *     from += write - nbytes;
+         *     if (nbytes < len) {
+         *       len -= nbytes;
+         *       do {
+         *         PUP(out) = PUP(from);
+         *       } while (--nbytes);
+         *       from = out - dist;
+         *     }
+         *   }
+         */
+#define write_r %eax
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += write - nbytes */
+#undef write_r
+
+        movl    len(%esp), len_r
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1             /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+.L_do_copy1:
+        /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out
+         *       %eax = len
+         *
+         *     while (len > 0) {
+         *       PUP(out) = PUP(from);
+         *       len--;
+         *     }
+         *   }
+         * } while (in < last && out < end);
+         */
+#undef nbytes_r
+#define in_r %esi
+        movl    len_r, %ecx
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        jmp     .L_while_test
+
+#undef len_r
+#undef dist_r
+
+#endif /* NO_MMX || RUN_TIME_MMX */
+
+
+/*** MMX code ***/
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+.align 32,0x90
+.L_init_mmx:
+        emms
+
+#undef  bits_r
+#undef  bitslong_r
+#define bitslong_r %ebp
+#define hold_mm    %mm0
+        movd    %ebp, hold_mm
+        movl    %ebx, bitslong_r
+
+#define used_mm   %mm1
+#define dmask2_mm %mm2
+#define lmask2_mm %mm3
+#define lmask_mm  %mm4
+#define dmask_mm  %mm5
+#define tmp_mm    %mm6
+
+        movd    lmask(%esp), lmask_mm 
+        movq    lmask_mm, lmask2_mm
+        movd    dmask(%esp), dmask_mm
+        movq    dmask_mm, dmask2_mm
+        pxor    used_mm, used_mm
+        movl    lcode(%esp), %ebx       /* ebx = lcode */
+        jmp     .L_do_loop_mmx
+
+.align 32,0x90
+.L_while_test_mmx:
+        /* while (in < last && out < end)
+         */
+        cmpl    out_r, end(%esp)
+        jbe     .L_break_loop           /* if (out >= end) */
+
+        cmpl    in_r, last(%esp)
+        jbe     .L_break_loop
+
+.L_do_loop_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+
+        cmpl    $32, bitslong_r
+        ja      .L_get_length_code_mmx  /* if (32 < bits) */
+
+        movd    bitslong_r, tmp_mm
+        movd    (in_r), %mm7
+        addl    $4, in_r
+        psllq   tmp_mm, %mm7
+        addl    $32, bitslong_r
+        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */
+
+.L_get_length_code_mmx:
+        pand    hold_mm, lmask_mm
+        movd    lmask_mm, %eax
+        movq    lmask2_mm, lmask_mm
+        movl    (%ebx,%eax,4), %eax     /* eax = lcode[hold & lmask] */
+
+.L_dolen_mmx:
+        movzbl  %ah, %ecx               /* ecx = this.bits */
+        movd    %ecx, used_mm
+        subl    %ecx, bitslong_r        /* bits -= this.bits */
+
+        testb   %al, %al
+        jnz     .L_test_for_length_base_mmx /* if (op != 0) 45.7% */
+
+        shrl    $16, %eax               /* output this.val char */
+        stosb
+        jmp     .L_while_test_mmx
+
+.L_test_for_length_base_mmx:
+#define len_r  %edx
+        movl    %eax, len_r             /* len = this */
+        shrl    $16, len_r              /* len = this.val */
+
+        testb   $16, %al
+        jz      .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */
+        andl    $15, %eax               /* op &= 15 */
+        jz      .L_decode_distance_mmx  /* if (!op) */
+
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    %eax, used_mm
+        movd    hold_mm, %ecx
+        subl    %eax, bitslong_r
+        andl    .L_mask(,%eax,4), %ecx
+        addl    %ecx, len_r             /* len += hold & mask[op] */
+
+.L_decode_distance_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+
+        cmpl    $32, bitslong_r
+        ja      .L_get_dist_code_mmx    /* if (32 < bits) */
+
+        movd    bitslong_r, tmp_mm
+        movd    (in_r), %mm7
+        addl    $4, in_r
+        psllq   tmp_mm, %mm7
+        addl    $32, bitslong_r
+        por     %mm7, hold_mm           /* hold_mm |= *((uint *)in)++ << bits */
+
+.L_get_dist_code_mmx:
+        movl    dcode(%esp), %ebx       /* ebx = dcode */
+        pand    hold_mm, dmask_mm
+        movd    dmask_mm, %eax
+        movq    dmask2_mm, dmask_mm
+        movl    (%ebx,%eax,4), %eax     /* eax = dcode[hold & lmask] */
+
+.L_dodist_mmx:
+#define dist_r %ebx
+        movzbl  %ah, %ecx               /* ecx = this.bits */
+        movl    %eax, dist_r
+        shrl    $16, dist_r             /* dist  = this.val */
+        subl    %ecx, bitslong_r        /* bits -= this.bits */
+        movd    %ecx, used_mm
+
+        testb   $16, %al                /* if ((op & 16) == 0) */
+        jz      .L_test_for_second_level_dist_mmx
+        andl    $15, %eax               /* op &= 15 */
+        jz      .L_check_dist_one_mmx
+
+.L_add_bits_to_dist_mmx:
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    %eax, used_mm           /* save bit length of current op */
+        movd    hold_mm, %ecx           /* get the next bits on input stream */
+        subl    %eax, bitslong_r        /* bits -= op bits */
+        andl    .L_mask(,%eax,4), %ecx  /* ecx   = hold & mask[op] */
+        addl    %ecx, dist_r            /* dist += hold & mask[op] */
+
+.L_check_window_mmx:
+        movl    in_r, in(%esp)          /* save in so from can use it's reg */
+        movl    out_r, %eax
+        subl    beg(%esp), %eax         /* nbytes = out - beg */
+
+        cmpl    dist_r, %eax
+        jb      .L_clip_window_mmx      /* if (dist > nbytes) 4.2% */
+
+        movl    len_r, %ecx
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+        subl    $3, %ecx
+        movb    (from_r), %al
+        movb    %al, (out_r)
+        movb    1(from_r), %al
+        movb    2(from_r), %dl
+        addl    $3, from_r
+        movb    %al, 1(out_r)
+        movb    %dl, 2(out_r)
+        addl    $3, out_r
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+.align 16,0x90
+.L_check_dist_one_mmx:
+        cmpl    $1, dist_r
+        jne     .L_check_window_mmx
+        cmpl    out_r, beg(%esp)
+        je      .L_check_window_mmx
+
+        decl    out_r
+        movl    len_r, %ecx
+        movb    (out_r), %al
+        subl    $3, %ecx
+
+        movb    %al, 1(out_r)
+        movb    %al, 2(out_r)
+        movb    %al, 3(out_r)
+        addl    $4, out_r
+        rep     stosb
+
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+.align 16,0x90
+.L_test_for_second_level_length_mmx: 
+        testb   $64, %al
+        jnz     .L_test_for_end_of_block  /* if ((op & 64) != 0) */
+
+        andl    $15, %eax
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ecx
+        andl    .L_mask(,%eax,4), %ecx
+        addl    len_r, %ecx
+        movl    (%ebx,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
+        jmp     .L_dolen_mmx
+
+.align 16,0x90
+.L_test_for_second_level_dist_mmx:
+        testb   $64, %al
+        jnz     .L_invalid_distance_code  /* if ((op & 64) != 0) */
+
+        andl    $15, %eax
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ecx
+        andl    .L_mask(,%eax,4), %ecx
+        movl    dcode(%esp), %eax       /* ecx = dcode */
+        addl    dist_r, %ecx
+        movl    (%eax,%ecx,4), %eax     /* eax = lcode[hold & lmask] */
+        jmp     .L_dodist_mmx
+
+.align 16,0x90
+.L_clip_window_mmx:
+#define nbytes_r %ecx
+        movl    %eax, nbytes_r
+        movl    wsize(%esp), %eax       /* prepare for dist compare */
+        negl    nbytes_r                /* nbytes = -nbytes */
+        movl    window(%esp), from_r    /* from = window */
+
+        cmpl    dist_r, %eax
+        jb      .L_invalid_distance_too_far /* if (dist > wsize) */
+
+        addl    dist_r, nbytes_r        /* nbytes = dist - nbytes */
+        cmpl    $0, write(%esp)
+        jne     .L_wrap_around_window_mmx /* if (write != 0) */
+
+        subl    nbytes_r, %eax
+        addl    %eax, from_r            /* from += wsize - nbytes */
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+.L_wrap_around_window_mmx:
+#define write_r %eax
+        movl    write(%esp), write_r
+        cmpl    write_r, nbytes_r
+        jbe     .L_contiguous_in_window_mmx /* if (write >= nbytes) */
+
+        addl    wsize(%esp), from_r
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += wsize + write - nbytes */
+        subl    write_r, nbytes_r       /* nbytes -= write */
+#undef write_r
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    window(%esp), from_r    /* from = window */
+        movl    write(%esp), nbytes_r   /* nbytes = write */
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+        jmp     .L_do_copy1_mmx
+
+.L_contiguous_in_window_mmx:
+#define write_r %eax
+        addl    write_r, from_r
+        subl    nbytes_r, from_r        /* from += write - nbytes */
+#undef write_r
+
+        cmpl    nbytes_r, len_r
+        jbe     .L_do_copy1_mmx         /* if (nbytes >= len) */
+
+        subl    nbytes_r, len_r         /* len -= nbytes */
+        rep     movsb
+        movl    out_r, from_r
+        subl    dist_r, from_r          /* from = out - dist */
+
+.L_do_copy1_mmx:
+#undef nbytes_r
+#define in_r %esi
+        movl    len_r, %ecx
+        rep     movsb
+
+        movl    in(%esp), in_r          /* move in back to %esi, toss from */
+        movl    lcode(%esp), %ebx       /* move lcode back to %ebx, toss dist */
+        jmp     .L_while_test_mmx
+
+#undef hold_r
+#undef bitslong_r
+
+#endif /* USE_MMX || RUN_TIME_MMX */
+
+
+/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/
+
+.L_invalid_distance_code:
+        /* else {
+         *   strm->msg = "invalid distance code";
+         *   state->mode = BAD;
+         * }
+         */
+        movl    $.L_invalid_distance_code_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_test_for_end_of_block:
+        /* else if (op & 32) {
+         *   state->mode = TYPE;
+         *   break;
+         * }
+         */
+        testb   $32, %al
+        jz      .L_invalid_literal_length_code  /* if ((op & 32) == 0) */
+
+        movl    $0, %ecx
+        movl    $INFLATE_MODE_TYPE, %edx
+        jmp     .L_update_stream_state
+
+.L_invalid_literal_length_code:
+        /* else {
+         *   strm->msg = "invalid literal/length code";
+         *   state->mode = BAD;
+         * }
+         */
+        movl    $.L_invalid_literal_length_code_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_invalid_distance_too_far:
+        /* strm->msg = "invalid distance too far back";
+         * state->mode = BAD;
+         */
+        movl    in(%esp), in_r          /* from_r has in's reg, put in back */
+        movl    $.L_invalid_distance_too_far_msg, %ecx
+        movl    $INFLATE_MODE_BAD, %edx
+        jmp     .L_update_stream_state
+
+.L_update_stream_state:
+        /* set strm->msg = %ecx, strm->state->mode = %edx */
+        movl    strm_sp(%esp), %eax
+        testl   %ecx, %ecx              /* if (msg != NULL) */
+        jz      .L_skip_msg
+        movl    %ecx, msg_strm(%eax)    /* strm->msg = msg */
+.L_skip_msg:
+        movl    state_strm(%eax), %eax  /* state = strm->state */
+        movl    %edx, mode_state(%eax)  /* state->mode = edx (BAD | TYPE) */
+        jmp     .L_break_loop
+
+.align 32,0x90
+.L_break_loop:
+
+/*
+ * Regs:
+ *
+ * bits = %ebp when mmx, and in %ebx when non-mmx
+ * hold = %hold_mm when mmx, and in %ebp when non-mmx
+ * in   = %esi
+ * out  = %edi
+ */
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+#if defined( RUN_TIME_MMX )
+
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        jne     .L_update_next_in
+
+#endif /* RUN_TIME_MMX */
+
+        movl    %ebp, %ebx
+
+.L_update_next_in:
+
+#endif
+
+#define strm_r  %eax
+#define state_r %edx
+
+        /* len = bits >> 3;
+         * in -= len;
+         * bits -= len << 3;
+         * hold &= (1U << bits) - 1;
+         * state->hold = hold;
+         * state->bits = bits;
+         * strm->next_in = in;
+         * strm->next_out = out;
+         */
+        movl    strm_sp(%esp), strm_r
+        movl    %ebx, %ecx
+        movl    state_strm(strm_r), state_r
+        shrl    $3, %ecx
+        subl    %ecx, in_r
+        shll    $3, %ecx
+        subl    %ecx, %ebx
+        movl    out_r, next_out_strm(strm_r)
+        movl    %ebx, bits_state(state_r)
+        movl    %ebx, %ecx
+
+        leal    buf(%esp), %ebx
+        cmpl    %ebx, last(%esp)
+        jne     .L_buf_not_used         /* if buf != last */
+
+        subl    %ebx, in_r              /* in -= buf */
+        movl    next_in_strm(strm_r), %ebx
+        movl    %ebx, last(%esp)        /* last = strm->next_in */
+        addl    %ebx, in_r              /* in += strm->next_in */
+        movl    avail_in_strm(strm_r), %ebx
+        subl    $11, %ebx
+        addl    %ebx, last(%esp)    /* last = &strm->next_in[ avail_in - 11 ] */
+
+.L_buf_not_used:
+        movl    in_r, next_in_strm(strm_r)
+
+        movl    $1, %ebx
+        shll    %cl, %ebx
+        decl    %ebx
+
+#if defined( USE_MMX ) || defined( RUN_TIME_MMX )
+
+#if defined( RUN_TIME_MMX )
+
+        cmpl    $DO_USE_MMX, inflate_fast_use_mmx
+        jne     .L_update_hold
+
+#endif /* RUN_TIME_MMX */
+
+        psrlq   used_mm, hold_mm        /* hold_mm >>= last bit length */
+        movd    hold_mm, %ebp
+
+        emms
+
+.L_update_hold:
+
+#endif /* USE_MMX || RUN_TIME_MMX */
+
+        andl    %ebx, %ebp
+        movl    %ebp, hold_state(state_r)
+
+#define last_r %ebx
+
+        /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */
+        movl    last(%esp), last_r
+        cmpl    in_r, last_r
+        jbe     .L_last_is_smaller     /* if (in >= last) */
+
+        subl    in_r, last_r           /* last -= in */
+        addl    $11, last_r            /* last += 11 */
+        movl    last_r, avail_in_strm(strm_r)
+        jmp     .L_fixup_out
+.L_last_is_smaller:
+        subl    last_r, in_r           /* in -= last */
+        negl    in_r                   /* in = -in */
+        addl    $11, in_r              /* in += 11 */
+        movl    in_r, avail_in_strm(strm_r)
+
+#undef last_r
+#define end_r %ebx
+
+.L_fixup_out:
+        /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/
+        movl    end(%esp), end_r
+        cmpl    out_r, end_r
+        jbe     .L_end_is_smaller      /* if (out >= end) */
+
+        subl    out_r, end_r           /* end -= out */
+        addl    $257, end_r            /* end += 257 */
+        movl    end_r, avail_out_strm(strm_r)
+        jmp     .L_done
+.L_end_is_smaller:
+        subl    end_r, out_r           /* out -= end */
+        negl    out_r                  /* out = -out */
+        addl    $257, out_r            /* out += 257 */
+        movl    out_r, avail_out_strm(strm_r)
+
+#undef end_r
+#undef strm_r
+#undef state_r
+
+.L_done:
+        addl    $local_var_size, %esp
+        popf
+        popl    %ebx
+        popl    %ebp
+        popl    %esi
+        popl    %edi
+        ret
+
+#if defined( GAS_ELF )
+/* elf info */
+.type inflate_fast,@function
+.size inflate_fast,.-inflate_fast
+#endif
diff --git a/contrib/minizip/ChangeLogUnzip b/contrib/minizip/ChangeLogUnzip
index 9987c54..18316fc 100644
--- a/contrib/minizip/ChangeLogUnzip
+++ b/contrib/minizip/ChangeLogUnzip
@@ -1,3 +1,12 @@
+Change in 0.21: (10 Mar 03)
+- bug fixes
+
+Change in 0.17: (27 Jan 02)
+- bug fixes
+
+Change in 0.16: (19 Jan 02)
+- Support of ioapi for virtualize zip file access
+
 Change in 0.15: (19 Mar 98)
 - fix memory leak in minizip.c
 
diff --git a/contrib/minizip/Makefile b/contrib/minizip/Makefile
index a1dfc16..84eaad2 100644
--- a/contrib/minizip/Makefile
+++ b/contrib/minizip/Makefile
@@ -1,8 +1,8 @@
 CC=cc
 CFLAGS=-O -I../..
 
-UNZ_OBJS = miniunz.o unzip.o ../../libz.a
-ZIP_OBJS = minizip.o zip.o   ../../libz.a
+UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
+ZIP_OBJS = minizip.o zip.o   ioapi.o ../../libz.a
 
 .c.o:
 	$(CC) -c $(CFLAGS) $*.c
diff --git a/contrib/minizip/crypt.h b/contrib/minizip/crypt.h
new file mode 100644
index 0000000..e5bc627
--- /dev/null
+++ b/contrib/minizip/crypt.h
@@ -0,0 +1,104 @@
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+{
+    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
+                     * unpredictable manner on 16-bit systems; not a problem
+                     * with any known compiler so far, though */
+
+    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+{
+    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+    {
+      register int keyshift = (int)((*(pkeys+1)) >> 24);
+      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+    }
+    return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+{
+    *(pkeys+0) = 305419896L;
+    *(pkeys+1) = 591751049L;
+    *(pkeys+2) = 878082192L;
+    while (*passwd != '\0') {
+        update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+        passwd++;
+    }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN  12
+   /* "last resort" source for second part of crypt seed pattern */
+#  ifndef ZCR_SEED2
+#    define ZCR_SEED2 (unsigned long)3141592654L     /* use PI as default pattern */
+#  endif
+
+static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
+    const char *passwd;         /* password string */
+    unsigned char *buf;         /* where to write header */
+    int bufSize;
+    unsigned long* pkeys;
+    const unsigned long* pcrc_32_tab;
+    unsigned long crcForCrypting;
+{
+    int n;                       /* index in random header */
+    int t;                       /* temporary */
+    int c;                       /* random byte */
+    unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+    static unsigned calls = 0;   /* ensure different random header each time */
+
+    if (bufSize<RAND_HEAD_LEN)
+      return 0;
+
+    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+     * output of rand() to get less predictability, since rand() is
+     * often poorly implemented.
+     */
+    if (++calls == 1)
+    {
+        srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+    }
+    init_keys(passwd, pkeys, pcrc_32_tab);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)
+    {
+        c = (rand() >> 7) & 0xff;
+        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+    }
+    /* Encrypt random header (last two bytes is high word of crc) */
+    init_keys(passwd, pkeys, pcrc_32_tab);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++)
+    {
+        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+    }
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+    buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+    return n;
+}
+
+#endif
diff --git a/contrib/minizip/ioapi.c b/contrib/minizip/ioapi.c
new file mode 100644
index 0000000..d35d5f5
--- /dev/null
+++ b/contrib/minizip/ioapi.c
@@ -0,0 +1,177 @@
+/* ioapi.c -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+
+   Version 0.21, March 10th, 2003
+
+   Copyright (C) 1998-2003 Gilles Vollant
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET    0
+#endif
+
+voidpf ZCALLBACK fopen_file_func OF((
+   voidpf opaque,
+   const char* filename,
+   int mode));
+
+uLong ZCALLBACK fread_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   void* buf,
+   uLong size));
+
+uLong ZCALLBACK fwrite_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   const void* buf,
+   uLong size));
+
+long ZCALLBACK ftell_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+long ZCALLBACK fseek_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   uLong offset,
+   int origin));
+
+int ZCALLBACK fclose_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+int ZCALLBACK ferror_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+
+voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
+   voidpf opaque;
+   const char* filename;
+   int mode;
+{
+    FILE* file = NULL;
+    const char* mode_fopen = NULL;
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+        mode_fopen = "rb";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+        mode_fopen = "r+b";
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+        mode_fopen = "wb";
+
+    if ((filename!=NULL) && (mode_fopen != NULL))
+        file = fopen(filename, mode_fopen);
+    return file;
+}
+
+
+uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   void* buf;
+   uLong size;
+{
+    uLong ret;
+    ret = fread(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+
+uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   const void* buf;
+   uLong size;
+{
+    uLong ret;
+    ret = fwrite(buf, 1, (size_t)size, (FILE *)stream);
+    return ret;
+}
+
+long ZCALLBACK ftell_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    long ret;
+    ret = ftell((FILE *)stream);
+    return ret;
+}
+
+long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
+   voidpf opaque;
+   voidpf stream;
+   uLong offset;
+   int origin;
+{
+    int fseek_origin=0;
+    long ret;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        fseek_origin = SEEK_CUR;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        fseek_origin = SEEK_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        fseek_origin = SEEK_SET;
+        break;
+    default: return -1;
+    }
+    ret = 0;
+    fseek((FILE *)stream, offset, fseek_origin);
+    return ret;
+}
+
+int ZCALLBACK fclose_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret;
+    ret = fclose((FILE *)stream);
+    return ret;
+}
+
+int ZCALLBACK ferror_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret;
+    ret = ferror((FILE *)stream);
+    return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = fopen_file_func;
+    pzlib_filefunc_def->zread_file = fread_file_func;
+    pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+    pzlib_filefunc_def->ztell_file = ftell_file_func;
+    pzlib_filefunc_def->zseek_file = fseek_file_func;
+    pzlib_filefunc_def->zclose_file = fclose_file_func;
+    pzlib_filefunc_def->zerror_file = ferror_file_func;
+    pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/contrib/minizip/ioapi.h b/contrib/minizip/ioapi.h
new file mode 100644
index 0000000..f30fe7a
--- /dev/null
+++ b/contrib/minizip/ioapi.h
@@ -0,0 +1,75 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+
+   Version 0.21, March 10th, 2003
+
+   Copyright (C) 1998-2003 Gilles Vollant
+*/
+
+#ifndef _ZLIBIOAPI_H
+#define _ZLIBIOAPI_H
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ      (1)
+#define ZLIB_FILEFUNC_MODE_WRITE     (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE   (8)
+
+
+#ifndef ZCALLBACK
+
+#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+#define ZCALLBACK CALLBACK
+#else
+#define ZCALLBACK
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong  (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong  (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef long   (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long   (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+typedef int    (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int    (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef struct zlib_filefunc_def_s
+{
+    open_file_func      zopen_file;
+    read_file_func      zread_file;
+    write_file_func     zwrite_file;
+    tell_file_func      ztell_file;
+    seek_file_func      zseek_file;
+    close_file_func     zclose_file;
+    testerror_file_func zerror_file;
+    voidpf              opaque;
+} zlib_filefunc_def;
+
+
+
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
+#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
+#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
+#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
+#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/contrib/minizip/iowin32.c b/contrib/minizip/iowin32.c
new file mode 100644
index 0000000..f1f5546
--- /dev/null
+++ b/contrib/minizip/iowin32.c
@@ -0,0 +1,271 @@
+/* iowin32.c -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+   This IO API version uses the Win32 API (for Microsoft Windows)
+
+   Version 0.21, March 10th, 2003
+
+   Copyright (C) 1998-2003 Gilles Vollant
+*/
+
+#include <windows.h>
+#include <stdlib.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+#include "iowin32.h"
+
+#ifndef INVALID_HANDLE_VALUE
+#define INVALID_HANDLE_VALUE (0xFFFFFFFF)
+#endif
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
+voidpf ZCALLBACK win32_open_file_func OF((
+   voidpf opaque,
+   const char* filename,
+   int mode));
+
+uLong ZCALLBACK win32_read_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   void* buf,
+   uLong size));
+
+uLong ZCALLBACK win32_write_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   const void* buf,
+   uLong size));
+
+long ZCALLBACK win32_tell_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+long ZCALLBACK win32_seek_file_func OF((
+   voidpf opaque,
+   voidpf stream,
+   uLong offset,
+   int origin));
+
+long ZCALLBACK win32_close_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+int ZCALLBACK win32_error_file_func OF((
+   voidpf opaque,
+   voidpf stream));
+
+typedef struct
+{
+    HANDLE hf;
+    int error;
+} WIN32FILE_IOWIN;
+
+voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
+   voidpf opaque;
+   const char* filename;
+   int mode;
+{
+    const char* mode_fopen = NULL;
+    DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
+    HANDLE hFile = 0;
+    voidpf ret=NULL;
+
+    dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
+
+    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+    {
+        dwDesiredAccess = GENERIC_READ;
+        dwCreationDisposition = OPEN_EXISTING;
+        dwShareMode = FILE_SHARE_READ;
+    }
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+    {
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        dwCreationDisposition = OPEN_EXISTING;
+    }
+    else
+    if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+    {
+        dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
+        dwCreationDisposition = CREATE_ALWAYS;
+    }
+
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
+                      dwCreationDisposition, dwFlagsAndAttributes, NULL);
+
+    if (hFile == INVALID_HANDLE_VALUE)
+        hFile = NULL;
+
+    if (hFile != NULL)
+    {
+        WIN32FILE_IOWIN w32fiow;
+        w32fiow.hf = hFile;
+        w32fiow.error = 0;
+        ret = malloc(sizeof(WIN32FILE_IOWIN));
+        if (ret==NULL)
+            CloseHandle(hFile);
+        else *((WIN32FILE_IOWIN*)ret) = w32fiow;
+    }
+    return ret;
+}
+
+
+uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   void* buf;
+   uLong size;
+{
+    uLong ret=0;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    if (hFile != NULL)
+        if (!ReadFile(hFile, buf, size, &ret, NULL))
+        {
+            DWORD dwErr = GetLastError();
+            if (dwErr == ERROR_HANDLE_EOF)
+                dwErr = 0;
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+        }
+
+    return ret;
+}
+
+
+uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
+   voidpf opaque;
+   voidpf stream;
+   const void* buf;
+   uLong size;
+{
+    uLong ret=0;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+
+    if (hFile !=NULL)
+        if (!WriteFile(hFile, buf, size, &ret, NULL))
+        {
+            DWORD dwErr = GetLastError();
+            if (dwErr == ERROR_HANDLE_EOF)
+                dwErr = 0;
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+        }
+
+    return ret;
+}
+
+long ZCALLBACK win32_tell_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    long ret=-1;
+    HANDLE hFile = NULL;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    if (hFile != NULL)
+    {
+        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
+        if (dwSet == INVALID_SET_FILE_POINTER)
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = -1;
+        }
+        else
+            ret=(long)dwSet;
+    }
+    return ret;
+}
+
+long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
+   voidpf opaque;
+   voidpf stream;
+   uLong offset;
+   int origin;
+{
+    DWORD dwMoveMethod=0xFFFFFFFF;
+    HANDLE hFile = NULL;
+
+    long ret=-1;
+    if (stream!=NULL)
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+    switch (origin)
+    {
+    case ZLIB_FILEFUNC_SEEK_CUR :
+        dwMoveMethod = FILE_CURRENT;
+        break;
+    case ZLIB_FILEFUNC_SEEK_END :
+        dwMoveMethod = FILE_END;
+        break;
+    case ZLIB_FILEFUNC_SEEK_SET :
+        dwMoveMethod = FILE_BEGIN;
+        break;
+    default: return -1;
+    }
+
+    if (hFile != NULL)
+    {
+        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
+        if (dwSet == INVALID_SET_FILE_POINTER)
+        {
+            DWORD dwErr = GetLastError();
+            ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
+            ret = -1;
+        }
+        else
+            ret=0;
+    }
+    return ret;
+}
+
+long ZCALLBACK win32_close_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    long ret=-1;
+
+    if (stream!=NULL)
+    {
+        HANDLE hFile;
+        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
+        if (hFile != NULL)
+        {
+            CloseHandle(hFile);
+            ret=0;
+        }
+        free(stream);
+    }
+    return ret;
+}
+
+int ZCALLBACK win32_error_file_func (opaque, stream)
+   voidpf opaque;
+   voidpf stream;
+{
+    int ret=-1;
+    if (stream!=NULL)
+    {
+        ret = ((WIN32FILE_IOWIN*)stream) -> error;
+    }
+    return ret;
+}
+
+void fill_win32_filefunc (pzlib_filefunc_def)
+  zlib_filefunc_def* pzlib_filefunc_def;
+{
+    pzlib_filefunc_def->zopen_file = win32_open_file_func;
+    pzlib_filefunc_def->zread_file = win32_read_file_func;
+    pzlib_filefunc_def->zwrite_file = win32_write_file_func;
+    pzlib_filefunc_def->ztell_file = win32_tell_file_func;
+    pzlib_filefunc_def->zseek_file = win32_seek_file_func;
+    pzlib_filefunc_def->zclose_file = win32_close_file_func;
+    pzlib_filefunc_def->zerror_file = win32_error_file_func;
+    pzlib_filefunc_def->opaque=NULL;
+}
diff --git a/contrib/minizip/iowin32.h b/contrib/minizip/iowin32.h
new file mode 100644
index 0000000..d2f5e37
--- /dev/null
+++ b/contrib/minizip/iowin32.h
@@ -0,0 +1,19 @@
+/* iowin32.h -- IO base function header for compress/uncompress .zip
+   files using zlib + zip or unzip API
+   This IO API version uses the Win32 API (for Microsoft Windows)
+
+   Version 0.21, March 10th, 2003
+
+   Copyright (C) 1998-2003 Gilles Vollant
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/minizip/miniunz.c b/contrib/minizip/miniunz.c
index f3b7832..938d4ef 100644
--- a/contrib/minizip/miniunz.c
+++ b/contrib/minizip/miniunz.c
@@ -17,7 +17,12 @@
 
 #define CASESENSITIVITY (0)
 #define WRITEBUFFERSIZE (8192)
+#define MAXFILENAME (256)
 
+#ifdef WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
 /*
   mini unzip, demo of unzip package
 
@@ -34,9 +39,9 @@
     dosdate : the new date at the MSDos format (4 bytes)
     tmu_date : the SAME new date at the tm_unz format */
 void change_file_date(filename,dosdate,tmu_date)
-	const char *filename;
-	uLong dosdate;
-	tm_unz tmu_date;
+    const char *filename;
+    uLong dosdate;
+    tm_unz tmu_date;
 {
 #ifdef WIN32
   HANDLE hFile;
@@ -75,17 +80,17 @@
    As I don't know well Unix, I wait feedback for the unix portion */
 
 int mymkdir(dirname)
-	const char* dirname;
+    const char* dirname;
 {
     int ret=0;
 #ifdef WIN32
-	ret = mkdir(dirname);
+    ret = mkdir(dirname);
 #else
 #ifdef unix
-	ret = mkdir (dirname,0775);
+    ret = mkdir (dirname,0775);
 #endif
 #endif
-	return ret;
+    return ret;
 }
 
 int makedir (newdir)
@@ -93,14 +98,14 @@
 {
   char *buffer ;
   char *p;
-  int  len = strlen(newdir);  
+  int  len = (int)strlen(newdir);
 
-  if (len <= 0) 
+  if (len <= 0)
     return 0;
 
   buffer = (char*)malloc(len+1);
   strcpy(buffer,newdir);
-  
+
   if (buffer[len-1] == '/') {
     buffer[len-1] = '\0';
   }
@@ -135,104 +140,105 @@
 
 void do_banner()
 {
-	printf("MiniUnz 0.15, demo of zLib + Unz package written by Gilles Vollant\n");
-	printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n");
+    printf("MiniUnz 0.15, demo of zLib + Unz package written by Gilles Vollant\n");
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
 }
 
 void do_help()
-{	
-	printf("Usage : miniunz [-exvlo] file.zip [file_to_extract]\n\n") ;
+{
+    printf("Usage : miniunz [-exvlo] file.zip [file_to_extract]\n\n") ;
 }
 
 
 int do_list(uf)
-	unzFile uf;
+    unzFile uf;
 {
-	uLong i;
-	unz_global_info gi;
-	int err;
+    uLong i;
+    unz_global_info gi;
+    int err;
 
-	err = unzGetGlobalInfo (uf,&gi);
-	if (err!=UNZ_OK)
-		printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+    err = unzGetGlobalInfo (uf,&gi);
+    if (err!=UNZ_OK)
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
     printf(" Length  Method   Size  Ratio   Date    Time   CRC-32     Name\n");
     printf(" ------  ------   ----  -----   ----    ----   ------     ----\n");
-	for (i=0;i<gi.number_entry;i++)
-	{
-		char filename_inzip[256];
-		unz_file_info file_info;
-		uLong ratio=0;
-		const char *string_method;
-		err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
-		if (err!=UNZ_OK)
-		{
-			printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
-			break;
-		}
-		if (file_info.uncompressed_size>0)
-			ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;
+    for (i=0;i<gi.number_entry;i++)
+    {
+        char filename_inzip[256];
+        unz_file_info file_info;
+        uLong ratio=0;
+        const char *string_method;
+        err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+        if (err!=UNZ_OK)
+        {
+            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+            break;
+        }
+        if (file_info.uncompressed_size>0)
+            ratio = (file_info.compressed_size*100)/file_info.uncompressed_size;
 
-		if (file_info.compression_method==0)
-			string_method="Stored";
-		else
-		if (file_info.compression_method==Z_DEFLATED)
-		{
-			uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
-			if (iLevel==0)
-			  string_method="Defl:N";
-			else if (iLevel==1)
-			  string_method="Defl:X";
-			else if ((iLevel==2) || (iLevel==3))
-			  string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
-		}
-		else
-			string_method="Unkn. ";
+        if (file_info.compression_method==0)
+            string_method="Stored";
+        else
+        if (file_info.compression_method==Z_DEFLATED)
+        {
+            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
+            if (iLevel==0)
+              string_method="Defl:N";
+            else if (iLevel==1)
+              string_method="Defl:X";
+            else if ((iLevel==2) || (iLevel==3))
+              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
+        }
+        else
+            string_method="Unkn. ";
 
-		printf("%7lu  %6s %7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
-			    file_info.uncompressed_size,string_method,file_info.compressed_size,
-				ratio,
-				(uLong)file_info.tmu_date.tm_mon + 1,
+        printf("%7lu  %6s %7lu %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
+                file_info.uncompressed_size,string_method,file_info.compressed_size,
+                ratio,
+                (uLong)file_info.tmu_date.tm_mon + 1,
                 (uLong)file_info.tmu_date.tm_mday,
-				(uLong)file_info.tmu_date.tm_year % 100,
-				(uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
-				(uLong)file_info.crc,filename_inzip);
-		if ((i+1)<gi.number_entry)
-		{
-			err = unzGoToNextFile(uf);
-			if (err!=UNZ_OK)
-			{
-				printf("error %d with zipfile in unzGoToNextFile\n",err);
-				break;
-			}
-		}
-	}
+                (uLong)file_info.tmu_date.tm_year % 100,
+                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
+                (uLong)file_info.crc,filename_inzip);
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
 
-	return 0;
+    return 0;
 }
 
 
-int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite)
-	unzFile uf;
-	const int* popt_extract_without_path;
+int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
+    unzFile uf;
+    const int* popt_extract_without_path;
     int* popt_overwrite;
+    const char* password;
 {
-	char filename_inzip[256];
-	char* filename_withoutpath;
-	char* p;
+    char filename_inzip[256];
+    char* filename_withoutpath;
+    char* p;
     int err=UNZ_OK;
     FILE *fout=NULL;
     void* buf;
     uInt size_buf;
-	
-	unz_file_info file_info;
-	uLong ratio=0;
-	err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
 
-	if (err!=UNZ_OK)
-	{
-		printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
-		return err;
-	}
+    unz_file_info file_info;
+    uLong ratio=0;
+    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+
+    if (err!=UNZ_OK)
+    {
+        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
+        return err;
+    }
 
     size_buf = WRITEBUFFERSIZE;
     buf = (void*)malloc(size_buf);
@@ -242,71 +248,71 @@
         return UNZ_INTERNALERROR;
     }
 
-	p = filename_withoutpath = filename_inzip;
-	while ((*p) != '\0')
-	{
-		if (((*p)=='/') || ((*p)=='\\'))
-			filename_withoutpath = p+1;
-		p++;
-	}
+    p = filename_withoutpath = filename_inzip;
+    while ((*p) != '\0')
+    {
+        if (((*p)=='/') || ((*p)=='\\'))
+            filename_withoutpath = p+1;
+        p++;
+    }
 
-	if ((*filename_withoutpath)=='\0')
-	{
-		if ((*popt_extract_without_path)==0)
-		{
-			printf("creating directory: %s\n",filename_inzip);
-			mymkdir(filename_inzip);
-		}
-	}
-	else
-	{
-		const char* write_filename;
-		int skip=0;
+    if ((*filename_withoutpath)=='\0')
+    {
+        if ((*popt_extract_without_path)==0)
+        {
+            printf("creating directory: %s\n",filename_inzip);
+            mymkdir(filename_inzip);
+        }
+    }
+    else
+    {
+        const char* write_filename;
+        int skip=0;
 
-		if ((*popt_extract_without_path)==0)
-			write_filename = filename_inzip;
-		else
-			write_filename = filename_withoutpath;
+        if ((*popt_extract_without_path)==0)
+            write_filename = filename_inzip;
+        else
+            write_filename = filename_withoutpath;
 
-		err = unzOpenCurrentFile(uf);
-		if (err!=UNZ_OK)
-		{
-			printf("error %d with zipfile in unzOpenCurrentFile\n",err);
-		}
+        err = unzOpenCurrentFilePassword(uf,password);
+        if (err!=UNZ_OK)
+        {
+            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
+        }
 
-		if (((*popt_overwrite)==0) && (err==UNZ_OK))
-		{
-			char rep;
-			FILE* ftestexist;
-			ftestexist = fopen(write_filename,"rb");
-			if (ftestexist!=NULL)
-			{
-				fclose(ftestexist);
-				do
-				{
-					char answer[128];
-					printf("The file %s exist. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
-					scanf("%1s",answer);
-					rep = answer[0] ;
-					if ((rep>='a') && (rep<='z'))
-						rep -= 0x20;
-				}
-				while ((rep!='Y') && (rep!='N') && (rep!='A'));
-			}
+        if (((*popt_overwrite)==0) && (err==UNZ_OK))
+        {
+            char rep=0;
+            FILE* ftestexist;
+            ftestexist = fopen(write_filename,"rb");
+            if (ftestexist!=NULL)
+            {
+                fclose(ftestexist);
+                do
+                {
+                    char answer[128];
+                    printf("The file %s exist. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
+                    scanf("%1s",answer);
+                    rep = answer[0] ;
+                    if ((rep>='a') && (rep<='z'))
+                        rep -= 0x20;
+                }
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));
+            }
 
-			if (rep == 'N')
-				skip = 1;
+            if (rep == 'N')
+                skip = 1;
 
-			if (rep == 'A')
-				*popt_overwrite=1;
-		}
+            if (rep == 'A')
+                *popt_overwrite=1;
+        }
 
-		if ((skip==0) && (err==UNZ_OK))
-		{
-			fout=fopen(write_filename,"wb");
+        if ((skip==0) && (err==UNZ_OK))
+        {
+            fout=fopen(write_filename,"wb");
 
             /* some zipfile don't contain directory alone before file */
-            if ((fout==NULL) && ((*popt_extract_without_path)==0) && 
+            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
                                 (filename_withoutpath!=(char*)filename_inzip))
             {
                 char c=*(filename_withoutpath-1);
@@ -316,95 +322,100 @@
                 fout=fopen(write_filename,"wb");
             }
 
-			if (fout==NULL)
-			{
-				printf("error opening %s\n",write_filename);
-			}
-		}
+            if (fout==NULL)
+            {
+                printf("error opening %s\n",write_filename);
+            }
+        }
 
-		if (fout!=NULL)
-		{
-			printf(" extracting: %s\n",write_filename);
+        if (fout!=NULL)
+        {
+            printf(" extracting: %s\n",write_filename);
 
-			do
-			{
-				err = unzReadCurrentFile(uf,buf,size_buf);
-				if (err<0)	
-				{
-					printf("error %d with zipfile in unzReadCurrentFile\n",err);
-					break;
-				}
-				if (err>0)
-					if (fwrite(buf,err,1,fout)!=1)
-					{
-						printf("error in writing extracted file\n");
+            do
+            {
+                err = unzReadCurrentFile(uf,buf,size_buf);
+                if (err<0)
+                {
+                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
+                    break;
+                }
+                if (err>0)
+                    if (fwrite(buf,err,1,fout)!=1)
+                    {
+                        printf("error in writing extracted file\n");
                         err=UNZ_ERRNO;
-						break;
-					}
-			}
-			while (err>0);
-			fclose(fout);
-			if (err==0) 
-				change_file_date(write_filename,file_info.dosDate,
-					             file_info.tmu_date);
-		}
+                        break;
+                    }
+            }
+            while (err>0);
+            if (fout)
+                    fclose(fout);
+
+            if (err==0)
+                change_file_date(write_filename,file_info.dosDate,
+                                 file_info.tmu_date);
+        }
 
         if (err==UNZ_OK)
         {
-		    err = unzCloseCurrentFile (uf);
-		    if (err!=UNZ_OK)
-		    {
-			    printf("error %d with zipfile in unzCloseCurrentFile\n",err);
-		    }
+            err = unzCloseCurrentFile (uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzCloseCurrentFile\n",err);
+            }
         }
         else
-            unzCloseCurrentFile(uf); /* don't lose the error */       
-	}
+            unzCloseCurrentFile(uf); /* don't lose the error */
+    }
 
-    free(buf);    
+    free(buf);
     return err;
 }
 
 
-int do_extract(uf,opt_extract_without_path,opt_overwrite)
-	unzFile uf;
-	int opt_extract_without_path;
+int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
+    unzFile uf;
+    int opt_extract_without_path;
     int opt_overwrite;
+    const char* password;
 {
-	uLong i;
-	unz_global_info gi;
-	int err;
-	FILE* fout=NULL;	
+    uLong i;
+    unz_global_info gi;
+    int err;
+    FILE* fout=NULL;
 
-	err = unzGetGlobalInfo (uf,&gi);
-	if (err!=UNZ_OK)
-		printf("error %d with zipfile in unzGetGlobalInfo \n",err);
+    err = unzGetGlobalInfo (uf,&gi);
+    if (err!=UNZ_OK)
+        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
 
-	for (i=0;i<gi.number_entry;i++)
-	{
+    for (i=0;i<gi.number_entry;i++)
+    {
         if (do_extract_currentfile(uf,&opt_extract_without_path,
-                                      &opt_overwrite) != UNZ_OK)
+                                      &opt_overwrite,
+                                      password) != UNZ_OK)
             break;
 
-		if ((i+1)<gi.number_entry)
-		{
-			err = unzGoToNextFile(uf);
-			if (err!=UNZ_OK)
-			{
-				printf("error %d with zipfile in unzGoToNextFile\n",err);
-				break;
-			}
-		}
-	}
+        if ((i+1)<gi.number_entry)
+        {
+            err = unzGoToNextFile(uf);
+            if (err!=UNZ_OK)
+            {
+                printf("error %d with zipfile in unzGoToNextFile\n",err);
+                break;
+            }
+        }
+    }
 
-	return 0;
+    return 0;
 }
 
-int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite)
-	unzFile uf;
-	const char* filename;
-	int opt_extract_without_path;
+int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
+    unzFile uf;
+    const char* filename;
+    int opt_extract_without_path;
     int opt_overwrite;
+    const char* password;
 {
     int err = UNZ_OK;
     if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
@@ -414,7 +425,8 @@
     }
 
     if (do_extract_currentfile(uf,&opt_extract_without_path,
-                                      &opt_overwrite) == UNZ_OK)
+                                      &opt_overwrite,
+                                      password) == UNZ_OK)
         return 0;
     else
         return 1;
@@ -422,87 +434,110 @@
 
 
 int main(argc,argv)
-	int argc;
-	char *argv[];
+    int argc;
+    char *argv[];
 {
-	const char *zipfilename=NULL;
+    const char *zipfilename=NULL;
     const char *filename_to_extract=NULL;
-	int i;
-	int opt_do_list=0;
-	int opt_do_extract=1;
-	int opt_do_extract_withoutpath=0;
-	int opt_overwrite=0;
-	char filename_try[512];
-	unzFile uf=NULL;
+    const char *password=NULL;
+    char filename_try[MAXFILENAME+16] = "";
+    int i;
+    int opt_do_list=0;
+    int opt_do_extract=1;
+    int opt_do_extract_withoutpath=0;
+    int opt_overwrite=0;
+    unzFile uf=NULL;
 
-	do_banner();
-	if (argc==1)
-	{
-		do_help();
-		exit(0);
-	}
-	else
-	{
-		for (i=1;i<argc;i++)
-		{
-			if ((*argv[i])=='-')
-			{
-				const char *p=argv[i]+1;
-				
-				while ((*p)!='\0')
-				{			
-					char c=*(p++);;
-					if ((c=='l') || (c=='L'))
-						opt_do_list = 1;
-					if ((c=='v') || (c=='V'))
-						opt_do_list = 1;
-					if ((c=='x') || (c=='X'))
-						opt_do_extract = 1;
-					if ((c=='e') || (c=='E'))
-						opt_do_extract = opt_do_extract_withoutpath = 1;
-					if ((c=='o') || (c=='O'))
-						opt_overwrite=1;
-				}
-			}
-			else
+    do_banner();
+    if (argc==1)
+    {
+        do_help();
+        return 0;
+    }
+    else
+    {
+        for (i=1;i<argc;i++)
+        {
+            if ((*argv[i])=='-')
             {
-				if (zipfilename == NULL)
-					zipfilename = argv[i];
+                const char *p=argv[i]+1;
+
+                while ((*p)!='\0')
+                {
+                    char c=*(p++);;
+                    if ((c=='l') || (c=='L'))
+                        opt_do_list = 1;
+                    if ((c=='v') || (c=='V'))
+                        opt_do_list = 1;
+                    if ((c=='x') || (c=='X'))
+                        opt_do_extract = 1;
+                    if ((c=='e') || (c=='E'))
+                        opt_do_extract = opt_do_extract_withoutpath = 1;
+                    if ((c=='o') || (c=='O'))
+                        opt_overwrite=1;
+                    if (((c=='p') || (c=='P')) && (i+1<argc))
+                    {
+                        password=argv[i+1];
+                        i++;
+                    }
+                }
+            }
+            else
+            {
+                if (zipfilename == NULL)
+                    zipfilename = argv[i];
                 else if (filename_to_extract==NULL)
                         filename_to_extract = argv[i] ;
             }
-		}
-	}
+        }
+    }
 
-	if (zipfilename!=NULL)
-	{
-		strcpy(filename_try,zipfilename);
-		uf = unzOpen(zipfilename);
-		if (uf==NULL)
-		{
-			strcat(filename_try,".zip");
-			uf = unzOpen(filename_try);
-		}
-	}
+    if (zipfilename!=NULL)
+    {
 
-	if (uf==NULL)
-	{
-		printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
-		exit (1);
-	}
+        #ifdef USEWIN32IOAPI
+        zlib_filefunc_def ffunc;
+        #endif
+
+        strncpy(filename_try, zipfilename,MAXFILENAME-1);
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+        #ifdef USEWIN32IOAPI
+        fill_win32_filefunc(&ffunc);
+        uf = unzOpen2(zipfilename,&ffunc);
+        #else
+        uf = unzOpen(zipfilename);
+        #endif
+        if (uf==NULL)
+        {
+            strcat(filename_try,".zip");
+            #ifdef USEWIN32IOAPI
+            uf = unzOpen2(filename_try,&ffunc);
+            #else
+            uf = unzOpen(filename_try);
+            #endif
+        }
+    }
+
+    if (uf==NULL)
+    {
+        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
+        return 1;
+    }
     printf("%s opened\n",filename_try);
 
-	if (opt_do_list==1)
-		return do_list(uf);
-	else if (opt_do_extract==1)
+    if (opt_do_list==1)
+        return do_list(uf);
+    else if (opt_do_extract==1)
     {
         if (filename_to_extract == NULL)
-		    return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite);
+            return do_extract(uf,opt_do_extract_withoutpath,opt_overwrite,password);
         else
             return do_extract_onefile(uf,filename_to_extract,
-                                      opt_do_extract_withoutpath,opt_overwrite);
+                                      opt_do_extract_withoutpath,opt_overwrite,password);
     }
-	unzCloseCurrentFile(uf);
+    unzCloseCurrentFile(uf);
 
-	return 0;  /* to avoid warning */
+    return 0;
 }
diff --git a/contrib/minizip/minizip.c b/contrib/minizip/minizip.c
index 5e492d2..5792a1e 100644
--- a/contrib/minizip/minizip.c
+++ b/contrib/minizip/minizip.c
@@ -17,6 +17,12 @@
 
 #include "zip.h"
 
+#ifdef WIN32
+#define USEWIN32IOAPI
+#include "iowin32.h"
+#endif
+
+
 
 #define WRITEBUFFERSIZE (16384)
 #define MAXFILENAME (256)
@@ -55,12 +61,16 @@
   struct stat s;        /* results of stat() */
   struct tm* filedate;
   time_t tm_t=0;
-  
+
   if (strcmp(f,"-")!=0)
   {
-    char name[MAXFILENAME];
+    char name[MAXFILENAME+1];
     int len = strlen(f);
-    strcpy(name, f);
+
+    strncpy(name, f,MAXFILENAME-1);
+    /* strncpy doesnt append the trailing NULL, of the string is too long. */
+    name[ MAXFILENAME ] = '\0';
+
     if (name[len - 1] == '/')
       name[len - 1] = '\0';
     /* not all systems allow stat'ing a file with / appended */
@@ -98,10 +108,10 @@
 int check_exist_file(filename)
     const char* filename;
 {
-	FILE* ftestexist;
+    FILE* ftestexist;
     int ret = 1;
-	ftestexist = fopen(filename,"rb");
-	if (ftestexist==NULL)
+    ftestexist = fopen(filename,"rb");
+    if (ftestexist==NULL)
         ret = 0;
     else
         fclose(ftestexist);
@@ -110,59 +120,107 @@
 
 void do_banner()
 {
-	printf("MiniZip 0.15, demo of zLib + Zip package written by Gilles Vollant\n");
-	printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n");
+    printf("MiniZip 0.15, demo of zLib + Zip package written by Gilles Vollant\n");
+    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
 }
 
 void do_help()
-{	
-	printf("Usage : minizip [-o] file.zip [files_to_add]\n\n") ;
+{
+    printf("Usage : minizip [-o] file.zip [files_to_add]\n\n") ;
+}
+
+/* calculate the CRC32 of a file,
+   because to encrypt a file, we need known the CRC32 of the file before */
+int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
+{
+   unsigned long calculate_crc=0;
+   int err=ZIP_OK;
+   FILE * fin = fopen(filenameinzip,"rb");
+   unsigned long size_read = 0;
+   unsigned long total_read = 0;
+   if (fin==NULL)
+   {
+       err = ZIP_ERRNO;
+   }
+
+    if (err == ZIP_OK)
+        do
+        {
+            err = ZIP_OK;
+            size_read = (int)fread(buf,1,size_buf,fin);
+            if (size_read < size_buf)
+                if (feof(fin)==0)
+            {
+                printf("error in reading %s\n",filenameinzip);
+                err = ZIP_ERRNO;
+            }
+
+            if (size_read>0)
+                calculate_crc = crc32(calculate_crc,buf,size_read);
+            total_read += size_read;
+
+        } while ((err == ZIP_OK) && (size_read>0));
+
+    if (fin)
+        fclose(fin);
+
+    *result_crc=calculate_crc;
+    printf("file %s crc %x\n",filenameinzip,calculate_crc);
+    return err;
 }
 
 int main(argc,argv)
-	int argc;
-	char *argv[];
+    int argc;
+    char *argv[];
 {
-	int i;
-	int opt_overwrite=0;
+    int i;
+    int opt_overwrite=0;
     int opt_compress_level=Z_DEFAULT_COMPRESSION;
     int zipfilenamearg = 0;
-	char filename_try[MAXFILENAME];
+    char filename_try[MAXFILENAME+16];
     int zipok;
     int err=0;
     int size_buf=0;
-    void* buf=NULL,
+    void* buf=NULL;
+    const char* password=NULL;
 
 
-	do_banner();
-	if (argc==1)
-	{
-		do_help();
-		exit(0);
+    do_banner();
+    if (argc==1)
+    {
+        do_help();
         return 0;
-	}
-	else
-	{
-		for (i=1;i<argc;i++)
-		{
-			if ((*argv[i])=='-')
-			{
-				const char *p=argv[i]+1;
-				
-				while ((*p)!='\0')
-				{			
-					char c=*(p++);;
-					if ((c=='o') || (c=='O'))
-						opt_overwrite = 1;
+    }
+    else
+    {
+        for (i=1;i<argc;i++)
+        {
+            if ((*argv[i])=='-')
+            {
+                const char *p=argv[i]+1;
+
+                while ((*p)!='\0')
+                {
+                    char c=*(p++);;
+                    if ((c=='o') || (c=='O'))
+                        opt_overwrite = 1;
+                    if ((c=='a') || (c=='A'))
+                        opt_overwrite = 2;
                     if ((c>='0') && (c<='9'))
                         opt_compress_level = c-'0';
-				}
-			}
-			else
-				if (zipfilenamearg == 0)
+
+                    if (((c=='p') || (c=='P')) && (i+1<argc))
+                    {
+                        password=argv[i+1];
+                        i++;
+                    }
+                }
+            }
+            else
+                if (zipfilenamearg == 0)
                     zipfilenamearg = i ;
-		}
-	}
+        }
+    }
 
     size_buf = WRITEBUFFERSIZE;
     buf = (void*)malloc(size_buf);
@@ -172,16 +230,19 @@
         return ZIP_INTERNALERROR;
     }
 
-	if (zipfilenamearg==0)
+    if (zipfilenamearg==0)
         zipok=0;
     else
-	{
+    {
         int i,len;
         int dot_found=0;
 
         zipok = 1 ;
-		strcpy(filename_try,argv[zipfilenamearg]);
-        len=strlen(filename_try);
+        strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
+        /* strncpy doesnt append the trailing NULL, of the string is too long. */
+        filename_try[ MAXFILENAME ] = '\0';
+
+        len=(int)strlen(filename_try);
         for (i=0;i<len;i++)
             if (filename_try[i]=='.')
                 dot_found=1;
@@ -189,36 +250,52 @@
         if (dot_found==0)
             strcat(filename_try,".zip");
 
+        if (opt_overwrite==2)
+        {
+            /* if the file don't exist, we not append file */
+            if (check_exist_file(filename_try)==0)
+                opt_overwrite=1;
+        }
+        else
         if (opt_overwrite==0)
             if (check_exist_file(filename_try)!=0)
-			{
-                char rep;
-				do
-				{
-					char answer[128];
-					printf("The file %s exist. Overwrite ? [y]es, [n]o : ",filename_try);
-					scanf("%1s",answer);
-					rep = answer[0] ;
-					if ((rep>='a') && (rep<='z'))
-						rep -= 0x20;
-				}
-				while ((rep!='Y') && (rep!='N'));
+            {
+                char rep=0;
+                do
+                {
+                    char answer[128];
+                    printf("The file %s exist. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
+                    scanf("%1s",answer);
+                    rep = answer[0] ;
+                    if ((rep>='a') && (rep<='z'))
+                        rep -= 0x20;
+                }
+                while ((rep!='Y') && (rep!='N') && (rep!='A'));
                 if (rep=='N')
                     zipok = 0;
-			}
+                if (rep=='A')
+                    opt_overwrite = 2;
+            }
     }
 
     if (zipok==1)
     {
         zipFile zf;
         int errclose;
-        zf = zipOpen(filename_try,0);
+        #ifdef USEWIN32IOAPI
+        zlib_filefunc_def ffunc;
+        fill_win32_filefunc(&ffunc);
+        zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
+        #else
+        zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
+        #endif
+
         if (zf == NULL)
         {
             printf("error opening %s\n",filename_try);
             err= ZIP_ERRNO;
         }
-        else 
+        else
             printf("creating %s\n",filename_try);
 
         for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
@@ -229,19 +306,31 @@
                 int size_read;
                 const char* filenameinzip = argv[i];
                 zip_fileinfo zi;
+                unsigned long crcFile=0;
 
-                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = 
-                zi.tmz_date.tm_mday = zi.tmz_date.tm_min = zi.tmz_date.tm_year = 0;
+                zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
+                zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
                 zi.dosDate = 0;
                 zi.internal_fa = 0;
                 zi.external_fa = 0;
                 filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
 
-
+/*
                 err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
-                                 NULL,0,NULL,0,NULL /* comment*/,
+                                 NULL,0,NULL,0,NULL / * comment * /,
                                  (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                  opt_compress_level);
+*/
+                if ((password != NULL) && (err==ZIP_OK))
+                    err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
+
+                err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
+                                 NULL,0,NULL,0,NULL /* comment*/,
+                                 (opt_compress_level != 0) ? Z_DEFLATED : 0,
+                                 opt_compress_level,0,
+                                 /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 password,crcFile);
 
                 if (err != ZIP_OK)
                     printf("error in opening %s in zipfile\n",filenameinzip);
@@ -259,7 +348,7 @@
                     do
                     {
                         err = ZIP_OK;
-                        size_read = fread(buf,1,size_buf,fin);
+                        size_read = (int)fread(buf,1,size_buf,fin);
                         if (size_read < size_buf)
                             if (feof(fin)==0)
                         {
@@ -275,15 +364,17 @@
                                 printf("error in writing %s in the zipfile\n",
                                                  filenameinzip);
                             }
-                                
+
                         }
                     } while ((err == ZIP_OK) && (size_read>0));
 
-                fclose(fin);
+                if (fin)
+                    fclose(fin);
+
                 if (err<0)
                     err=ZIP_ERRNO;
                 else
-                {                    
+                {
                     err = zipCloseFileInZip(zf);
                     if (err!=ZIP_OK)
                         printf("error in closing %s in the zipfile\n",
@@ -297,6 +388,5 @@
    }
 
     free(buf);
-    exit(0);
-	return 0;  /* to avoid warning */
+    return 0;
 }
diff --git a/contrib/minizip/readme.txt b/contrib/minizip/readme.txt
deleted file mode 100644
index 1fc023c..0000000
--- a/contrib/minizip/readme.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-
-UnZip 0.15 additionnal library
-
-
-  This unzip package allow extract file from .ZIP file, compatible with 
-PKZip 2.04g, WinZip, InfoZip tools and compatible.
-
-  Multi volume ZipFile (span) are not supported, and old compression used by old 
-PKZip 1.x are not supported.
-
-See probdesc.zip from PKWare for specification of .ZIP format.
-
-What is Unzip
-  The Zlib library support the deflate compression and the creation of gzip (.gz) 
-file. Zlib is free and small.
-  The .Zip format, which can contain several compressed files (.gz can containt
-only one file) is a very popular format. This is why I've written a package for reading file compressed in Zipfile.
-
-Using Unzip package
-
-You need source of Zlib (get zlib111.zip and read zlib.h).
-Get unzlb015.zip and read unzip.h (whith documentation of unzip functions)
-
-The Unzip package is only two file : unzip.h and unzip.c. But it use the Zlib 
-  files.
-unztst.c is a simple sample program, which list file in a zipfile and display
-  README.TXT or FILE_ID.DIZ (if these files are found).
-miniunz.c is a mini unzip program.
-
-I'm also currenlyt writing a zipping portion (zip.h, zip.c and test with minizip.c)
-
-Please email me for feedback.
-I hope my source is compatible with Unix system, but I need your help for be sure
-
-Latest revision : Mar 04th, 1998
-
-Check http://www.winimage.com/zLibDll/unzip.html for up to date info.
diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c
index ff71a47..7244523 100644
--- a/contrib/minizip/unzip.c
+++ b/contrib/minizip/unzip.c
@@ -1,9 +1,39 @@
-/* unzip.c -- IO on .zip files using zlib 
-   Version 0.15 beta, Mar 19th, 1998,
+/* unzip.c -- IO for uncompress .zip files using zlib
+   Version 0.21 with encryption, March 10th, 2003
+
+   Copyright (C) 1998-2003 Gilles Vollant
 
    Read unzip.h for more info
 */
 
+/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+compatibility with older software. The following is from the original crypt.c. Code
+woven in by Terry Thorsen 1/2003.
+*/
+/*
+  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2000-Apr-09 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
+
+  The encryption/decryption parts of this source code (as opposed to the
+  non-echoing password parts) were originally written in Europe.  The
+  whole source package can be freely distributed, including from the USA.
+  (Prior to January 2000, re-export from the US was a violation of US law.)
+ */
+
+/*
+  This encryption code is a direct transcription of the algorithm from
+  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+  file (appnote.txt) is distributed with the PKZIP program (even in the
+  version without encryption capabilities).
+ */
+
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -55,22 +85,10 @@
 #define SIZEZIPLOCALHEADER (0x1e)
 
 
-/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
 
-#ifndef SEEK_CUR
-#define SEEK_CUR    1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END    2
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET    0
-#endif
 
 const char unz_copyright[] =
-   " unzip 0.15 Copyright 1998 Gilles Vollant ";
+   " unzip 0.21 Copyright 1998-2003 Gilles Vollant - http://www.winimage.com/zLibDll";
 
 /* unz_file_info_interntal contain internal info about a file in zipfile*/
 typedef struct unz_file_info_internal_s
@@ -83,23 +101,25 @@
     when reading and decompress it */
 typedef struct
 {
-	char  *read_buffer;         /* internal buffer for compressed data */
-	z_stream stream;            /* zLib stream structure for inflate */
+    char  *read_buffer;         /* internal buffer for compressed data */
+    z_stream stream;            /* zLib stream structure for inflate */
 
-	uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
-	uLong stream_initialised;   /* flag set if stream structure is initialised*/
+    uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
+    uLong stream_initialised;   /* flag set if stream structure is initialised*/
 
-	uLong offset_local_extrafield;/* offset of the local extra field */
-	uInt  size_local_extrafield;/* size of the local extra field */
-	uLong pos_local_extrafield;   /* position in the local extra field in read*/
+    uLong offset_local_extrafield;/* offset of the local extra field */
+    uInt  size_local_extrafield;/* size of the local extra field */
+    uLong pos_local_extrafield;   /* position in the local extra field in read*/
 
-	uLong crc32;                /* crc32 of all data uncompressed */
-	uLong crc32_wait;           /* crc32 we must obtain after decompress all */
-	uLong rest_read_compressed; /* number of byte to be decompressed */
-	uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
-	FILE* file;                 /* io structore of the zipfile */
-	uLong compression_method;   /* compression method (0==store) */
-	uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    uLong crc32;                /* crc32 of all data uncompressed */
+    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
+    uLong rest_read_compressed; /* number of byte to be decompressed */
+    uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    uLong compression_method;   /* compression method (0==store) */
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    int   raw;
 } file_in_zip_read_info_s;
 
 
@@ -107,25 +127,35 @@
 */
 typedef struct
 {
-	FILE* file;                 /* io structore of the zipfile */
-	unz_global_info gi;       /* public global information */
-	uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
-	uLong num_file;             /* number of the current file in the zipfile*/
-	uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
-	uLong current_file_ok;      /* flag about the usability of the current file*/
-	uLong central_pos;          /* position of the beginning of the central dir*/
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
+    unz_global_info gi;       /* public global information */
+    uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+    uLong num_file;             /* number of the current file in the zipfile*/
+    uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
+    uLong current_file_ok;      /* flag about the usability of the current file*/
+    uLong central_pos;          /* position of the beginning of the central dir*/
 
-	uLong size_central_dir;     /* size of the central directory  */
-	uLong offset_central_dir;   /* offset of start of central directory with
-								   respect to the starting disk number */
+    uLong size_central_dir;     /* size of the central directory  */
+    uLong offset_central_dir;   /* offset of start of central directory with
+                                   respect to the starting disk number */
 
-	unz_file_info cur_file_info; /* public info about the current file in zip*/
-	unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    unz_file_info cur_file_info; /* public info about the current file in zip*/
+    unz_file_info_internal cur_file_info_internal; /* private info about it*/
     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
-	                                    file if we are decompressing it */
+                                        file if we are decompressing it */
+    int encrypted;
+    #ifndef NOUNCRPYT
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
+    const unsigned long* pcrc_32_tab;
+    #endif
 } unz_s;
 
 
+#ifndef NOUNCRPYT
+#include "crypt.h"
+#endif
+
 /* ===========================================================================
      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    for end of file.
@@ -133,12 +163,18 @@
 */
 
 
-local int unzlocal_getByte(fin,pi)
-	FILE *fin;
-	int *pi;
+local int unzlocal_getByte OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    int *pi));
+
+local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    int *pi;
 {
     unsigned char c;
-	int err = fread(&c, 1, 1, fin);
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
     if (err==1)
     {
         *pi = (int)c;
@@ -146,7 +182,7 @@
     }
     else
     {
-        if (ferror(fin)) 
+        if (ZERROR(*pzlib_filefunc_def,filestream))
             return UNZ_ERRNO;
         else
             return UNZ_EOF;
@@ -155,23 +191,29 @@
 
 
 /* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets 
+   Reads a long in LSB order from the given gz_stream. Sets
 */
-local int unzlocal_getShort (fin,pX)
-	FILE* fin;
+local int unzlocal_getShort OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
     uLong *pX;
 {
     uLong x ;
     int i;
     int err;
 
-    err = unzlocal_getByte(fin,&i);
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
-    
+
     if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<8;
-   
+
     if (err==UNZ_OK)
         *pX = x;
     else
@@ -179,29 +221,35 @@
     return err;
 }
 
-local int unzlocal_getLong (fin,pX)
-	FILE* fin;
+local int unzlocal_getLong OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
     uLong *pX;
 {
     uLong x ;
     int i;
     int err;
 
-    err = unzlocal_getByte(fin,&i);
+    err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
-    
+
     if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<8;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<16;
 
     if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
+        err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x += ((uLong)i)<<24;
-   
+
     if (err==UNZ_OK)
         *pX = x;
     else
@@ -212,26 +260,26 @@
 
 /* My own strcmpi / strcasecmp */
 local int strcmpcasenosensitive_internal (fileName1,fileName2)
-	const char* fileName1;
-	const char* fileName2;
+    const char* fileName1;
+    const char* fileName2;
 {
-	for (;;)
-	{
-		char c1=*(fileName1++);
-		char c2=*(fileName2++);
-		if ((c1>='a') && (c1<='z'))
-			c1 -= 0x20;
-		if ((c2>='a') && (c2<='z'))
-			c2 -= 0x20;
-		if (c1=='\0')
-			return ((c2=='\0') ? 0 : -1);
-		if (c2=='\0')
-			return 1;
-		if (c1<c2)
-			return -1;
-		if (c1>c2)
-			return 1;
-	}
+    for (;;)
+    {
+        char c1=*(fileName1++);
+        char c2=*(fileName2++);
+        if ((c1>='a') && (c1<='z'))
+            c1 -= 0x20;
+        if ((c2>='a') && (c2<='z'))
+            c2 -= 0x20;
+        if (c1=='\0')
+            return ((c2=='\0') ? 0 : -1);
+        if (c2=='\0')
+            return 1;
+        if (c1<c2)
+            return -1;
+        if (c1>c2)
+            return 1;
+    }
 }
 
 
@@ -245,7 +293,7 @@
 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
 #endif
 
-/* 
+/*
    Compare two filename (fileName1,fileName2).
    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
@@ -255,203 +303,225 @@
 
 */
 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
-	const char* fileName1;
-	const char* fileName2;
-	int iCaseSensitivity;
+    const char* fileName1;
+    const char* fileName2;
+    int iCaseSensitivity;
 {
-	if (iCaseSensitivity==0)
-		iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+    if (iCaseSensitivity==0)
+        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
 
-	if (iCaseSensitivity==1)
-		return strcmp(fileName1,fileName2);
+    if (iCaseSensitivity==1)
+        return strcmp(fileName1,fileName2);
 
-	return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
-} 
+    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
 
+#ifndef BUFREADCOMMENT
 #define BUFREADCOMMENT (0x400)
+#endif
 
 /*
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
 */
-local uLong unzlocal_SearchCentralDir(fin)
-	FILE *fin;
+local uLong unzlocal_SearchCentralDir OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
 {
-	unsigned char* buf;
-	uLong uSizeFile;
-	uLong uBackRead;
-	uLong uMaxBack=0xffff; /* maximum size of global comment */
-	uLong uPosFound=0;
-	
-	if (fseek(fin,0,SEEK_END) != 0)
-		return 0;
+    unsigned char* buf;
+    uLong uSizeFile;
+    uLong uBackRead;
+    uLong uMaxBack=0xffff; /* maximum size of global comment */
+    uLong uPosFound=0;
+
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
 
 
-	uSizeFile = ftell( fin );
-	
-	if (uMaxBack>uSizeFile)
-		uMaxBack = uSizeFile;
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
 
-	buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
-	if (buf==NULL)
-		return 0;
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
 
-	uBackRead = 4;
-	while (uBackRead<uMaxBack)
-	{
-		uLong uReadSize,uReadPos ;
-		int i;
-		if (uBackRead+BUFREADCOMMENT>uMaxBack) 
-			uBackRead = uMaxBack;
-		else
-			uBackRead+=BUFREADCOMMENT;
-		uReadPos = uSizeFile-uBackRead ;
-		
-		uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize,uReadPos ;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-		if (fseek(fin,uReadPos,SEEK_SET)!=0)
-			break;
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
 
-		if (fread(buf,(uInt)uReadSize,1,fin)!=1)
-			break;
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
 
-                for (i=(int)uReadSize-3; (i--)>0;)
-			if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
-				((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
-			{
-				uPosFound = uReadPos+i;
-				break;
-			}
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
 
-		if (uPosFound!=0)
-			break;
-	}
-	TRYFREE(buf);
-	return uPosFound;
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    return uPosFound;
 }
 
 /*
   Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
-	 "zlib/zlib109.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
+     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+     "zlib/zlib114.zip".
+     If the zipfile cannot be opened (file doesn't exist or in not valid), the
+       return value is NULL.
      Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
+       of this unzip package.
 */
-extern unzFile ZEXPORT unzOpen (path)
-	const char *path;
+extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
+    const char *path;
+    zlib_filefunc_def* pzlib_filefunc_def;
 {
-	unz_s us;
-	unz_s *s;
-	uLong central_pos,uL;
-	FILE * fin ;
+    unz_s us;
+    unz_s *s;
+    uLong central_pos,uL;
 
-	uLong number_disk;          /* number of the current dist, used for 
-								   spaning ZIP, unsupported, always 0*/
-	uLong number_disk_with_CD;  /* number the the disk with central dir, used
-								   for spaning ZIP, unsupported, always 0*/
-	uLong number_entry_CD;      /* total number of entries in
-	                               the central dir 
-	                               (same than number_entry on nospan) */
+    uLong number_disk;          /* number of the current dist, used for
+                                   spaning ZIP, unsupported, always 0*/
+    uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                   for spaning ZIP, unsupported, always 0*/
+    uLong number_entry_CD;      /* total number of entries in
+                                   the central dir
+                                   (same than number_entry on nospan) */
 
-	int err=UNZ_OK;
+    int err=UNZ_OK;
 
     if (unz_copyright[0]!=' ')
         return NULL;
 
-    fin=fopen(path,"rb");
-	if (fin==NULL)
-		return NULL;
+    if (pzlib_filefunc_def==NULL)
+        fill_fopen_filefunc(&us.z_filefunc);
+    else
+        us.z_filefunc = *pzlib_filefunc_def;
 
-	central_pos = unzlocal_SearchCentralDir(fin);
-	if (central_pos==0)
-		err=UNZ_ERRNO;
+    us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
+                                                 path,
+                                                 ZLIB_FILEFUNC_MODE_READ |
+                                                 ZLIB_FILEFUNC_MODE_EXISTING);
+    if (us.filestream==NULL)
+        return NULL;
 
-	if (fseek(fin,central_pos,SEEK_SET)!=0)
-		err=UNZ_ERRNO;
+    central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
+    if (central_pos==0)
+        err=UNZ_ERRNO;
 
-	/* the signature, already checked */
-	if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    if (ZSEEK(us.z_filefunc, us.filestream,
+                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
 
-	/* number of this disk */
-	if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* the signature, already checked */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	/* number of the disk with the start of the central directory */
-	if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* number of this disk */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	/* total number of entries in the central dir on this disk */
-	if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* number of the disk with the start of the central directory */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	/* total number of entries in the central dir */
-	if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* total number of entries in the central dir on this disk */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if ((number_entry_CD!=us.gi.number_entry) ||
-		(number_disk_with_CD!=0) ||
-		(number_disk!=0))
-		err=UNZ_BADZIPFILE;
+    /* total number of entries in the central dir */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	/* size of the central directory */
-	if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    if ((number_entry_CD!=us.gi.number_entry) ||
+        (number_disk_with_CD!=0) ||
+        (number_disk!=0))
+        err=UNZ_BADZIPFILE;
 
-	/* offset of start of central directory with respect to the 
-	      starting disk number */
-	if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* size of the central directory */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	/* zipfile comment length */
-	if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
-		err=UNZ_ERRNO;
+    /* offset of start of central directory with respect to the
+          starting disk number */
+    if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
-		(err==UNZ_OK))
-		err=UNZ_BADZIPFILE;
+    /* zipfile comment length */
+    if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (err!=UNZ_OK)
-	{
-		fclose(fin);
-		return NULL;
-	}
+    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+        (err==UNZ_OK))
+        err=UNZ_BADZIPFILE;
 
-	us.file=fin;
-	us.byte_before_the_zipfile = central_pos -
-		                    (us.offset_central_dir+us.size_central_dir);
-	us.central_pos = central_pos;
+    if (err!=UNZ_OK)
+    {
+        ZCLOSE(us.z_filefunc, us.filestream);
+        return NULL;
+    }
+
+    us.byte_before_the_zipfile = central_pos -
+                            (us.offset_central_dir+us.size_central_dir);
+    us.central_pos = central_pos;
     us.pfile_in_zip_read = NULL;
-	
+    us.encrypted = 0;
 
-	s=(unz_s*)ALLOC(sizeof(unz_s));
-	*s=us;
-	unzGoToFirstFile((unzFile)s);	
-	return (unzFile)s;	
+
+    s=(unz_s*)ALLOC(sizeof(unz_s));
+    *s=us;
+    unzGoToFirstFile((unzFile)s);
+    return (unzFile)s;
 }
 
 
+extern unzFile ZEXPORT unzOpen (path)
+    const char *path;
+{
+    return unzOpen2(path, NULL);
+}
+
 /*
   Close a ZipFile opened with unzipOpen.
   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
   return UNZ_OK if there is no problem. */
 extern int ZEXPORT unzClose (file)
-	unzFile file;
+    unzFile file;
 {
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
 
     if (s->pfile_in_zip_read!=NULL)
         unzCloseCurrentFile(file);
 
-	fclose(s->file);
-	TRYFREE(s);
-	return UNZ_OK;
+    ZCLOSE(s->z_filefunc, s->filestream);
+    TRYFREE(s);
+    return UNZ_OK;
 }
 
 
@@ -460,15 +530,15 @@
   No preparation of the structure is needed
   return UNZ_OK if there is no problem. */
 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
-	unzFile file;
-	unz_global_info *pglobal_info;
+    unzFile file;
+    unz_global_info *pglobal_info;
 {
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	*pglobal_info=s->gi;
-	return UNZ_OK;
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    *pglobal_info=s->gi;
+    return UNZ_OK;
 }
 
 
@@ -495,14 +565,14 @@
 */
 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
                                                   unz_file_info *pfile_info,
-                                                  unz_file_info_internal 
+                                                  unz_file_info_internal
                                                   *pfile_info_internal,
                                                   char *szFileName,
-												  uLong fileNameBufferSize,
+                                                  uLong fileNameBufferSize,
                                                   void *extraField,
-												  uLong extraFieldBufferSize,
+                                                  uLong extraFieldBufferSize,
                                                   char *szComment,
-												  uLong commentBufferSize));
+                                                  uLong commentBufferSize));
 
 local int unzlocal_GetCurrentFileInfoInternal (file,
                                               pfile_info,
@@ -510,156 +580,158 @@
                                               szFileName, fileNameBufferSize,
                                               extraField, extraFieldBufferSize,
                                               szComment,  commentBufferSize)
-	unzFile file;
-	unz_file_info *pfile_info;
-	unz_file_info_internal *pfile_info_internal;
-	char *szFileName;
-	uLong fileNameBufferSize;
-	void *extraField;
-	uLong extraFieldBufferSize;
-	char *szComment;
-	uLong commentBufferSize;
+    unzFile file;
+    unz_file_info *pfile_info;
+    unz_file_info_internal *pfile_info_internal;
+    char *szFileName;
+    uLong fileNameBufferSize;
+    void *extraField;
+    uLong extraFieldBufferSize;
+    char *szComment;
+    uLong commentBufferSize;
 {
-	unz_s* s;
-	unz_file_info file_info;
-	unz_file_info_internal file_info_internal;
-	int err=UNZ_OK;
-	uLong uMagic;
-	long lSeek=0;
+    unz_s* s;
+    unz_file_info file_info;
+    unz_file_info_internal file_info_internal;
+    int err=UNZ_OK;
+    uLong uMagic;
+    long lSeek=0;
 
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
-		err=UNZ_ERRNO;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (ZSEEK(s->z_filefunc, s->filestream,
+              s->pos_in_central_dir+s->byte_before_the_zipfile,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        err=UNZ_ERRNO;
 
 
-	/* we check the magic */
-	if (err==UNZ_OK)
-		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
-			err=UNZ_ERRNO;
-		else if (uMagic!=0x02014b50)
-			err=UNZ_BADZIPFILE;
+    /* we check the magic */
+    if (err==UNZ_OK)
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x02014b50)
+            err=UNZ_BADZIPFILE;
 
-	if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+        err=UNZ_ERRNO;
 
     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
 
-	if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	lSeek+=file_info.size_filename;
-	if ((err==UNZ_OK) && (szFileName!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_filename<fileNameBufferSize)
-		{
-			*(szFileName+file_info.size_filename)='\0';
-			uSizeRead = file_info.size_filename;
-		}
-		else
-			uSizeRead = fileNameBufferSize;
+    lSeek+=file_info.size_filename;
+    if ((err==UNZ_OK) && (szFileName!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_filename<fileNameBufferSize)
+        {
+            *(szFileName+file_info.size_filename)='\0';
+            uSizeRead = file_info.size_filename;
+        }
+        else
+            uSizeRead = fileNameBufferSize;
 
-		if ((file_info.size_filename>0) && (fileNameBufferSize>0))
-			if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek -= uSizeRead;
-	}
+        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek -= uSizeRead;
+    }
 
-	
-	if ((err==UNZ_OK) && (extraField!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_file_extra<extraFieldBufferSize)
-			uSizeRead = file_info.size_file_extra;
-		else
-			uSizeRead = extraFieldBufferSize;
 
-		if (lSeek!=0)
-			if (fseek(s->file,lSeek,SEEK_CUR)==0)
-				lSeek=0;
-			else
-				err=UNZ_ERRNO;
-		if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
-			if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek += file_info.size_file_extra - uSizeRead;
-	}
-	else
-		lSeek+=file_info.size_file_extra; 
+    if ((err==UNZ_OK) && (extraField!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_file_extra<extraFieldBufferSize)
+            uSizeRead = file_info.size_file_extra;
+        else
+            uSizeRead = extraFieldBufferSize;
 
-	
-	if ((err==UNZ_OK) && (szComment!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_file_comment<commentBufferSize)
-		{
-			*(szComment+file_info.size_file_comment)='\0';
-			uSizeRead = file_info.size_file_comment;
-		}
-		else
-			uSizeRead = commentBufferSize;
+        if (lSeek!=0)
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek += file_info.size_file_extra - uSizeRead;
+    }
+    else
+        lSeek+=file_info.size_file_extra;
 
-		if (lSeek!=0)
-			if (fseek(s->file,lSeek,SEEK_CUR)==0)
-				lSeek=0;
-			else
-				err=UNZ_ERRNO;
-		if ((file_info.size_file_comment>0) && (commentBufferSize>0))
-			if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek+=file_info.size_file_comment - uSizeRead;
-	}
-	else
-		lSeek+=file_info.size_file_comment;
 
-	if ((err==UNZ_OK) && (pfile_info!=NULL))
-		*pfile_info=file_info;
+    if ((err==UNZ_OK) && (szComment!=NULL))
+    {
+        uLong uSizeRead ;
+        if (file_info.size_file_comment<commentBufferSize)
+        {
+            *(szComment+file_info.size_file_comment)='\0';
+            uSizeRead = file_info.size_file_comment;
+        }
+        else
+            uSizeRead = commentBufferSize;
 
-	if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
-		*pfile_info_internal=file_info_internal;
+        if (lSeek!=0)
+            if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+                lSeek=0;
+            else
+                err=UNZ_ERRNO;
+        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+            if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+                err=UNZ_ERRNO;
+        lSeek+=file_info.size_file_comment - uSizeRead;
+    }
+    else
+        lSeek+=file_info.size_file_comment;
 
-	return err;
+    if ((err==UNZ_OK) && (pfile_info!=NULL))
+        *pfile_info=file_info;
+
+    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+        *pfile_info_internal=file_info_internal;
+
+    return err;
 }
 
 
@@ -670,23 +742,23 @@
   return UNZ_OK if there is no problem.
 */
 extern int ZEXPORT unzGetCurrentFileInfo (file,
-                                                  pfile_info,
-                                                  szFileName, fileNameBufferSize,
-                                                  extraField, extraFieldBufferSize,
-                                                  szComment,  commentBufferSize)
-	unzFile file;
-	unz_file_info *pfile_info;
-	char *szFileName;
-	uLong fileNameBufferSize;
-	void *extraField;
-	uLong extraFieldBufferSize;
-	char *szComment;
-	uLong commentBufferSize;
+                                          pfile_info,
+                                          szFileName, fileNameBufferSize,
+                                          extraField, extraFieldBufferSize,
+                                          szComment,  commentBufferSize)
+    unzFile file;
+    unz_file_info *pfile_info;
+    char *szFileName;
+    uLong fileNameBufferSize;
+    void *extraField;
+    uLong extraFieldBufferSize;
+    char *szComment;
+    uLong commentBufferSize;
 {
-	return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
-												szFileName,fileNameBufferSize,
-												extraField,extraFieldBufferSize,
-												szComment,commentBufferSize);
+    return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+                                                szFileName,fileNameBufferSize,
+                                                extraField,extraFieldBufferSize,
+                                                szComment,commentBufferSize);
 }
 
 /*
@@ -694,50 +766,49 @@
   return UNZ_OK if there is no problem
 */
 extern int ZEXPORT unzGoToFirstFile (file)
-	unzFile file;
+    unzFile file;
 {
-	int err=UNZ_OK;
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	s->pos_in_central_dir=s->offset_central_dir;
-	s->num_file=0;
-	err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-											 &s->cur_file_info_internal,
-											 NULL,0,NULL,0,NULL,0);
-	s->current_file_ok = (err == UNZ_OK);
-	return err;
+    int err=UNZ_OK;
+    unz_s* s;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    s->pos_in_central_dir=s->offset_central_dir;
+    s->num_file=0;
+    err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                             &s->cur_file_info_internal,
+                                             NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
 }
 
-
 /*
   Set the current file of the zipfile to the next file.
   return UNZ_OK if there is no problem
   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
 */
 extern int ZEXPORT unzGoToNextFile (file)
-	unzFile file;
+    unzFile file;
 {
-	unz_s* s;	
-	int err;
+    unz_s* s;
+    int err;
 
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_END_OF_LIST_OF_FILE;
-	if (s->num_file+1==s->gi.number_entry)
-		return UNZ_END_OF_LIST_OF_FILE;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (s->num_file+1==s->gi.number_entry)
+        return UNZ_END_OF_LIST_OF_FILE;
 
-	s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
-			s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
-	s->num_file++;
-	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-											   &s->cur_file_info_internal,
-											   NULL,0,NULL,0,NULL,0);
-	s->current_file_ok = (err == UNZ_OK);
-	return err;
+    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+    s->num_file++;
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
 }
 
 
@@ -750,52 +821,117 @@
   UNZ_END_OF_LIST_OF_FILE if the file is not found
 */
 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
-	unzFile file;
-	const char *szFileName;
-	int iCaseSensitivity;
+    unzFile file;
+    const char *szFileName;
+    int iCaseSensitivity;
 {
-	unz_s* s;	
-	int err;
-
-	
-	uLong num_fileSaved;
-	uLong pos_in_central_dirSaved;
+    unz_s* s;
+    int err;
 
 
-	if (file==NULL)
-		return UNZ_PARAMERROR;
+    uLong num_fileSaved;
+    uLong pos_in_central_dirSaved;
+
+
+    if (file==NULL)
+        return UNZ_PARAMERROR;
 
     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
         return UNZ_PARAMERROR;
 
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_END_OF_LIST_OF_FILE;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
 
-	num_fileSaved = s->num_file;
-	pos_in_central_dirSaved = s->pos_in_central_dir;
+    num_fileSaved = s->num_file;
+    pos_in_central_dirSaved = s->pos_in_central_dir;
 
-	err = unzGoToFirstFile(file);
+    err = unzGoToFirstFile(file);
 
-	while (err == UNZ_OK)
-	{
-		char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
-		unzGetCurrentFileInfo(file,NULL,
-								szCurrentFileName,sizeof(szCurrentFileName)-1,
-								NULL,0,NULL,0);
-		if (unzStringFileNameCompare(szCurrentFileName,
-										szFileName,iCaseSensitivity)==0)
-			return UNZ_OK;
-		err = unzGoToNextFile(file);
-	}
+    while (err == UNZ_OK)
+    {
+        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+        unzGetCurrentFileInfo(file,NULL,
+                                szCurrentFileName,sizeof(szCurrentFileName)-1,
+                                NULL,0,NULL,0);
+        if (unzStringFileNameCompare(szCurrentFileName,
+                                        szFileName,iCaseSensitivity)==0)
+            return UNZ_OK;
+        err = unzGoToNextFile(file);
+    }
 
-	s->num_file = num_fileSaved ;
-	s->pos_in_central_dir = pos_in_central_dirSaved ;
-	return err;
+    s->num_file = num_fileSaved ;
+    s->pos_in_central_dir = pos_in_central_dirSaved ;
+    return err;
 }
 
 
 /*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+    uLong pos_in_zip_directory;   // offset in file
+    uLong num_of_file;            // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos(file, file_pos)
+    unzFile file;
+    unz_file_pos* file_pos;
+{
+    unz_s* s;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_END_OF_LIST_OF_FILE;
+
+    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
+    file_pos->num_of_file           = s->num_file;
+
+    return UNZ_OK;
+}
+
+extern int ZEXPORT unzGoToFilePos(file, file_pos)
+    unzFile file;
+    unz_file_pos* file_pos;
+{
+    unz_s* s;
+    int err;
+
+    if (file==NULL || file_pos==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+
+    /* jump to the right spot */
+    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+    s->num_file           = file_pos->num_of_file;
+
+    /* set the current file */
+    err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                               &s->cur_file_info_internal,
+                                               NULL,0,NULL,0,NULL,0);
+    /* return results */
+    s->current_file_ok = (err == UNZ_OK);
+    return err;
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
   Read the local header of the current zipfile
   Check the coherency of the local header and info in the end of central
         directory about this file
@@ -803,185 +939,256 @@
         (filename and size of extra field data)
 */
 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
-													poffset_local_extrafield,
-													psize_local_extrafield)
-	unz_s* s;
-	uInt* piSizeVar;
-	uLong *poffset_local_extrafield;
-	uInt  *psize_local_extrafield;
+                                                    poffset_local_extrafield,
+                                                    psize_local_extrafield)
+    unz_s* s;
+    uInt* piSizeVar;
+    uLong *poffset_local_extrafield;
+    uInt  *psize_local_extrafield;
 {
-	uLong uMagic,uData,uFlags;
-	uLong size_filename;
-	uLong size_extra_field;
-	int err=UNZ_OK;
+    uLong uMagic,uData,uFlags;
+    uLong size_filename;
+    uLong size_extra_field;
+    int err=UNZ_OK;
 
-	*piSizeVar = 0;
-	*poffset_local_extrafield = 0;
-	*psize_local_extrafield = 0;
+    *piSizeVar = 0;
+    *poffset_local_extrafield = 0;
+    *psize_local_extrafield = 0;
 
-	if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
-								s->byte_before_the_zipfile,SEEK_SET)!=0)
-		return UNZ_ERRNO;
+    if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
 
 
-	if (err==UNZ_OK)
-		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
-			err=UNZ_ERRNO;
-		else if (uMagic!=0x04034b50)
-			err=UNZ_BADZIPFILE;
+    if (err==UNZ_OK)
+        if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+            err=UNZ_ERRNO;
+        else if (uMagic!=0x04034b50)
+            err=UNZ_BADZIPFILE;
 
-	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
 /*
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
-		err=UNZ_BADZIPFILE;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+        err=UNZ_BADZIPFILE;
 */
-	if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
-		err=UNZ_ERRNO;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
-		err=UNZ_BADZIPFILE;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+        err=UNZ_BADZIPFILE;
 
     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
                          (s->cur_file_info.compression_method!=Z_DEFLATED))
         err=UNZ_BADZIPFILE;
 
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
-		err=UNZ_ERRNO;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+        err=UNZ_ERRNO;
 
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
-		                      ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
 
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
-							  ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
 
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
-							  ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
+    if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
+                              ((uFlags & 8)==0))
+        err=UNZ_BADZIPFILE;
 
 
-	if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
-		err=UNZ_BADZIPFILE;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+        err=UNZ_ERRNO;
+    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+        err=UNZ_BADZIPFILE;
 
-	*piSizeVar += (uInt)size_filename;
+    *piSizeVar += (uInt)size_filename;
 
-	if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
-		err=UNZ_ERRNO;
-	*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
-									SIZEZIPLOCALHEADER + size_filename;
-	*psize_local_extrafield = (uInt)size_extra_field;
+    if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+        err=UNZ_ERRNO;
+    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+                                    SIZEZIPLOCALHEADER + size_filename;
+    *psize_local_extrafield = (uInt)size_extra_field;
 
-	*piSizeVar += (uInt)size_extra_field;
+    *piSizeVar += (uInt)size_extra_field;
 
-	return err;
+    return err;
 }
-												
+
 /*
   Open for reading data the current file in the zipfile.
   If there is no error and the file is opened, the return value is UNZ_OK.
 */
-extern int ZEXPORT unzOpenCurrentFile (file)
-	unzFile file;
+extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
+    unzFile file;
+    int* method;
+    int* level;
+    int raw;
+    const char* password;
 {
-	int err=UNZ_OK;
-	int Store;
-	uInt iSizeVar;
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	uLong offset_local_extrafield;  /* offset of the local extra field */
-	uInt  size_local_extrafield;    /* size of the local extra field */
+    int err=UNZ_OK;
+    uInt iSizeVar;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    uLong offset_local_extrafield;  /* offset of the local extra field */
+    uInt  size_local_extrafield;    /* size of the local extra field */
+    #ifndef NOUNCRPYT
+    char source[12];
+    #else
+    if (password != NULL)
+        return UNZ_PARAMERROR;
+    #endif
 
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_PARAMERROR;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
+    if (!s->current_file_ok)
+        return UNZ_PARAMERROR;
 
     if (s->pfile_in_zip_read != NULL)
         unzCloseCurrentFile(file);
 
-	if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
-				&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
-		return UNZ_BADZIPFILE;
+    if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+        return UNZ_BADZIPFILE;
 
-	pfile_in_zip_read_info = (file_in_zip_read_info_s*)
-									    ALLOC(sizeof(file_in_zip_read_info_s));
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_INTERNALERROR;
+    pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+                                        ALLOC(sizeof(file_in_zip_read_info_s));
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_INTERNALERROR;
 
-	pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
-	pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
-	pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
-	pfile_in_zip_read_info->pos_local_extrafield=0;
+    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+    pfile_in_zip_read_info->pos_local_extrafield=0;
+    pfile_in_zip_read_info->raw=raw;
 
-	if (pfile_in_zip_read_info->read_buffer==NULL)
-	{
-		TRYFREE(pfile_in_zip_read_info);
-		return UNZ_INTERNALERROR;
-	}
+    if (pfile_in_zip_read_info->read_buffer==NULL)
+    {
+        TRYFREE(pfile_in_zip_read_info);
+        return UNZ_INTERNALERROR;
+    }
 
-	pfile_in_zip_read_info->stream_initialised=0;
-	
-	if ((s->cur_file_info.compression_method!=0) &&
+    pfile_in_zip_read_info->stream_initialised=0;
+
+    if (method!=NULL)
+        *method = (int)s->cur_file_info.compression_method;
+
+    if (level!=NULL)
+    {
+        *level = 6;
+        switch (s->cur_file_info.flag & 0x06)
+        {
+          case 6 : *level = 1; break;
+          case 4 : *level = 2; break;
+          case 2 : *level = 9; break;
+        }
+    }
+
+    if ((s->cur_file_info.compression_method!=0) &&
         (s->cur_file_info.compression_method!=Z_DEFLATED))
-		err=UNZ_BADZIPFILE;
-	Store = s->cur_file_info.compression_method==0;
+        err=UNZ_BADZIPFILE;
 
-	pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
-	pfile_in_zip_read_info->crc32=0;
-	pfile_in_zip_read_info->compression_method =
+    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+    pfile_in_zip_read_info->crc32=0;
+    pfile_in_zip_read_info->compression_method =
             s->cur_file_info.compression_method;
-	pfile_in_zip_read_info->file=s->file;
-	pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+    pfile_in_zip_read_info->filestream=s->filestream;
+    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
 
     pfile_in_zip_read_info->stream.total_out = 0;
 
-	if (!Store)
-	{
-	  pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
-	  pfile_in_zip_read_info->stream.zfree = (free_func)0;
-	  pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
-      
-	  err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
-	  if (err == Z_OK)
-	    pfile_in_zip_read_info->stream_initialised=1;
+    if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
+        (!raw))
+    {
+      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+      pfile_in_zip_read_info->stream.zfree = (free_func)0;
+      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+
+      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+      if (err == Z_OK)
+        pfile_in_zip_read_info->stream_initialised=1;
+      else
+        return err;
         /* windowBits is passed < 0 to tell that there is no zlib header.
          * Note that in this case inflate *requires* an extra "dummy" byte
          * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END. 
-         * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
+         * return Z_STREAM_END.
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
          * size of both compressed and uncompressed data
          */
-	}
-	pfile_in_zip_read_info->rest_read_compressed = 
+    }
+    pfile_in_zip_read_info->rest_read_compressed =
             s->cur_file_info.compressed_size ;
-	pfile_in_zip_read_info->rest_read_uncompressed = 
+    pfile_in_zip_read_info->rest_read_uncompressed =
             s->cur_file_info.uncompressed_size ;
 
-	
-	pfile_in_zip_read_info->pos_in_zipfile = 
-            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
-			  iSizeVar;
-	
-	pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+    pfile_in_zip_read_info->pos_in_zipfile =
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+              iSizeVar;
+
+    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+    s->pfile_in_zip_read = pfile_in_zip_read_info;
+
+    #ifndef NOUNCRPYT
+    if (password != NULL)
+    {
+        int i;
+        s->pcrc_32_tab = get_crc_table();
+        init_keys(password,s->keys,s->pcrc_32_tab);
+        if (ZSEEK(s->z_filefunc, s->filestream,
+                  s->pfile_in_zip_read->pos_in_zipfile +
+                     s->pfile_in_zip_read->byte_before_the_zipfile,
+                  SEEK_SET)!=0)
+            return UNZ_INTERNALERROR;
+        if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
+            return UNZ_INTERNALERROR;
+
+        for (i = 0; i<12; i++)
+            zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+        s->pfile_in_zip_read->pos_in_zipfile+=12;
+        s->encrypted=1;
+    }
+    #endif
 
 
-	s->pfile_in_zip_read = pfile_in_zip_read_info;
     return UNZ_OK;
 }
 
+extern int ZEXPORT unzOpenCurrentFile (file)
+    unzFile file;
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
+    unzFile file;
+    const char* password;
+{
+    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
+    unzFile file;
+    int* method;
+    int* level;
+    int raw;
+{
+    return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
 
 /*
   Read bytes from the current file.
@@ -994,126 +1201,149 @@
     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
 */
 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
-	unzFile file;
-	voidp buf;
-	unsigned len;
+    unzFile file;
+    voidp buf;
+    unsigned len;
 {
-	int err=UNZ_OK;
-	uInt iRead = 0;
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    int err=UNZ_OK;
+    uInt iRead = 0;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
 
 
-	if ((pfile_in_zip_read_info->read_buffer == NULL))
-		return UNZ_END_OF_LIST_OF_FILE;
-	if (len==0)
-		return 0;
+    if ((pfile_in_zip_read_info->read_buffer == NULL))
+        return UNZ_END_OF_LIST_OF_FILE;
+    if (len==0)
+        return 0;
 
-	pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
 
-	pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-	
-	if (len>pfile_in_zip_read_info->rest_read_uncompressed)
-		pfile_in_zip_read_info->stream.avail_out = 
-		  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
 
-	while (pfile_in_zip_read_info->stream.avail_out>0)
-	{
-		if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+    if (len>pfile_in_zip_read_info->rest_read_uncompressed)
+        pfile_in_zip_read_info->stream.avail_out =
+          (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+    while (pfile_in_zip_read_info->stream.avail_out>0)
+    {
+        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
             (pfile_in_zip_read_info->rest_read_compressed>0))
-		{
-			uInt uReadThis = UNZ_BUFSIZE;
-			if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
-				uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
-			if (uReadThis == 0)
-				return UNZ_EOF;
-			if (fseek(pfile_in_zip_read_info->file,
-                      pfile_in_zip_read_info->pos_in_zipfile + 
-                         pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
-				return UNZ_ERRNO;
-			if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
-                         pfile_in_zip_read_info->file)!=1)
-				return UNZ_ERRNO;
-			pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+        {
+            uInt uReadThis = UNZ_BUFSIZE;
+            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+            if (uReadThis == 0)
+                return UNZ_EOF;
+            if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->pos_in_zipfile +
+                         pfile_in_zip_read_info->byte_before_the_zipfile,
+                         ZLIB_FILEFUNC_SEEK_SET)!=0)
+                return UNZ_ERRNO;
+            if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+                      pfile_in_zip_read_info->filestream,
+                      pfile_in_zip_read_info->read_buffer,
+                      uReadThis)!=uReadThis)
+                return UNZ_ERRNO;
 
-			pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-			
-			pfile_in_zip_read_info->stream.next_in = 
+
+            #ifndef NOUNCRPYT
+            if(s->encrypted)
+            {
+                uInt i;
+                for(i=0;i<uReadThis;i++)
+                  pfile_in_zip_read_info->read_buffer[i] =
+                      zdecode(s->keys,s->pcrc_32_tab,
+                              pfile_in_zip_read_info->read_buffer[i]);
+            }
+            #endif
+
+
+            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+            pfile_in_zip_read_info->stream.next_in =
                 (Bytef*)pfile_in_zip_read_info->read_buffer;
-			pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
-		}
+            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+        }
 
-		if (pfile_in_zip_read_info->compression_method==0)
-		{
-			uInt uDoCopy,i ;
-			if (pfile_in_zip_read_info->stream.avail_out < 
+        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+        {
+            uInt uDoCopy,i ;
+
+            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                return (iRead==0) ? UNZ_EOF : iRead;
+
+            if (pfile_in_zip_read_info->stream.avail_out <
                             pfile_in_zip_read_info->stream.avail_in)
-				uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
-			else
-				uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
-				
-			for (i=0;i<uDoCopy;i++)
-				*(pfile_in_zip_read_info->stream.next_out+i) =
+                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+            else
+                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+            for (i=0;i<uDoCopy;i++)
+                *(pfile_in_zip_read_info->stream.next_out+i) =
                         *(pfile_in_zip_read_info->stream.next_in+i);
-					
-			pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
-								pfile_in_zip_read_info->stream.next_out,
-								uDoCopy);
-			pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
-			pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
-			pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
-			pfile_in_zip_read_info->stream.next_out += uDoCopy;
-			pfile_in_zip_read_info->stream.next_in += uDoCopy;
+
+            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+                                pfile_in_zip_read_info->stream.next_out,
+                                uDoCopy);
+            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+            pfile_in_zip_read_info->stream.next_out += uDoCopy;
+            pfile_in_zip_read_info->stream.next_in += uDoCopy;
             pfile_in_zip_read_info->stream.total_out += uDoCopy;
-			iRead += uDoCopy;
-		}
-		else
-		{
-			uLong uTotalOutBefore,uTotalOutAfter;
-			const Bytef *bufBefore;
-			uLong uOutThis;
-			int flush=Z_SYNC_FLUSH;
+            iRead += uDoCopy;
+        }
+        else
+        {
+            uLong uTotalOutBefore,uTotalOutAfter;
+            const Bytef *bufBefore;
+            uLong uOutThis;
+            int flush=Z_SYNC_FLUSH;
 
-			uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
-			bufBefore = pfile_in_zip_read_info->stream.next_out;
+            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+            bufBefore = pfile_in_zip_read_info->stream.next_out;
 
-			/*
-			if ((pfile_in_zip_read_info->rest_read_uncompressed ==
-			         pfile_in_zip_read_info->stream.avail_out) &&
-				(pfile_in_zip_read_info->rest_read_compressed == 0))
-				flush = Z_FINISH;
-			*/
-			err=inflate(&pfile_in_zip_read_info->stream,flush);
+            /*
+            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+                     pfile_in_zip_read_info->stream.avail_out) &&
+                (pfile_in_zip_read_info->rest_read_compressed == 0))
+                flush = Z_FINISH;
+            */
+            err=inflate(&pfile_in_zip_read_info->stream,flush);
 
-			uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
-			uOutThis = uTotalOutAfter-uTotalOutBefore;
-			
-			pfile_in_zip_read_info->crc32 = 
+            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+            uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+            pfile_in_zip_read_info->crc32 =
                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
                         (uInt)(uOutThis));
 
-			pfile_in_zip_read_info->rest_read_uncompressed -=
+            pfile_in_zip_read_info->rest_read_uncompressed -=
                 uOutThis;
 
-			iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-            
-			if (err==Z_STREAM_END)
-				return (iRead==0) ? UNZ_EOF : iRead;
-			if (err!=Z_OK) 
-				break;
-		}
-	}
+            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
 
-	if (err==Z_OK)
-		return iRead;
-	return err;
+            if (err==Z_STREAM_END)
+                return (iRead==0) ? UNZ_EOF : iRead;
+            if (err!=Z_OK)
+                break;
+        }
+    }
+
+    if (err==Z_OK)
+        return iRead;
+    return err;
 }
 
 
@@ -1121,42 +1351,42 @@
   Give the current position in uncompressed data
 */
 extern z_off_t ZEXPORT unztell (file)
-	unzFile file;
+    unzFile file;
 {
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
 
-	return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
 }
 
 
 /*
-  return 1 if the end of file was reached, 0 elsewhere 
+  return 1 if the end of file was reached, 0 elsewhere
 */
 extern int ZEXPORT unzeof (file)
-	unzFile file;
+    unzFile file;
 {
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-	
-	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
-		return 1;
-	else
-		return 0;
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
+
+    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+        return 1;
+    else
+        return 0;
 }
 
 
@@ -1169,51 +1399,55 @@
   if buf==NULL, it return the size of the local extra field that can be read
 
   if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of bytes copied in buf, or (if <0) 
-	the error code
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
 */
 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
-	unzFile file;
-	voidp buf;
-	unsigned len;
+    unzFile file;
+    voidp buf;
+    unsigned len;
 {
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	uInt read_now;
-	uLong size_to_read;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    uInt read_now;
+    uLong size_to_read;
 
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
 
-	size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
-				pfile_in_zip_read_info->pos_local_extrafield);
+    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+                pfile_in_zip_read_info->pos_local_extrafield);
 
-	if (buf==NULL)
-		return (int)size_to_read;
-	
-	if (len>size_to_read)
-		read_now = (uInt)size_to_read;
-	else
-		read_now = (uInt)len ;
+    if (buf==NULL)
+        return (int)size_to_read;
 
-	if (read_now==0)
-		return 0;
-	
-	if (fseek(pfile_in_zip_read_info->file,
-              pfile_in_zip_read_info->offset_local_extrafield + 
-			  pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
-		return UNZ_ERRNO;
+    if (len>size_to_read)
+        read_now = (uInt)size_to_read;
+    else
+        read_now = (uInt)len ;
 
-	if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
-		return UNZ_ERRNO;
+    if (read_now==0)
+        return 0;
 
-	return (int)read_now;
+    if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              pfile_in_zip_read_info->offset_local_extrafield +
+              pfile_in_zip_read_info->pos_local_extrafield,
+              ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
+
+    if (ZREAD(pfile_in_zip_read_info->z_filefunc,
+              pfile_in_zip_read_info->filestream,
+              buf,size_to_read)!=size_to_read)
+        return UNZ_ERRNO;
+
+    return (int)read_now;
 }
 
 /*
@@ -1221,39 +1455,40 @@
   Return UNZ_CRCERROR if all the file was read but the CRC is not good
 */
 extern int ZEXPORT unzCloseCurrentFile (file)
-	unzFile file;
+    unzFile file;
 {
-	int err=UNZ_OK;
+    int err=UNZ_OK;
 
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    unz_s* s;
+    file_in_zip_read_info_s* pfile_in_zip_read_info;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
 
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
+    if (pfile_in_zip_read_info==NULL)
+        return UNZ_PARAMERROR;
 
 
-	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
-	{
-		if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
-			err=UNZ_CRCERROR;
-	}
+    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+        (!pfile_in_zip_read_info->raw))
+    {
+        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+            err=UNZ_CRCERROR;
+    }
 
 
-	TRYFREE(pfile_in_zip_read_info->read_buffer);
-	pfile_in_zip_read_info->read_buffer = NULL;
-	if (pfile_in_zip_read_info->stream_initialised)
-		inflateEnd(&pfile_in_zip_read_info->stream);
+    TRYFREE(pfile_in_zip_read_info->read_buffer);
+    pfile_in_zip_read_info->read_buffer = NULL;
+    if (pfile_in_zip_read_info->stream_initialised)
+        inflateEnd(&pfile_in_zip_read_info->stream);
 
-	pfile_in_zip_read_info->stream_initialised = 0;
-	TRYFREE(pfile_in_zip_read_info);
+    pfile_in_zip_read_info->stream_initialised = 0;
+    TRYFREE(pfile_in_zip_read_info);
 
     s->pfile_in_zip_read=NULL;
 
-	return err;
+    return err;
 }
 
 
@@ -1263,32 +1498,32 @@
   return the number of byte copied or an error code <0
 */
 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
-	unzFile file;
-	char *szComment;
-	uLong uSizeBuf;
+    unzFile file;
+    char *szComment;
+    uLong uSizeBuf;
 {
-	int err=UNZ_OK;
-	unz_s* s;
-	uLong uReadThis ;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
+    int err=UNZ_OK;
+    unz_s* s;
+    uLong uReadThis ;
+    if (file==NULL)
+        return UNZ_PARAMERROR;
+    s=(unz_s*)file;
 
-	uReadThis = uSizeBuf;
-	if (uReadThis>s->gi.size_comment)
-		uReadThis = s->gi.size_comment;
+    uReadThis = uSizeBuf;
+    if (uReadThis>s->gi.size_comment)
+        uReadThis = s->gi.size_comment;
 
-	if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
-		return UNZ_ERRNO;
+    if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        return UNZ_ERRNO;
 
-	if (uReadThis>0)
+    if (uReadThis>0)
     {
       *szComment='\0';
-	  if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
-		return UNZ_ERRNO;
+      if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+        return UNZ_ERRNO;
     }
 
-	if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
-		*(szComment+s->gi.size_comment)='\0';
-	return (int)uReadThis;
+    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+        *(szComment+s->gi.size_comment)='\0';
+    return (int)uReadThis;
 }
diff --git a/contrib/minizip/unzip.def b/contrib/minizip/unzip.def
deleted file mode 100644
index f6ede89..0000000
--- a/contrib/minizip/unzip.def
+++ /dev/null
@@ -1,15 +0,0 @@
-	unzOpen                       @61
-	unzClose                      @62
-	unzGetGlobalInfo              @63
-	unzGetCurrentFileInfo         @64
-	unzGoToFirstFile              @65
-	unzGoToNextFile               @66
-	unzOpenCurrentFile            @67
-	unzReadCurrentFile            @68
-	unztell                       @70
-	unzeof                        @71
-	unzCloseCurrentFile           @72
-	unzGetGlobalComment           @73
-	unzStringFileNameCompare      @74
-	unzLocateFile                 @75
-	unzGetLocalExtrafield         @76
diff --git a/contrib/minizip/unzip.h b/contrib/minizip/unzip.h
index 76692cb..67ca851 100644
--- a/contrib/minizip/unzip.h
+++ b/contrib/minizip/unzip.h
@@ -1,15 +1,14 @@
-/* unzip.h -- IO for uncompress .zip files using zlib 
-   Version 0.15 beta, Mar 19th, 1998,
+/* unzip.h -- IO for uncompress .zip files using zlib
+   Version 0.21, March 10th, 2003
 
-   Copyright (C) 1998 Gilles Vollant
+   Copyright (C) 1998-2003 Gilles Vollant
 
    This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
      WinZip, InfoZip tools and compatible.
    Encryption and multi volume ZipFile (span) are not supported.
    Old compressions used by old PKZip 1.x are not supported
 
-   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
-   CAN CHANGE IN FUTURE VERSION !!
+
    I WAIT FEEDBACK at mail info@winimage.com
    Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
 
@@ -33,10 +32,13 @@
 
 
 */
-/* for more info about .ZIP format, see 
-      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+
+/* for more info about .ZIP format, see
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+      http://www.info-zip.org/pub/infozip/doc/
    PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip */
+      ftp://ftp.pkware.com/probdesc.zip
+*/
 
 #ifndef _unz_H
 #define _unz_H
@@ -49,43 +51,47 @@
 #include "zlib.h"
 #endif
 
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
 #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
 /* like the STRICT of WIN32, we define a pointer that cannot be converted
     from (void*) without cast */
-typedef struct TagunzFile__ { int unused; } unzFile__; 
+typedef struct TagunzFile__ { int unused; } unzFile__;
 typedef unzFile__ *unzFile;
 #else
 typedef voidp unzFile;
 #endif
 
 
-#define UNZ_OK                                  (0)
-#define UNZ_END_OF_LIST_OF_FILE (-100)
-#define UNZ_ERRNO               (Z_ERRNO)
-#define UNZ_EOF                 (0)
+#define UNZ_OK                          (0)
+#define UNZ_END_OF_LIST_OF_FILE         (-100)
+#define UNZ_ERRNO                       (Z_ERRNO)
+#define UNZ_EOF                         (0)
 #define UNZ_PARAMERROR                  (-102)
 #define UNZ_BADZIPFILE                  (-103)
 #define UNZ_INTERNALERROR               (-104)
 #define UNZ_CRCERROR                    (-105)
 
 /* tm_unz contain date/time info */
-typedef struct tm_unz_s 
+typedef struct tm_unz_s
 {
-	uInt tm_sec;            /* seconds after the minute - [0,59] */
-	uInt tm_min;            /* minutes after the hour - [0,59] */
-	uInt tm_hour;           /* hours since midnight - [0,23] */
-	uInt tm_mday;           /* day of the month - [1,31] */
-	uInt tm_mon;            /* months since January - [0,11] */
-	uInt tm_year;           /* years - [1980..2044] */
+    uInt tm_sec;            /* seconds after the minute - [0,59] */
+    uInt tm_min;            /* minutes after the hour - [0,59] */
+    uInt tm_hour;           /* hours since midnight - [0,23] */
+    uInt tm_mday;           /* day of the month - [1,31] */
+    uInt tm_mon;            /* months since January - [0,11] */
+    uInt tm_year;           /* years - [1980..2044] */
 } tm_unz;
 
 /* unz_global_info structure contain global data about the ZIPfile
    These data comes from the end of central dir */
 typedef struct unz_global_info_s
 {
-	uLong number_entry;         /* total number of entries in
-				       the central dir on this disk */
-	uLong size_comment;         /* size of the global comment of the zipfile */
+    uLong number_entry;         /* total number of entries in
+                       the central dir on this disk */
+    uLong size_comment;         /* size of the global comment of the zipfile */
 } unz_global_info;
 
 
@@ -98,8 +104,8 @@
     uLong compression_method;   /* compression method              2 bytes */
     uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
     uLong crc;                  /* crc-32                          4 bytes */
-    uLong compressed_size;      /* compressed size                 4 bytes */ 
-    uLong uncompressed_size;    /* uncompressed size               4 bytes */ 
+    uLong compressed_size;      /* compressed size                 4 bytes */
+    uLong uncompressed_size;    /* uncompressed size               4 bytes */
     uLong size_filename;        /* filename length                 2 bytes */
     uLong size_file_extra;      /* extra field length              2 bytes */
     uLong size_file_comment;    /* file comment length             2 bytes */
@@ -112,27 +118,34 @@
 } unz_file_info;
 
 extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
-												 const char* fileName2,
-												 int iCaseSensitivity));
+                                                 const char* fileName2,
+                                                 int iCaseSensitivity));
 /*
    Compare two filename (fileName1,fileName2).
    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-								or strcasecmp)
+                                or strcasecmp)
    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-	(like 1 on Unix, 2 on Windows)
+    (like 1 on Unix, 2 on Windows)
 */
 
 
 extern unzFile ZEXPORT unzOpen OF((const char *path));
 /*
   Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
-	 "zlib/zlib111.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
+     on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+     "zlib/zlib113.zip".
+     If the zipfile cannot be opened (file don't exist or in not valid), the
+       return value is NULL.
      Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
+       of this unzip package.
+*/
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+                                    zlib_filefunc_def* pzlib_filefunc_def));
+/*
+   Open a Zip file, like unzOpen, but provide a set of file low level API
+      for read/write the zip file (see ioapi.h)
 */
 
 extern int ZEXPORT unzClose OF((unzFile file));
@@ -143,7 +156,7 @@
   return UNZ_OK if there is no problem. */
 
 extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
-					unz_global_info *pglobal_info));
+                                        unz_global_info *pglobal_info));
 /*
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
@@ -151,8 +164,8 @@
 
 
 extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
-										   char *szComment,
-					   uLong uSizeBuf));
+                                           char *szComment,
+                                           uLong uSizeBuf));
 /*
   Get the global comment string of the ZipFile, in the szComment buffer.
   uSizeBuf is the size of the szComment buffer.
@@ -176,9 +189,9 @@
   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
 */
 
-extern int ZEXPORT unzLocateFile OF((unzFile file, 
-				     const char *szFileName,
-				     int iCaseSensitivity));
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+                     const char *szFileName,
+                     int iCaseSensitivity));
 /*
   Try locate the file szFileName in the zipfile.
   For the iCaseSensitivity signification, see unzStringFileNameCompare
@@ -189,25 +202,44 @@
 */
 
 
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+    uLong pos_in_zip_directory;   /* offset in zip file directory */
+    uLong num_of_file;            /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+    unzFile file,
+    unz_file_pos* file_pos);
+
+/* ****************************************** */
+
 extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
-					     unz_file_info *pfile_info,
-					     char *szFileName,
-					     uLong fileNameBufferSize,
-					     void *extraField,
-					     uLong extraFieldBufferSize,
-					     char *szComment,
-					     uLong commentBufferSize));
+                         unz_file_info *pfile_info,
+                         char *szFileName,
+                         uLong fileNameBufferSize,
+                         void *extraField,
+                         uLong extraFieldBufferSize,
+                         char *szComment,
+                         uLong commentBufferSize));
 /*
   Get Info about the current file
   if pfile_info!=NULL, the *pfile_info structure will contain somes info about
-	    the current file
+        the current file
   if szFileName!=NULL, the filemane string will be copied in szFileName
-			(fileNameBufferSize is the size of the buffer)
+            (fileNameBufferSize is the size of the buffer)
   if extraField!=NULL, the extra field information will be copied in extraField
-			(extraFieldBufferSize is the size of the buffer).
-			This is the Central-header version of the extra field
+            (extraFieldBufferSize is the size of the buffer).
+            This is the Central-header version of the extra field
   if szComment!=NULL, the comment string of the file will be copied in szComment
-			(commentBufferSize is the size of the buffer)
+            (commentBufferSize is the size of the buffer)
 */
 
 /***************************************************************************/
@@ -221,16 +253,51 @@
   If there is no error, the return value is UNZ_OK.
 */
 
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+                                                  const char* password));
+/*
+  Open for reading data the current file in the zipfile.
+  password is a crypting password
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+                                           int* method,
+                                           int* level,
+                                           int raw,
+                                           const char* password));
+/*
+  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+    if raw==1
+  *method will receive method of compression, *level will receive level of
+     compression
+  note : you can set level parameter as NULL (if you did not want known level,
+         but you CANNOT set method parameter as NULL
+*/
+
+
 extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
 /*
   Close the file in zip opened with unzOpenCurrentFile
   Return UNZ_CRCERROR if all the file was read but the CRC is not good
 */
 
-												
-extern int ZEXPORT unzReadCurrentFile OF((unzFile file, 
-					  voidp buf,
-					  unsigned len));
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+                      voidp buf,
+                      unsigned len));
 /*
   Read bytes from the current file (opened by unzOpenCurrentFile)
   buf contain buffer where data must be copied
@@ -249,12 +316,12 @@
 
 extern int ZEXPORT unzeof OF((unzFile file));
 /*
-  return 1 if the end of file was reached, 0 elsewhere 
+  return 1 if the end of file was reached, 0 elsewhere
 */
 
 extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
-											 voidp buf,
-											 unsigned len));
+                                             voidp buf,
+                                             unsigned len));
 /*
   Read extra field from the current file (opened by unzOpenCurrentFile)
   This is the local-header version of the extra field (sometimes, there is
@@ -263,9 +330,9 @@
   if buf==NULL, it return the size of the local extra field
 
   if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of bytes copied in buf, or (if <0) 
-	the error code
+    buf.
+  the return value is the number of bytes copied in buf, or (if <0)
+    the error code
 */
 
 #ifdef __cplusplus
diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c
index 0cae64a..29c17d8 100644
--- a/contrib/minizip/zip.c
+++ b/contrib/minizip/zip.c
@@ -1,5 +1,5 @@
-/* zip.c -- IO on .zip files using zlib 
-   Version 0.15 beta, Mar 19th, 1998,
+/* zip.c -- IO on .zip files using zlib
+   Version 0.21, March 10th, 2003
 
    Read zip.h for more info
 */
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include "zlib.h"
 #include "zip.h"
 
@@ -66,8 +67,15 @@
 #define SEEK_SET    0
 #endif
 
+#ifndef DEF_MEM_LEVEL
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+#endif
 const char zip_copyright[] =
-   " zip 0.15 Copyright 1998 Gilles Vollant ";
+   " zip 0.21 Copyright 1998-2003 Gilles Vollant - http://www.winimage.com/zLibDll";
 
 
 #define SIZEDATA_INDATABLOCK (4096-(4*4))
@@ -99,33 +107,49 @@
 
 typedef struct
 {
-	z_stream stream;            /* zLib stream structure for inflate */
+    z_stream stream;            /* zLib stream structure for inflate */
     int  stream_initialised;    /* 1 is stream is initialised */
     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
 
-    uLong pos_local_header;     /* offset of the local header of the file 
+    uLong pos_local_header;     /* offset of the local header of the file
                                      currenty writing */
     char* central_header;       /* central header data for the current file */
     uLong size_centralheader;   /* size of the central header for cur file */
     uLong flag;                 /* flag of the file currently writing */
 
     int  method;                /* compression method of file currenty wr.*/
+    int  raw;                   /* 1 for directly writing raw data */
     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
     uLong dosDate;
     uLong crc32;
+    int  encrypt;
+#ifndef NOCRPYT
+    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
+    const unsigned long* pcrc_32_tab;
+    int crypt_header_size;
+#endif
 } curfile_info;
 
 typedef struct
 {
-    FILE * filezip;
+    zlib_filefunc_def z_filefunc;
+    voidpf filestream;        /* io structore of the zipfile */
     linkedlist_data central_dir;/* datablock with central dir in construction*/
     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
     curfile_info ci;            /* info on the file curretly writing */
 
     uLong begin_pos;            /* position of the beginning of the zipfile */
+    uLong add_position_when_writting_offset;
     uLong number_entry;
 } zip_internal;
 
+
+
+#ifndef NOCRPYT
+#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+#include "crypt.h"
+#endif
+
 local linkedlist_datablock_internal* allocate_new_datablock()
 {
     linkedlist_datablock_internal* ldi;
@@ -166,7 +190,7 @@
 
 
 local int add_data_in_datablock(ll,buf,len)
-    linkedlist_data* ll;    
+    linkedlist_data* ll;
     const void* buf;
     uLong len;
 {
@@ -220,32 +244,20 @@
 }
 
 
-local int write_datablock(fout,ll)
-    FILE * fout;
-    linkedlist_data* ll;    
-{
-    linkedlist_datablock_internal* ldi;
-    ldi = ll->first_block;
-    while (ldi!=NULL)
-    {
-        if (ldi->filled_in_this_block > 0)
-            if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1)
-                return ZIP_ERRNO;
-        ldi = ldi->next_datablock;
-    }
-    return ZIP_OK;
-}
 
 /****************************************************************************/
 
+#ifndef NO_ADDFILEINEXISTINGZIP
 /* ===========================================================================
-   Outputs a long in LSB order to the given file
+   Inputs a long in LSB order to the given file
    nbByte == 1, 2 or 4 (byte, short or long)
 */
 
-local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte));
-local int ziplocal_putValue (file, x, nbByte)
-    FILE *file;
+local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
+                                voidpf filestream, uLong x, int nbByte));
+local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
     uLong x;
     int nbByte;
 {
@@ -255,7 +267,7 @@
         buf[n] = (unsigned char)(x & 0xff);
         x >>= 8;
     }
-    if (fwrite(buf,nbByte,1,file)!=1)
+    if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
         return ZIP_ERRNO;
     else
         return ZIP_OK;
@@ -278,7 +290,7 @@
 
 
 local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
-    tm_zip* ptm;
+    const tm_zip* ptm;
     uLong dosDate;
 {
     uLong year = (uLong)ptm->tm_year;
@@ -294,38 +306,348 @@
 
 /****************************************************************************/
 
-extern zipFile ZEXPORT zipOpen (pathname, append)
+local int ziplocal_getByte OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    int *pi));
+
+local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    int *pi;
+{
+    unsigned char c;
+    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return ZIP_OK;
+    }
+    else
+    {
+        if (ZERROR(*pzlib_filefunc_def,filestream))
+            return ZIP_ERRNO;
+        else
+            return ZIP_EOF;
+    }
+}
+
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int ziplocal_getShort OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==ZIP_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int ziplocal_getLong OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream,
+    uLong *pX));
+
+local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x = (uLong)i;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<16;
+
+    if (err==ZIP_OK)
+        err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
+    x += ((uLong)i)<<24;
+
+    if (err==ZIP_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+local uLong ziplocal_SearchCentralDir OF((
+    const zlib_filefunc_def* pzlib_filefunc_def,
+    voidpf filestream));
+
+local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
+    const zlib_filefunc_def* pzlib_filefunc_def;
+    voidpf filestream;
+{
+    unsigned char* buf;
+    uLong uSizeFile;
+    uLong uBackRead;
+    uLong uMaxBack=0xffff; /* maximum size of global comment */
+    uLong uPosFound=0;
+
+    if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+        return 0;
+
+
+    uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
+
+    if (uMaxBack>uSizeFile)
+        uMaxBack = uSizeFile;
+
+    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+    if (buf==NULL)
+        return 0;
+
+    uBackRead = 4;
+    while (uBackRead<uMaxBack)
+    {
+        uLong uReadSize,uReadPos ;
+        int i;
+        if (uBackRead+BUFREADCOMMENT>uMaxBack)
+            uBackRead = uMaxBack;
+        else
+            uBackRead+=BUFREADCOMMENT;
+        uReadPos = uSizeFile-uBackRead ;
+
+        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            break;
+
+        if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+            break;
+
+        for (i=(int)uReadSize-3; (i--)>0;)
+            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+            {
+                uPosFound = uReadPos+i;
+                break;
+            }
+
+        if (uPosFound!=0)
+            break;
+    }
+    TRYFREE(buf);
+    return uPosFound;
+}
+#endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+/************************************************************/
+extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
     const char *pathname;
     int append;
+    zipcharpc* globalcomment;
+    zlib_filefunc_def* pzlib_filefunc_def;
 {
     zip_internal ziinit;
     zip_internal* zi;
+    int err=ZIP_OK;
 
-    ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab");
-    if (ziinit.filezip == NULL)
+
+    if (pzlib_filefunc_def==NULL)
+        fill_fopen_filefunc(&ziinit.z_filefunc);
+    else
+        ziinit.z_filefunc = *pzlib_filefunc_def;
+
+    ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
+                 (ziinit.z_filefunc.opaque,
+                  pathname,
+                  (append == APPEND_STATUS_CREATE) ?
+                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
+                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
+
+    if (ziinit.filestream == NULL)
         return NULL;
-    ziinit.begin_pos = ftell(ziinit.filezip);
+    ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
     ziinit.in_opened_file_inzip = 0;
     ziinit.ci.stream_initialised = 0;
     ziinit.number_entry = 0;
+    ziinit.add_position_when_writting_offset = 0;
     init_linkedlist(&(ziinit.central_dir));
 
 
     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
     if (zi==NULL)
     {
-        fclose(ziinit.filezip);
+        ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
         return NULL;
     }
 
-    *zi = ziinit;
-    return (zipFile)zi;
+    /* now we add file in a zipfile */
+    #ifndef NO_ADDFILEINEXISTINGZIP
+    if (append == APPEND_STATUS_ADDINZIP)
+    {
+        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+
+        uLong size_central_dir;     /* size of the central directory  */
+        uLong offset_central_dir;   /* offset of start of central directory */
+        uLong central_pos,uL;
+
+        uLong number_disk;          /* number of the current dist, used for
+                                    spaning ZIP, unsupported, always 0*/
+        uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                    for spaning ZIP, unsupported, always 0*/
+        uLong number_entry;
+        uLong number_entry_CD;      /* total number of entries in
+                                    the central dir
+                                    (same than number_entry on nospan) */
+        uLong size_comment;
+
+        central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
+        if (central_pos==0)
+            err=ZIP_ERRNO;
+
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=ZIP_ERRNO;
+
+        /* the signature, already checked */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* number of this disk */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* number of the disk with the start of the central directory */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* total number of entries in the central dir on this disk */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* total number of entries in the central dir */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        if ((number_entry_CD!=number_entry) ||
+            (number_disk_with_CD!=0) ||
+            (number_disk!=0))
+            err=ZIP_BADZIPFILE;
+
+        /* size of the central directory */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* offset of start of central directory with respect to the
+            starting disk number */
+        if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        /* zipfile comment length */
+        if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
+            err=ZIP_ERRNO;
+
+        if ((central_pos<offset_central_dir+size_central_dir) &&
+            (err==ZIP_OK))
+            err=ZIP_BADZIPFILE;
+
+        if (err!=ZIP_OK)
+        {
+            ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
+            return NULL;
+        }
+
+        byte_before_the_zipfile = central_pos -
+                                (offset_central_dir+size_central_dir);
+        ziinit.add_position_when_writting_offset = byte_before_the_zipfile ;
+
+        {
+            uLong size_central_dir_to_read = size_central_dir;
+            size_t buf_size = SIZEDATA_INDATABLOCK;
+            void* buf_read = (void*)ALLOC(buf_size);
+            if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                  offset_central_dir + byte_before_the_zipfile,
+                  ZLIB_FILEFUNC_SEEK_SET) != 0)
+                  err=ZIP_ERRNO;
+
+            while ((size_central_dir_to_read>0) && (err==ZIP_OK))
+            {
+                uLong read_this = SIZEDATA_INDATABLOCK;
+                if (read_this > size_central_dir_to_read)
+                    read_this = size_central_dir_to_read;
+                if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
+                    err=ZIP_ERRNO;
+
+                if (err==ZIP_OK)
+                    err = add_data_in_datablock(&ziinit.central_dir,buf_read,
+                                                (uLong)read_this);
+                size_central_dir_to_read-=read_this;
+            }
+            TRYFREE(buf_read);
+        }
+        ziinit.begin_pos = byte_before_the_zipfile;
+        ziinit.number_entry = number_entry_CD;
+
+        if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
+                  offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err=ZIP_ERRNO;
+    }
+    #endif /* !NO_ADDFILEINEXISTINGZIP*/
+
+    if (err != ZIP_OK)
+    {
+        TRYFREE(zi);
+        return NULL;
+    }
+    else
+    {
+        *zi = ziinit;
+        return (zipFile)zi;
+    }
 }
 
-extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, 
-                                        extrafield_local, size_extrafield_local,
-                                        extrafield_global, size_extrafield_global,
-                                        comment, method, level)
+extern zipFile ZEXPORT zipOpen (pathname, append)
+    const char *pathname;
+    int append;
+{
+    return zipOpen2(pathname,append,NULL,NULL);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
+                                         extrafield_local, size_extrafield_local,
+                                         extrafield_global, size_extrafield_global,
+                                         comment, method, level, raw,
+                                         windowBits, memLevel, strategy,
+                                         password, crcForCrypting)
     zipFile file;
     const char* filename;
     const zip_fileinfo* zipfi;
@@ -336,6 +658,12 @@
     const char* comment;
     int method;
     int level;
+    int raw;
+    int windowBits;
+    int memLevel;
+    int strategy;
+    const char* password;
+    uLong crcForCrypting;
 {
     zip_internal* zi;
     uInt size_filename;
@@ -343,6 +671,11 @@
     uInt i;
     int err = ZIP_OK;
 
+    #ifdef NOCRPYT
+    if (password != NULL)
+        return ZIP_PARAMERROR;
+    #endif
+
     if (file == NULL)
         return ZIP_PARAMERROR;
     if ((method!=0) && (method!=Z_DEFLATED))
@@ -384,13 +717,17 @@
       zi->ci.flag |= 4;
     if ((level==1))
       zi->ci.flag |= 6;
+    if (password != NULL)
+      zi->ci.flag |= 1;
 
     zi->ci.crc32 = 0;
     zi->ci.method = method;
+    zi->ci.encrypt = 0;
     zi->ci.stream_initialised = 0;
     zi->ci.pos_in_buffered_data = 0;
-    zi->ci.pos_local_header = ftell(zi->filezip);
-    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 
+    zi->ci.raw = raw;
+    zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
+    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
                                       size_extrafield_global + size_comment;
     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
 
@@ -410,16 +747,16 @@
     ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
 
     if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
     else
-        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
 
     if (zipfi==NULL)
-        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
     else
         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
 
-    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4);
+    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
 
     for (i=0;i<size_filename;i++)
         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
@@ -430,44 +767,44 @@
 
     for (i=0;i<size_comment;i++)
         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
-              size_extrafield_global+i) = *(filename+i);
+              size_extrafield_global+i) = *(comment+i);
     if (zi->ci.central_header == NULL)
         return ZIP_INTERNALERROR;
 
     /* write the local header */
-    err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4);
+    err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
 
     if (err==ZIP_OK)
-        err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
 
     if ((err==ZIP_OK) && (size_filename>0))
-        if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
+        if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
                 err = ZIP_ERRNO;
 
     if ((err==ZIP_OK) && (size_extrafield_local>0))
-        if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
-                                                                           !=1)
+        if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
+                                                                           !=size_extrafield_local)
                 err = ZIP_ERRNO;
 
     zi->ci.stream.avail_in = (uInt)0;
@@ -476,17 +813,38 @@
     zi->ci.stream.total_in = 0;
     zi->ci.stream.total_out = 0;
 
-    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
+    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
     {
         zi->ci.stream.zalloc = (alloc_func)0;
         zi->ci.stream.zfree = (free_func)0;
         zi->ci.stream.opaque = (voidpf)0;
 
+        if (windowBits>0)
+            windowBits = -windowBits;
+
         err = deflateInit2(&zi->ci.stream, level,
-               Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
+               Z_DEFLATED, windowBits, memLevel, strategy);
 
         if (err==Z_OK)
             zi->ci.stream_initialised = 1;
+
+        #ifndef NOCRPYT
+        zi->ci.crypt_header_size = 0;
+        if ((err==Z_OK) && (password != NULL))
+        {
+            unsigned char bufHead[RAND_HEAD_LEN];
+            unsigned int sizeHead;
+            zi->ci.encrypt = 1;
+            zi->ci.pcrc_32_tab = get_crc_table();
+            /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
+
+            sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
+            zi->ci.crypt_header_size = sizeHead;
+
+            if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
+                    err = ZIP_ERRNO;
+        }
+        #endif
     }
 
 
@@ -495,9 +853,74 @@
     return err;
 }
 
+extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
+                                        extrafield_local, size_extrafield_local,
+                                        extrafield_global, size_extrafield_global,
+                                        comment, method, level, raw)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+    int raw;
+{
+    return zipOpenNewFileInZip3 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, raw,
+                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+                                 NULL, 0);
+}
+
+extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
+                                        extrafield_local, size_extrafield_local,
+                                        extrafield_global, size_extrafield_global,
+                                        comment, method, level)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+{
+    return zipOpenNewFileInZip2 (file, filename, zipfi,
+                                 extrafield_local, size_extrafield_local,
+                                 extrafield_global, size_extrafield_global,
+                                 comment, method, level, 0);
+}
+
+local int zipFlushWriteBuffer(zi)
+  zip_internal* zi;
+{
+    int err=ZIP_OK;
+
+    if (zi->ci.encrypt != 0)
+    {
+        uInt i;
+        int t;
+        for (i=0;i<zi->ci.pos_in_buffered_data;i++)
+            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
+                                       zi->ci.buffered_data[i],t);
+    }
+    if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
+                                                                    !=zi->ci.pos_in_buffered_data)
+      err = ZIP_ERRNO;
+    zi->ci.pos_in_buffered_data = 0;
+    return err;
+}
+
 extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
     zipFile file;
-    const voidp buf;
+    const void* buf;
     unsigned len;
 {
     zip_internal* zi;
@@ -510,7 +933,7 @@
     if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
 
-    zi->ci.stream.next_in = buf;
+    zi->ci.stream.next_in = (void*)buf;
     zi->ci.stream.avail_in = len;
     zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
 
@@ -518,15 +941,17 @@
     {
         if (zi->ci.stream.avail_out == 0)
         {
-            if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
-                                                                           !=1)
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
                 err = ZIP_ERRNO;
-            zi->ci.pos_in_buffered_data = 0;
             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
             zi->ci.stream.next_out = zi->ci.buffered_data;
         }
 
-        if (zi->ci.method == Z_DEFLATED)
+
+        if(err != ZIP_OK)
+            break;
+
+        if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
         {
             uLong uTotalOutBefore = zi->ci.stream.total_out;
             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
@@ -555,33 +980,34 @@
         }
     }
 
-    return 0;
+    return err;
 }
 
-extern int ZEXPORT zipCloseFileInZip (file)
+extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
     zipFile file;
+    uLong uncompressed_size;
+    uLong crc32;
 {
     zip_internal* zi;
+    uLong compressed_size;
     int err=ZIP_OK;
 
     if (file == NULL)
         return ZIP_PARAMERROR;
     zi = (zip_internal*)file;
 
-    if (zi->in_opened_file_inzip == 0)    
+    if (zi->in_opened_file_inzip == 0)
         return ZIP_PARAMERROR;
     zi->ci.stream.avail_in = 0;
-    
-    if (zi->ci.method == Z_DEFLATED)
+
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
         while (err==ZIP_OK)
     {
         uLong uTotalOutBefore;
         if (zi->ci.stream.avail_out == 0)
         {
-            if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
-                                                                           !=1)
+            if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
                 err = ZIP_ERRNO;
-            zi->ci.pos_in_buffered_data = 0;
             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
             zi->ci.stream.next_out = zi->ci.buffered_data;
         }
@@ -594,21 +1020,32 @@
         err=ZIP_OK; /* this is normal */
 
     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
-        if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
-                                                                       !=1)
+        if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
             err = ZIP_ERRNO;
 
-    if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
+    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
     {
         err=deflateEnd(&zi->ci.stream);
         zi->ci.stream_initialised = 0;
     }
 
-    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/
+    if (!zi->ci.raw)
+    {
+        crc32 = (uLong)zi->ci.crc32;
+        uncompressed_size = (uLong)zi->ci.stream.total_in;
+    }
+    compressed_size = (uLong)zi->ci.stream.total_out;
+    #ifndef NOCRPYT
+    compressed_size += zi->ci.crypt_header_size;
+    #endif
+
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
     ziplocal_putValue_inmemory(zi->ci.central_header+20,
-                                (uLong)zi->ci.stream.total_out,4); /*compr size*/
+                                compressed_size,4); /*compr size*/
+    if (zi->ci.stream.data_type == Z_ASCII)
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
     ziplocal_putValue_inmemory(zi->ci.central_header+24,
-                                (uLong)zi->ci.stream.total_in,4); /*uncompr size*/
+                                uncompressed_size,4); /*uncompr size*/
 
     if (err==ZIP_OK)
         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
@@ -617,23 +1054,23 @@
 
     if (err==ZIP_OK)
     {
-        long cur_pos_inzip = ftell(zi->filezip);
-	    if (fseek(zi->filezip,
-                  zi->ci.pos_local_header + 14,SEEK_SET)!=0)
-		    err = ZIP_ERRNO;
+        long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
+        if (ZSEEK(zi->z_filefunc,zi->filestream,
+                  zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err = ZIP_ERRNO;
 
         if (err==ZIP_OK)
-            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
 
         if (err==ZIP_OK) /* compressed size, unknown */
-            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); 
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
 
         if (err==ZIP_OK) /* uncompressed size, unknown */
-            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4);
+            err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
 
-	    if (fseek(zi->filezip,
-                  cur_pos_inzip,SEEK_SET)!=0)
-		    err = ZIP_ERRNO;
+        if (ZSEEK(zi->z_filefunc,zi->filestream,
+                  cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
+            err = ZIP_ERRNO;
     }
 
     zi->number_entry ++;
@@ -642,6 +1079,12 @@
     return err;
 }
 
+extern int ZEXPORT zipCloseFileInZip (file)
+    zipFile file;
+{
+    return zipCloseFileInZipRaw (file,0,0);
+}
+
 extern int ZEXPORT zipClose (file, global_comment)
     zipFile file;
     const char* global_comment;
@@ -666,15 +1109,16 @@
         size_global_comment = strlen(global_comment);
 
 
-    centraldir_pos_inzip = ftell(zi->filezip);
+    centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
     if (err==ZIP_OK)
     {
         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
         while (ldi!=NULL)
         {
             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
-                if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
-                                        1,zi->filezip) !=1 )
+                if (ZWRITE(zi->z_filefunc,zi->filestream,
+                           ldi->data,ldi->filled_in_this_block)
+                              !=ldi->filled_in_this_block )
                     err = ZIP_ERRNO;
 
             size_centraldir += ldi->filled_in_this_block;
@@ -684,34 +1128,40 @@
     free_datablock(zi->central_dir.first_block);
 
     if (err==ZIP_OK) /* Magic End */
-        err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
 
     if (err==ZIP_OK) /* number of this disk */
-        err = ziplocal_putValue(zi->filezip,(uLong)0,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
 
     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
-        err = ziplocal_putValue(zi->filezip,(uLong)0,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
 
     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
-        err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
 
     if (err==ZIP_OK) /* total number of entries in the central dir */
-        err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
 
     if (err==ZIP_OK) /* size of the central directory */
-        err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
 
-    if (err==ZIP_OK) /* offset of start of central directory with respect to the 
-	                        starting disk number */
-        err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4);
+    if (err==ZIP_OK) /* offset of start of central directory with respect to the
+                            starting disk number */
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
+                                (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
 
     if (err==ZIP_OK) /* zipfile comment length */
-        err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
+        err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
 
     if ((err==ZIP_OK) && (size_global_comment>0))
-        if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
+        if (ZWRITE(zi->z_filefunc,zi->filestream,
+                   global_comment,size_global_comment) != size_global_comment)
                 err = ZIP_ERRNO;
-    fclose(zi->filezip);
+
+    if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
+        if (err == ZIP_OK)
+            err = ZIP_ERRNO;
+
     TRYFREE(zi);
 
     return err;
diff --git a/contrib/minizip/zip.def b/contrib/minizip/zip.def
deleted file mode 100644
index 5d5079f..0000000
--- a/contrib/minizip/zip.def
+++ /dev/null
@@ -1,5 +0,0 @@
-	zipOpen                       @80
-	zipOpenNewFileInZip           @81
-	zipWriteInFileInZip           @82
-	zipCloseFileInZip             @83
-	zipClose                      @84
diff --git a/contrib/minizip/zip.h b/contrib/minizip/zip.h
index 678260b..4bc6aa4 100644
--- a/contrib/minizip/zip.h
+++ b/contrib/minizip/zip.h
@@ -1,7 +1,7 @@
-/* zip.h -- IO for compress .zip files using zlib 
-   Version 0.15 alpha, Mar 19th, 1998,
+/* zip.h -- IO for compress .zip files using zlib
+   Version 0.21, March 10th, 2003
 
-   Copyright (C) 1998 Gilles Vollant
+   Copyright (C) 1998-2003 Gilles Vollant
 
    This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
      WinZip, InfoZip tools and compatible.
@@ -10,10 +10,9 @@
 
   For uncompress .zip file, look at unzip.h
 
-   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
-   CAN CHANGE IN FUTURE VERSION !!
+
    I WAIT FEEDBACK at mail info@winimage.com
-   Visit also http://www.winimage.com/zLibDll/zip.htm for evolution
+   Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
 
    Condition of use and distribution are the same than zlib :
 
@@ -36,8 +35,9 @@
 
 */
 
-/* for more info about .ZIP format, see 
-      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+/* for more info about .ZIP format, see
+      http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
+      http://www.info-zip.org/pub/infozip/doc/
    PkWare has also a specification at :
       ftp://ftp.pkware.com/probdesc.zip
 */
@@ -53,34 +53,49 @@
 #include "zlib.h"
 #endif
 
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
 #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
 /* like the STRICT of WIN32, we define a pointer that cannot be converted
     from (void*) without cast */
-typedef struct TagzipFile__ { int unused; } zipFile__; 
+typedef struct TagzipFile__ { int unused; } zipFile__;
 typedef zipFile__ *zipFile;
 #else
 typedef voidp zipFile;
 #endif
 
-#define ZIP_OK                                  (0)
-#define ZIP_ERRNO               (Z_ERRNO)
+#define ZIP_OK                          (0)
+#define ZIP_EOF                         (0)
+#define ZIP_ERRNO                       (Z_ERRNO)
 #define ZIP_PARAMERROR                  (-102)
+#define ZIP_BADZIPFILE                  (-103)
 #define ZIP_INTERNALERROR               (-104)
 
+#ifndef DEF_MEM_LEVEL
+#  if MAX_MEM_LEVEL >= 8
+#    define DEF_MEM_LEVEL 8
+#  else
+#    define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#  endif
+#endif
+/* default memLevel */
+
 /* tm_zip contain date/time info */
-typedef struct tm_zip_s 
+typedef struct tm_zip_s
 {
-	uInt tm_sec;            /* seconds after the minute - [0,59] */
-	uInt tm_min;            /* minutes after the hour - [0,59] */
-	uInt tm_hour;           /* hours since midnight - [0,23] */
-	uInt tm_mday;           /* day of the month - [1,31] */
-	uInt tm_mon;            /* months since January - [0,11] */
-	uInt tm_year;           /* years - [1980..2044] */
+    uInt tm_sec;            /* seconds after the minute - [0,59] */
+    uInt tm_min;            /* minutes after the hour - [0,59] */
+    uInt tm_hour;           /* hours since midnight - [0,23] */
+    uInt tm_mday;           /* day of the month - [1,31] */
+    uInt tm_mon;            /* months since January - [0,11] */
+    uInt tm_year;           /* years - [1980..2044] */
 } tm_zip;
 
 typedef struct
 {
-	tm_zip      tmz_date;       /* date in understandable format           */
+    tm_zip      tmz_date;       /* date in understandable format           */
     uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */
 /*    uLong       flag;        */   /* general purpose bit flag        2 bytes */
 
@@ -88,30 +103,48 @@
     uLong       external_fa;    /* external file attributes        4 bytes */
 } zip_fileinfo;
 
+typedef const char* zipcharpc;
+
+
+#define APPEND_STATUS_CREATE        (0)
+#define APPEND_STATUS_CREATEAFTER   (1)
+#define APPEND_STATUS_ADDINZIP      (2)
+
 extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
 /*
   Create a zipfile.
-	 pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on
-	   an Unix computer "zlib/zlib111.zip".
-	 if the file pathname exist and append=1, the zip will be created at the end
-	   of the file. (useful if the file contain a self extractor code)
-	 If the zipfile cannot be opened, the return value is NULL.
+     pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
+       an Unix computer "zlib/zlib113.zip".
+     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
+       will be created at the end of the file.
+         (useful if the file contain a self extractor code)
+     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
+       add files in existing zip (be sure you don't add file that doesn't exist)
+     If the zipfile cannot be opened, the return value is NULL.
      Else, the return value is a zipFile Handle, usable with other function
-	   of this zip package.
-
-
+       of this zip package.
 */
 
+/* Note : there is no delete function into a zipfile.
+   If you want delete file into a zipfile, you must open a zipfile, and create another
+   Of couse, you can use RAW reading and writing to copy the file you did not want delte
+*/
+
+extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
+                                   int append,
+                                   zipcharpc* globalcomment,
+                                   zlib_filefunc_def* pzlib_filefunc_def));
+
 extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
-					   const char* filename,
-					   const zip_fileinfo* zipfi,
-					   const void* extrafield_local,
-					   uInt size_extrafield_local,
-					   const void* extrafield_global,
-					   uInt size_extrafield_global,
-					   const char* comment,
-					   int method,
-					   int level));
+                       const char* filename,
+                       const zip_fileinfo* zipfi,
+                       const void* extrafield_local,
+                       uInt size_extrafield_local,
+                       const void* extrafield_global,
+                       uInt size_extrafield_global,
+                       const char* comment,
+                       int method,
+                       int level));
 /*
   Open a file in the ZIP for writing.
   filename : the filename in zip (if NULL, '-' without quote will be used
@@ -125,9 +158,51 @@
   level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
 */
 
+
+extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw));
+
+/*
+  Same than zipOpenNewFileInZip, except if raw=1, we write raw file
+ */
+
+extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
+                                            const char* filename,
+                                            const zip_fileinfo* zipfi,
+                                            const void* extrafield_local,
+                                            uInt size_extrafield_local,
+                                            const void* extrafield_global,
+                                            uInt size_extrafield_global,
+                                            const char* comment,
+                                            int method,
+                                            int level,
+                                            int raw,
+                                            int windowBits,
+                                            int memLevel,
+                                            int strategy,
+                                            const char* password,
+                                            uLong crcForCtypting));
+
+/*
+  Same than zipOpenNewFileInZip2, except
+    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
+    password : crypting password (NULL for no crypting)
+    crcForCtypting : crc of file to compress (needed for crypting)
+ */
+
+
 extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
-					   const voidp buf,
-					   unsigned len));
+                       const void* buf,
+                       unsigned len));
 /*
   Write data in the zipfile
 */
@@ -137,8 +212,18 @@
   Close the current file in the zipfile
 */
 
+
+extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
+                                            uLong uncompressed_size,
+                                            uLong crc32));
+/*
+  Close the current file in the zipfile, for fiel opened with
+    parameter raw=1 in zipOpenNewFileInZip2
+  uncompressed_size and crc32 are value for the uncompressed size
+*/
+
 extern int ZEXPORT zipClose OF((zipFile file,
-				const char* global_comment));
+                const char* global_comment));
 /*
   Close the zipfile
 */
diff --git a/contrib/minizip/zlibvc.dsp b/contrib/minizip/zlibvc.dsp
deleted file mode 100644
index a70d4d4..0000000
--- a/contrib/minizip/zlibvc.dsp
+++ /dev/null
@@ -1,651 +0,0 @@
-# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602
-
-CFG=zlibvc - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "zlibvc.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\
- "Win32 (ALPHA) Dynamic-Link Library")
-!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ".\Release"
-# PROP BASE Intermediate_Dir ".\Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release"
-# PROP Intermediate_Dir ".\Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
-# SUBTRACT CPP /YX
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x40c /d "NDEBUG"
-# ADD RSC /l 0x40c /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
-# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir ".\Debug"
-# PROP BASE Intermediate_Dir ".\Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug"
-# PROP Intermediate_Dir ".\Debug"
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c
-# SUBTRACT CPP /YX
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x40c /d "_DEBUG"
-# ADD RSC /l 0x40c /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlibvc__"
-# PROP BASE Intermediate_Dir "zlibvc__"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "zlibvc__"
-# PROP Intermediate_Dir "zlibvc__"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-CPP=cl.exe
-# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
-# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
-# SUBTRACT CPP /YX
-RSC=rc.exe
-# ADD BASE RSC /l 0x40c /d "NDEBUG"
-# ADD RSC /l 0x40c /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll"
-# SUBTRACT BASE LINK32 /pdb:none
-# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlibvc_0"
-# PROP BASE Intermediate_Dir "zlibvc_0"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "zlibvc_0"
-# PROP Intermediate_Dir "zlibvc_0"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c
-# SUBTRACT CPP /YX
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x40c /d "NDEBUG"
-# ADD RSC /l 0x40c /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
-# SUBTRACT BASE LINK32 /pdb:none
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "zlibvc_1"
-# PROP BASE Intermediate_Dir "zlibvc_1"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "zlibvc_1"
-# PROP Intermediate_Dir "zlibvc_1"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-CPP=cl.exe
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c
-# SUBTRACT CPP /YX
-MTL=midl.exe
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-# ADD BASE RSC /l 0x40c /d "NDEBUG"
-# ADD RSC /l 0x40c /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll"
-# SUBTRACT BASE LINK32 /pdb:none
-# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll"
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF 
-
-# Begin Target
-
-# Name "zlibvc - Win32 Release"
-# Name "zlibvc - Win32 Debug"
-# Name "zlibvc - Win32 ReleaseAxp"
-# Name "zlibvc - Win32 ReleaseWithoutAsm"
-# Name "zlibvc - Win32 ReleaseWithoutCrtdll"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\adler32.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_ADLER=\
-	".\zconf.h"\
-	".\zlib.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\compress.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_COMPR=\
-	".\zconf.h"\
-	".\zlib.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\crc32.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_CRC32=\
-	".\zconf.h"\
-	".\zlib.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\deflate.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_DEFLA=\
-	".\deflate.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\gvmat32c.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\gzio.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_GZIO_=\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\infblock.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFBL=\
-	".\infblock.h"\
-	".\infcodes.h"\
-	".\inftrees.h"\
-	".\infutil.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\infcodes.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFCO=\
-	".\infblock.h"\
-	".\infcodes.h"\
-	".\inffast.h"\
-	".\inftrees.h"\
-	".\infutil.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\inffast.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFFA=\
-	".\infblock.h"\
-	".\infcodes.h"\
-	".\inffast.h"\
-	".\inftrees.h"\
-	".\infutil.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\inflate.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFLA=\
-	".\infblock.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\inftrees.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFTR=\
-	".\inftrees.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\infutil.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_INFUT=\
-	".\infblock.h"\
-	".\infcodes.h"\
-	".\inftrees.h"\
-	".\infutil.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\trees.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_TREES=\
-	".\deflate.h"\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\uncompr.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_UNCOM=\
-	".\zconf.h"\
-	".\zlib.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\unzip.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\zip.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# Begin Source File
-
-SOURCE=.\zlib.rc
-# End Source File
-# Begin Source File
-
-SOURCE=.\zlibvc.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\zutil.c
-
-!IF  "$(CFG)" == "zlibvc - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 Debug"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseAxp"
-
-DEP_CPP_ZUTIL=\
-	".\zconf.h"\
-	".\zlib.h"\
-	".\zutil.h"\
-	
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm"
-
-!ELSEIF  "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll"
-
-!ENDIF 
-
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
-# Begin Source File
-
-SOURCE=.\deflate.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\infblock.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\infcodes.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\inffast.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\inftrees.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\infutil.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\zutil.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/contrib/minizip/zlibvc.dsw b/contrib/minizip/zlibvc.dsw
deleted file mode 100644
index 493cd87..0000000
--- a/contrib/minizip/zlibvc.dsw
+++ /dev/null
@@ -1,41 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 5.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/contrib/testzlib/testzlib.c b/contrib/testzlib/testzlib.c
new file mode 100644
index 0000000..caae4ef
--- /dev/null
+++ b/contrib/testzlib/testzlib.c
@@ -0,0 +1,149 @@
+

+#include <stdio.h>

+#include <stdlib.h>

+#include <windows.h>

+#include "zlib.h"

+

+int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)

+{

+    FILE* stream;

+    void* ptr;

+    int retVal=1;

+    stream=fopen(filename, "rb");

+    if (stream==NULL)

+        return 0;

+

+    fseek(stream,0,SEEK_END);

+

+    *plFileSize=ftell(stream);

+    fseek(stream,0,SEEK_SET);

+    ptr=malloc((*plFileSize)+1);

+    if (ptr==NULL)

+        retVal=0;

+    else

+    {

+        if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))

+            retVal=0;

+    }

+    fclose(stream);

+    *pFilePtr=ptr;

+    return retVal;

+}

+

+int main(int argc, char *argv[])

+{

+    int BlockSizeCompress=0x8000;

+    int BlockSizeUncompress=0x8000;

+    int cprLevel=Z_DEFAULT_COMPRESSION ;

+    long lFileSize;

+    unsigned char* FilePtr;

+    long lBufferSizeCpr;

+    long lBufferSizeUncpr;

+    long lCompressedSize=0;

+    unsigned char* CprPtr;

+    unsigned char* UncprPtr;

+    long lSizeCpr,lSizeUncpr;

+    DWORD dwGetTick;

+

+    if (argc<=1)

+    {

+        printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");

+        return 0;

+    }

+

+    if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)

+    {

+        printf("error reading %s\n",argv[1]);

+        return 1;

+    }

+    else printf("file %s read, %u bytes\n",argv[1],lFileSize);

+

+    if (argc>=3)

+        BlockSizeCompress=atol(argv[2]);

+

+    if (argc>=4)

+        BlockSizeUncompress=atol(argv[3]);

+

+    if (argc>=5)

+        cprLevel=(int)atol(argv[4]);

+

+    lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;

+    lBufferSizeUncpr = lBufferSizeCpr;

+

+    CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);

+    UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);

+

+    dwGetTick=GetTickCount();

+    {

+        z_stream zcpr;

+        int ret=Z_OK;

+        long lOrigToDo = lFileSize;

+        long lOrigDone = 0;

+        int step=0;

+        memset(&zcpr,0,sizeof(z_stream));

+        deflateInit(&zcpr,cprLevel);

+

+        zcpr.next_in = FilePtr;

+        zcpr.next_out = CprPtr;

+

+

+        do

+        {

+            long all_read_before = zcpr.total_in;

+            zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);

+            zcpr.avail_out = BlockSizeCompress;

+            ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);

+            lOrigDone += (zcpr.total_in-all_read_before);

+            lOrigToDo -= (zcpr.total_in-all_read_before);

+            step++;

+        } while (ret==Z_OK);

+

+        lSizeCpr=zcpr.total_out;

+        deflateEnd(&zcpr);

+        dwGetTick=GetTickCount()-dwGetTick;

+        printf("total compress size = %u, in %u step\n",lSizeCpr,step);

+        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);

+    }

+

+    dwGetTick=GetTickCount();

+    {

+        z_stream zcpr;

+        int ret=Z_OK;

+        long lOrigToDo = lSizeCpr;

+        long lOrigDone = 0;

+        int step=0;

+        memset(&zcpr,0,sizeof(z_stream));

+        inflateInit(&zcpr);

+

+        zcpr.next_in = CprPtr;

+        zcpr.next_out = UncprPtr;

+

+

+        do

+        {

+            long all_read_before = zcpr.total_in;

+            zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);

+            zcpr.avail_out = BlockSizeUncompress;

+            ret=inflate(&zcpr,Z_SYNC_FLUSH);

+            lOrigDone += (zcpr.total_in-all_read_before);

+            lOrigToDo -= (zcpr.total_in-all_read_before);

+            step++;

+        } while (ret==Z_OK);

+

+        lSizeUncpr=zcpr.total_out;

+        inflateEnd(&zcpr);

+        dwGetTick=GetTickCount()-dwGetTick;

+        printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);

+        printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.);

+    }

+

+    if (lSizeUncpr==lFileSize)

+    {

+        if (memcmp(FilePtr,UncprPtr,lFileSize)==0)

+            printf("compare ok\n");

+

+    }

+

+    return 0;

+

+}

diff --git a/contrib/testzlib/testzlib.sln b/contrib/testzlib/testzlib.sln
new file mode 100644
index 0000000..86da716
--- /dev/null
+++ b/contrib/testzlib/testzlib.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		ConfigName.0 = Debug

+		ConfigName.1 = Release

+	EndGlobalSection

+	GlobalSection(ProjectDependencies) = postSolution

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug.ActiveCfg = Debug|Win32

+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug.Build.0 = Debug|Win32

+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release.ActiveCfg = Release|Win32

+		{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/contrib/testzlib/testzlib.vcproj b/contrib/testzlib/testzlib.vcproj
new file mode 100644
index 0000000..8e4233a
--- /dev/null
+++ b/contrib/testzlib/testzlib.vcproj
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding = "Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.00"

+	Name="testzlib"

+	ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/testzlib.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/testzlib.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="2"

+				InlineFunctionExpansion="1"

+				OmitFramePointers="TRUE"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				StringPooling="TRUE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/testzlib.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				OptimizeForWindows98="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+	</Configurations>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">

+			<File

+				RelativePath="testzlib.c">

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc">

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">

+		</Filter>

+		<File

+			RelativePath="zlib.lib">

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/contrib/vstudio/readme.txt b/contrib/vstudio/readme.txt
new file mode 100644
index 0000000..a619b96
--- /dev/null
+++ b/contrib/vstudio/readme.txt
@@ -0,0 +1,17 @@
+For create the 16 and 32 bits DLL of Zlib 1.20

+

+For the 16 bits :

+unzip zlib120.zip and copy file from contrib\vstudio\vc15_16 and from contrib\minizip in the same directory

+open zlib16.mak with Microsoft Visual C++ 1.52

+

+

+For the 32 bits :

+unzip zlib120.zip and copy file from contrib\vstudio\vc70_32 and from contrib\minizip in the same directory

+You can also need unzip http://www.winimage.com/zLibDll/crtdll.zip

+

+If you are using x86, use target Release

+open zlibvc.sln with Microsoft Visual C++ 7.0 (Visual Studio .net)

+

+

+Note : You don't need recompile yourself. There is compiled .LIB in

+  http://www.winimage.com/zLibDll

diff --git a/contrib/vstudio/vc15_16/zlib16.def b/contrib/vstudio/vc15_16/zlib16.def
new file mode 100644
index 0000000..89cb8d1
--- /dev/null
+++ b/contrib/vstudio/vc15_16/zlib16.def
@@ -0,0 +1,94 @@
+LIBRARY		"zlib"

+

+DESCRIPTION	'"""zlib data compression library"""'

+

+EXETYPE		WINDOWS

+

+VERSION		1.20

+

+CODE    PRELOAD MOVEABLE DISCARDABLE

+DATA    PRELOAD MOVEABLE SINGLE

+

+

+HEAPSIZE	32768,8192

+

+EXPORTS

+        adler32                                  @1

+        compress                                 @2

+        crc32                                    @3

+        deflate                                  @4

+        deflateCopy                              @5

+        deflateEnd                               @6

+        deflateInit2_                            @7

+        deflateInit_                             @8

+        deflateParams                            @9

+        deflateReset                             @10

+        deflateSetDictionary                     @11

+        gzclose                                  @12

+        gzdopen                                  @13

+        gzerror                                  @14

+        gzflush                                  @15

+        gzopen                                   @16

+        gzread                                   @17

+        gzwrite                                  @18

+        inflate                                  @19

+        inflateEnd                               @20

+        inflateInit2_                            @21

+        inflateInit_                             @22

+        inflateReset                             @23

+        inflateSetDictionary                     @24

+        inflateSync                              @25

+        uncompress                               @26

+        zlibVersion                              @27

+        _gzprintf                                @28

+        gzputc                                   @29

+        gzgetc                                   @30

+        gzseek                                   @31

+        gzrewind                                 @32

+        gztell                                   @33

+        gzeof                                    @34

+        gzsetparams                              @35

+        zError                                   @36

+        inflateSyncPoint                         @37

+        get_crc_table                            @38

+        compress2                                @39

+        gzputs                                   @40

+        gzgets                                   @41

+        inflateCopy                              @42

+        inflateBackInit_                         @43

+        inflateBack                              @44

+        inflateBackEnd                           @45

+        compressBound                            @46

+

+        unzOpen                                  @61

+        unzClose                                 @62

+        unzGetGlobalInfo                         @63

+        unzGetCurrentFileInfo                    @64

+        unzGoToFirstFile                         @65

+        unzGoToNextFile                          @66

+        unzOpenCurrentFile                       @67

+        unzReadCurrentFile                       @68

+        unzOpenCurrentFile3                      @69

+        unztell                                  @70

+        unzeof                                   @71

+        unzCloseCurrentFile                      @72

+        unzGetGlobalComment                      @73

+        unzStringFileNameCompare                 @74

+        unzLocateFile                            @75

+        unzGetLocalExtrafield                    @76

+        unzOpen2                                 @77

+        unzOpenCurrentFile2                      @78

+        unzOpenCurrentFilePassword               @79

+

+        zipOpen                                  @80

+        zipOpenNewFileInZip                      @81

+        zipWriteInFileInZip                      @82

+        zipCloseFileInZip                        @83

+        zipClose                                 @84

+        zipOpenNewFileInZip2                     @86

+        zipCloseFileInZipRaw                     @87

+        zipOpen2                                 @88

+        zipOpenNewFileInZip3                     @89

+

+        unzGetFilePos                            @100

+        unzGoToFilePos                           @101

diff --git a/contrib/vstudio/vc15_16/zlib16.mak b/contrib/vstudio/vc15_16/zlib16.mak
new file mode 100644
index 0000000..75c8d80
--- /dev/null
+++ b/contrib/vstudio/vc15_16/zlib16.mak
@@ -0,0 +1,256 @@
+# Microsoft Visual C++ generated build script - Do not modify

+

+PROJ = ZLIB16

+DEBUG = 0

+PROGTYPE = 1

+CALLER = 

+ARGS = 

+DLLS = 

+D_RCDEFINES = -d_DEBUG

+R_RCDEFINES = -dNDEBUG

+ORIGIN = MSVC

+ORIGIN_VER = 1.00

+PROJPATH = c:\zlib\

+USEMFC = 0

+CC = cl

+CPP = cl

+CXX = cl

+CCREATEPCHFLAG = 

+CPPCREATEPCHFLAG = 

+CUSEPCHFLAG = 

+CPPUSEPCHFLAG = 

+FIRSTC = ADLER32.C   

+FIRSTCPP =             

+RC = rc

+CFLAGS_D_WDLL = /nologo /G2 /W3 /Zi /ALw /Od /D "_DEBUG" /D "WINDOWS" /D "ZLIB_DLL" /FR /GD /Fd"ZLIB.PDB"

+CFLAGS_R_WDLL = /nologo /W3 /ALw /O1 /D "NDEBUG" /D "WINDOWS" /D "ZLIB_DLL" /FR /GD 

+LFLAGS_D_WDLL = /NOLOGO /ONERROR:NOEXE /NOD /PACKC:61440 /CO /NOE /ALIGN:16 /MAP:FULL

+LFLAGS_R_WDLL = /NOLOGO /ONERROR:NOEXE /NOD /PACKC:61440 /NOE /ALIGN:16 /MAP:FULL

+LIBS_D_WDLL = oldnames libw commdlg shell olecli olesvr ldllcew

+LIBS_R_WDLL = oldnames libw commdlg shell olecli olesvr ldllcew

+RCFLAGS = /nologo

+RESFLAGS = /nologo

+RUNFLAGS = 

+DEFFILE = ZLIB16.DEF

+OBJS_EXT = 

+LIBS_EXT = 

+!if "$(DEBUG)" == "1"

+CFLAGS = $(CFLAGS_D_WDLL)

+LFLAGS = $(LFLAGS_D_WDLL)

+LIBS = $(LIBS_D_WDLL)

+MAPFILE = nul

+RCDEFINES = $(D_RCDEFINES)

+!else

+CFLAGS = $(CFLAGS_R_WDLL)

+LFLAGS = $(LFLAGS_R_WDLL)

+LIBS = $(LIBS_R_WDLL)

+MAPFILE = nul

+RCDEFINES = $(R_RCDEFINES)

+!endif

+!if [if exist MSVC.BND del MSVC.BND]

+!endif

+SBRS = ADLER32.SBR \

+		COMPRESS.SBR \

+		CRC32.SBR \

+		DEFLATE.SBR \

+		GZIO.SBR \

+		INFFAST.SBR \

+		INFLATE.SBR \

+		TREES.SBR \

+		UNCOMPR.SBR \

+		ZUTIL.SBR \

+		ZIP.SBR \

+		UNZIP.SBR \

+		INFBACK.SBR \

+		IOAPI.SBR \

+		INFTREES.SBR

+

+

+ADLER32_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+COMPRESS_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+CRC32_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\crc32.h

+

+

+DEFLATE_DEP = c:\zlib\deflate.h \

+	c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+GZIO_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+INFFAST_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\inftrees.h \

+	c:\zlib\inflate.h \

+	c:\zlib\inffast.h

+

+

+INFLATE_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\inftrees.h \

+	c:\zlib\inflate.h \

+	c:\zlib\inffast.h \

+	c:\zlib\inffixed.h

+

+

+TREES_DEP = c:\zlib\deflate.h \

+	c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\trees.h

+

+

+UNCOMPR_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+ZUTIL_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h

+

+

+ZLIB16_RCDEP = 

+

+ZIP_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\zip.h \

+	c:\zlib\ioapi.h

+

+

+UNZIP_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\unzip.h \

+	c:\zlib\ioapi.h

+

+

+INFBACK_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\inftrees.h \

+	c:\zlib\inflate.h \

+	c:\zlib\inffast.h \

+	c:\zlib\inffixed.h

+

+

+IOAPI_DEP = c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\ioapi.h

+

+

+INFTREES_DEP = c:\zlib\zutil.h \

+	c:\zlib\zlib.h \

+	c:\zlib\zconf.h \

+	c:\zlib\inftrees.h

+

+

+all:	$(PROJ).DLL $(PROJ).BSC

+

+ADLER32.OBJ:	ADLER32.C $(ADLER32_DEP)

+	$(CC) $(CFLAGS) $(CCREATEPCHFLAG) /c ADLER32.C

+

+COMPRESS.OBJ:	COMPRESS.C $(COMPRESS_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c COMPRESS.C

+

+CRC32.OBJ:	CRC32.C $(CRC32_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c CRC32.C

+

+DEFLATE.OBJ:	DEFLATE.C $(DEFLATE_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c DEFLATE.C

+

+GZIO.OBJ:	GZIO.C $(GZIO_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c GZIO.C

+

+INFFAST.OBJ:	INFFAST.C $(INFFAST_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c INFFAST.C

+

+INFLATE.OBJ:	INFLATE.C $(INFLATE_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c INFLATE.C

+

+TREES.OBJ:	TREES.C $(TREES_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c TREES.C

+

+UNCOMPR.OBJ:	UNCOMPR.C $(UNCOMPR_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c UNCOMPR.C

+

+ZUTIL.OBJ:	ZUTIL.C $(ZUTIL_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c ZUTIL.C

+

+ZLIB16.RES:	ZLIB16.RC $(ZLIB16_RCDEP)

+	$(RC) $(RCFLAGS) $(RCDEFINES) -r ZLIB16.RC

+

+ZIP.OBJ:	ZIP.C $(ZIP_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c ZIP.C

+

+UNZIP.OBJ:	UNZIP.C $(UNZIP_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c UNZIP.C

+

+INFBACK.OBJ:	INFBACK.C $(INFBACK_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c INFBACK.C

+

+IOAPI.OBJ:	IOAPI.C $(IOAPI_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c IOAPI.C

+

+INFTREES.OBJ:	INFTREES.C $(INFTREES_DEP)

+	$(CC) $(CFLAGS) $(CUSEPCHFLAG) /c INFTREES.C

+

+

+$(PROJ).DLL::	ZLIB16.RES

+

+$(PROJ).DLL::	ADLER32.OBJ COMPRESS.OBJ CRC32.OBJ DEFLATE.OBJ GZIO.OBJ INFFAST.OBJ \

+	INFLATE.OBJ TREES.OBJ UNCOMPR.OBJ ZUTIL.OBJ ZIP.OBJ UNZIP.OBJ INFBACK.OBJ IOAPI.OBJ \

+	INFTREES.OBJ $(OBJS_EXT) $(DEFFILE)

+	echo >NUL @<<$(PROJ).CRF

+ADLER32.OBJ +

+COMPRESS.OBJ +

+CRC32.OBJ +

+DEFLATE.OBJ +

+GZIO.OBJ +

+INFFAST.OBJ +

+INFLATE.OBJ +

+TREES.OBJ +

+UNCOMPR.OBJ +

+ZUTIL.OBJ +

+ZIP.OBJ +

+UNZIP.OBJ +

+INFBACK.OBJ +

+IOAPI.OBJ +

+INFTREES.OBJ +

+$(OBJS_EXT)

+$(PROJ).DLL

+$(MAPFILE)

+C:\MSVC\LIB\+

+C:\MSVC\MFC\LIB\+

+E:\PROGRAMFILES\MICROSOFTVISUALSTUDIO.NET\FRAMEWORKSDK\LIB\+

+$(LIBS)

+$(DEFFILE);

+<<

+	link $(LFLAGS) @$(PROJ).CRF

+	$(RC) $(RESFLAGS) ZLIB16.RES $@

+	@copy $(PROJ).CRF MSVC.BND

+	implib /nowep $(PROJ).LIB $(PROJ).DLL

+

+$(PROJ).DLL::	ZLIB16.RES

+	if not exist MSVC.BND 	$(RC) $(RESFLAGS) ZLIB16.RES $@

+

+run: $(PROJ).DLL

+	$(PROJ) $(RUNFLAGS)

+

+

+$(PROJ).BSC: $(SBRS)

+	bscmake @<<

+/o$@ $(SBRS)

+<<

diff --git a/contrib/vstudio/vc15_16/zlib16.rc b/contrib/vstudio/vc15_16/zlib16.rc
new file mode 100644
index 0000000..13d0d66
--- /dev/null
+++ b/contrib/vstudio/vc15_16/zlib16.rc
@@ -0,0 +1,33 @@
+#include <windows.h>

+#include <ver.h>

+

+#define IDR_VERSION1  1

+IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE

+  FILEVERSION	 1,2,0,0

+  PRODUCTVERSION 1,2,0,0

+  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK

+  FILEFLAGS	0

+  FILEOS	VOS_DOS_WINDOWS16

+  FILETYPE	VFT_DLL

+  FILESUBTYPE	0	// not used

+BEGIN

+  BLOCK "StringFileInfo"

+  BEGIN

+    BLOCK "040904E4"

+    //language ID = U.S. English, char set = Windows, Multilingual

+

+    BEGIN

+      VALUE "FileDescription", "zlib data compression library\0"

+      VALUE "FileVersion",	"1.2.0\0"

+      VALUE "InternalName",	"zlib16\0"

+      VALUE "OriginalFilename",	"zlib16.dll\0"

+      VALUE "ProductName",	"ZLib16.DLL\0"

+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"

+      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"

+    END

+  END

+  BLOCK "VarFileInfo"

+  BEGIN

+    VALUE "Translation", 0x0409, 1252

+  END

+END

diff --git a/contrib/vstudio/vc70_32/gvmat32.asm b/contrib/vstudio/vc70_32/gvmat32.asm
new file mode 100644
index 0000000..320348f
--- /dev/null
+++ b/contrib/vstudio/vc70_32/gvmat32.asm
@@ -0,0 +1,905 @@
+;

+; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86

+; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.

+; File written by Gilles Vollant, by modifiying the longest_match

+;  from Jean-loup Gailly in deflate.c

+; It need wmask == 0x7fff

+;     (assembly code is faster with a fixed wmask)

+;

+; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)

+;   I compile with : "ml /coff /Zi /c gvmat32.asm"

+;

+

+;uInt longest_match_7fff(s, cur_match)

+;    deflate_state *s;

+;    IPos cur_match;                             /* current match */

+

+        NbStack         equ     76

+        cur_match       equ     dword ptr[esp+NbStack-0]

+        str_s           equ     dword ptr[esp+NbStack-4]

+; 5 dword on top (ret,ebp,esi,edi,ebx)

+        adrret          equ     dword ptr[esp+NbStack-8]

+        pushebp         equ     dword ptr[esp+NbStack-12]

+        pushedi         equ     dword ptr[esp+NbStack-16]

+        pushesi         equ     dword ptr[esp+NbStack-20]

+        pushebx         equ     dword ptr[esp+NbStack-24]

+

+        chain_length    equ     dword ptr [esp+NbStack-28]

+        limit           equ     dword ptr [esp+NbStack-32]

+        best_len        equ     dword ptr [esp+NbStack-36]

+        window          equ     dword ptr [esp+NbStack-40]

+        prev            equ     dword ptr [esp+NbStack-44]

+        scan_start      equ      word ptr [esp+NbStack-48]

+        wmask           equ     dword ptr [esp+NbStack-52]

+        match_start_ptr equ     dword ptr [esp+NbStack-56]

+        nice_match      equ     dword ptr [esp+NbStack-60]

+        scan            equ     dword ptr [esp+NbStack-64]

+

+        windowlen       equ     dword ptr [esp+NbStack-68]

+        match_start     equ     dword ptr [esp+NbStack-72]

+        strend          equ     dword ptr [esp+NbStack-76]

+        NbStackAdd      equ     (NbStack-24)

+

+    .386p

+

+    name    gvmatch

+    .MODEL  FLAT

+

+

+

+;  all the +4 offsets are due to the addition of pending_buf_size (in zlib

+;  in the deflate_state structure since the asm code was first written

+;  (if you compile with zlib 1.0.4 or older, remove the +4).

+;  Note : these value are good with a 8 bytes boundary pack structure

+    dep_chain_length    equ     70h+4

+    dep_window          equ     2ch+4

+    dep_strstart        equ     60h+4

+    dep_prev_length     equ     6ch+4

+    dep_nice_match      equ     84h+4

+    dep_w_size          equ     20h+4

+    dep_prev            equ     34h+4

+    dep_w_mask          equ     28h+4

+    dep_good_match      equ     80h+4

+    dep_match_start     equ     64h+4

+    dep_lookahead       equ     68h+4

+

+

+_TEXT                   segment

+

+IFDEF NOUNDERLINE

+                        public  longest_match_7fff

+                        public  longest_match_686

+;                        public  match_init

+ELSE

+                        public  _longest_match_7fff

+                        public  _longest_match_686

+;                        public  _match_init

+ENDIF

+

+    MAX_MATCH           equ     258

+    MIN_MATCH           equ     3

+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)

+

+

+

+IFDEF NOUNDERLINE

+;match_init      proc near

+;                ret

+;match_init      endp

+ELSE

+;_match_init     proc near

+;                ret

+;_match_init     endp

+ENDIF

+

+

+IFDEF NOUNDERLINE

+longest_match_7fff   proc near

+ELSE

+_longest_match_7fff  proc near

+ENDIF

+

+        mov     edx,[esp+4]

+

+

+

+        push    ebp

+        push    edi

+        push    esi

+        push    ebx

+

+        sub     esp,NbStackAdd

+

+; initialize or check the variables used in match.asm.

+        mov     ebp,edx

+

+; chain_length = s->max_chain_length

+; if (prev_length>=good_match) chain_length >>= 2

+        mov     edx,[ebp+dep_chain_length]

+        mov     ebx,[ebp+dep_prev_length]

+        cmp     [ebp+dep_good_match],ebx

+        ja      noshr

+        shr     edx,2

+noshr:

+; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop

+        inc     edx

+        mov     edi,[ebp+dep_nice_match]

+        mov     chain_length,edx

+        mov     eax,[ebp+dep_lookahead]

+        cmp     eax,edi

+; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

+        jae     nolookaheadnicematch

+        mov     edi,eax

+nolookaheadnicematch:

+; best_len = s->prev_length

+        mov     best_len,ebx

+

+; window = s->window

+        mov     esi,[ebp+dep_window]

+        mov     ecx,[ebp+dep_strstart]

+        mov     window,esi

+

+        mov     nice_match,edi

+; scan = window + strstart

+        add     esi,ecx

+        mov     scan,esi

+; dx = *window

+        mov     dx,word ptr [esi]

+; bx = *(window+best_len-1)

+        mov     bx,word ptr [esi+ebx-1]

+        add     esi,MAX_MATCH-1

+; scan_start = *scan

+        mov     scan_start,dx

+; strend = scan + MAX_MATCH-1

+        mov     strend,esi

+; bx = scan_end = *(window+best_len-1)

+

+;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?

+;        s->strstart - (IPos)MAX_DIST(s) : NIL;

+

+        mov     esi,[ebp+dep_w_size]

+        sub     esi,MIN_LOOKAHEAD

+; here esi = MAX_DIST(s)

+        sub     ecx,esi

+        ja      nodist

+        xor     ecx,ecx

+nodist:

+        mov     limit,ecx

+

+; prev = s->prev

+        mov     edx,[ebp+dep_prev]

+        mov     prev,edx

+

+;

+        mov     edx,dword ptr [ebp+dep_match_start]

+        mov     bp,scan_start

+        mov     eax,cur_match

+        mov     match_start,edx

+

+        mov     edx,window

+        mov     edi,edx

+        add     edi,best_len

+        mov     esi,prev

+        dec     edi

+; windowlen = window + best_len -1

+        mov     windowlen,edi

+

+        jmp     beginloop2

+        align   4

+

+; here, in the loop

+;       eax = ax = cur_match

+;       ecx = limit

+;        bx = scan_end

+;        bp = scan_start

+;       edi = windowlen (window + best_len -1)

+;       esi = prev

+

+

+;// here; chain_length <=16

+normalbeg0add16:

+        add     chain_length,16

+        jz      exitloop

+normalbeg0:

+        cmp     word ptr[edi+eax],bx

+        je      normalbeg2noroll

+rcontlabnoroll:

+; cur_match = prev[cur_match & wmask]

+        and     eax,7fffh

+        mov     ax,word ptr[esi+eax*2]

+; if cur_match > limit, go to exitloop

+        cmp     ecx,eax

+        jnb     exitloop

+; if --chain_length != 0, go to exitloop

+        dec     chain_length

+        jnz     normalbeg0

+        jmp     exitloop

+

+normalbeg2noroll:

+; if (scan_start==*(cur_match+window)) goto normalbeg2

+        cmp     bp,word ptr[edx+eax]

+        jne     rcontlabnoroll

+        jmp     normalbeg2

+

+contloop3:

+        mov     edi,windowlen

+

+; cur_match = prev[cur_match & wmask]

+        and     eax,7fffh

+        mov     ax,word ptr[esi+eax*2]

+; if cur_match > limit, go to exitloop

+        cmp     ecx,eax

+jnbexitloopshort1:

+        jnb     exitloop

+; if --chain_length != 0, go to exitloop

+

+

+; begin the main loop

+beginloop2:

+        sub     chain_length,16+1

+; if chain_length <=16, don't use the unrolled loop

+        jna     normalbeg0add16

+

+do16:

+        cmp     word ptr[edi+eax],bx

+        je      normalbeg2dc0

+

+maccn   MACRO   lab

+        and     eax,7fffh

+        mov     ax,word ptr[esi+eax*2]

+        cmp     ecx,eax

+        jnb     exitloop

+        cmp     word ptr[edi+eax],bx

+        je      lab

+        ENDM

+

+rcontloop0:

+        maccn   normalbeg2dc1

+

+rcontloop1:

+        maccn   normalbeg2dc2

+

+rcontloop2:

+        maccn   normalbeg2dc3

+

+rcontloop3:

+        maccn   normalbeg2dc4

+

+rcontloop4:

+        maccn   normalbeg2dc5

+

+rcontloop5:

+        maccn   normalbeg2dc6

+

+rcontloop6:

+        maccn   normalbeg2dc7

+

+rcontloop7:

+        maccn   normalbeg2dc8

+

+rcontloop8:

+        maccn   normalbeg2dc9

+

+rcontloop9:

+        maccn   normalbeg2dc10

+

+rcontloop10:

+        maccn   short normalbeg2dc11

+

+rcontloop11:

+        maccn   short normalbeg2dc12

+

+rcontloop12:

+        maccn   short normalbeg2dc13

+

+rcontloop13:

+        maccn   short normalbeg2dc14

+

+rcontloop14:

+        maccn   short normalbeg2dc15

+

+rcontloop15:

+        and     eax,7fffh

+        mov     ax,word ptr[esi+eax*2]

+        cmp     ecx,eax

+        jnb     exitloop

+

+        sub     chain_length,16

+        ja      do16

+        jmp     normalbeg0add16

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+normbeg MACRO   rcontlab,valsub

+; if we are here, we know that *(match+best_len-1) == scan_end

+        cmp     bp,word ptr[edx+eax]

+; if (match != scan_start) goto rcontlab

+        jne     rcontlab

+; calculate the good chain_length, and we'll compare scan and match string

+        add     chain_length,16-valsub

+        jmp     iseq

+        ENDM

+

+

+normalbeg2dc11:

+        normbeg rcontloop11,11

+

+normalbeg2dc12:

+        normbeg short rcontloop12,12

+

+normalbeg2dc13:

+        normbeg short rcontloop13,13

+

+normalbeg2dc14:

+        normbeg short rcontloop14,14

+

+normalbeg2dc15:

+        normbeg short rcontloop15,15

+

+normalbeg2dc10:

+        normbeg rcontloop10,10

+

+normalbeg2dc9:

+        normbeg rcontloop9,9

+

+normalbeg2dc8:

+        normbeg rcontloop8,8

+

+normalbeg2dc7:

+        normbeg rcontloop7,7

+

+normalbeg2dc6:

+        normbeg rcontloop6,6

+

+normalbeg2dc5:

+        normbeg rcontloop5,5

+

+normalbeg2dc4:

+        normbeg rcontloop4,4

+

+normalbeg2dc3:

+        normbeg rcontloop3,3

+

+normalbeg2dc2:

+        normbeg rcontloop2,2

+

+normalbeg2dc1:

+        normbeg rcontloop1,1

+

+normalbeg2dc0:

+        normbeg rcontloop0,0

+

+

+; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end

+

+normalbeg2:

+        mov     edi,window

+

+        cmp     bp,word ptr[edi+eax]

+        jne     contloop3                   ; if *(ushf*)match != scan_start, continue

+

+iseq:

+; if we are here, we know that *(match+best_len-1) == scan_end

+; and (match == scan_start)

+

+        mov     edi,edx

+        mov     esi,scan                    ; esi = scan

+        add     edi,eax                     ; edi = window + cur_match = match

+

+        mov     edx,[esi+3]                 ; compare manually dword at match+3

+        xor     edx,[edi+3]                 ; and scan +3

+

+        jz      begincompare                ; if equal, go to long compare

+

+; we will determine the unmatch byte and calculate len (in esi)

+        or      dl,dl

+        je      eq1rr

+        mov     esi,3

+        jmp     trfinval

+eq1rr:

+        or      dx,dx

+        je      eq1

+

+        mov     esi,4

+        jmp     trfinval

+eq1:

+        and     edx,0ffffffh

+        jz      eq11

+        mov     esi,5

+        jmp     trfinval

+eq11:

+        mov     esi,6

+        jmp     trfinval

+

+begincompare:

+        ; here we now scan and match begin same

+        add     edi,6

+        add     esi,6

+        mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes

+        repe    cmpsd                       ; loop until mismatch

+

+        je      trfin                       ; go to trfin if not unmatch

+; we determine the unmatch byte

+        sub     esi,4

+        mov     edx,[edi-4]

+        xor     edx,[esi]

+

+        or      dl,dl

+        jnz     trfin

+        inc     esi

+

+        or      dx,dx

+        jnz     trfin

+        inc     esi

+

+        and     edx,0ffffffh

+        jnz     trfin

+        inc     esi

+

+trfin:

+        sub     esi,scan          ; esi = len

+trfinval:

+; here we have finised compare, and esi contain len of equal string

+        cmp     esi,best_len        ; if len > best_len, go newbestlen

+        ja      short newbestlen

+; now we restore edx, ecx and esi, for the big loop

+        mov     esi,prev

+        mov     ecx,limit

+        mov     edx,window

+        jmp     contloop3

+

+newbestlen:

+        mov     best_len,esi        ; len become best_len

+

+        mov     match_start,eax     ; save new position as match_start

+        cmp     esi,nice_match      ; if best_len >= nice_match, exit

+        jae     exitloop

+        mov     ecx,scan

+        mov     edx,window          ; restore edx=window

+        add     ecx,esi

+        add     esi,edx

+

+        dec     esi

+        mov     windowlen,esi       ; windowlen = window + best_len-1

+        mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end

+

+; now we restore ecx and esi, for the big loop :

+        mov     esi,prev

+        mov     ecx,limit

+        jmp     contloop3

+

+exitloop:

+; exit : s->match_start=match_start

+        mov     ebx,match_start

+        mov     ebp,str_s

+        mov     ecx,best_len

+        mov     dword ptr [ebp+dep_match_start],ebx        

+        mov     eax,dword ptr [ebp+dep_lookahead]

+        cmp     ecx,eax

+        ja      minexlo

+        mov     eax,ecx

+minexlo:

+; return min(best_len,s->lookahead)

+        

+; restore stack and register ebx,esi,edi,ebp

+        add     esp,NbStackAdd

+

+        pop     ebx

+        pop     esi

+        pop     edi

+        pop     ebp

+        ret

+InfoAuthor:

+; please don't remove this string !

+; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!

+        db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah

+

+

+

+IFDEF NOUNDERLINE

+longest_match_7fff   endp

+ELSE

+_longest_match_7fff  endp

+ENDIF

+

+

+IFDEF NOUNDERLINE

+cpudetect32     proc near

+ELSE

+_cpudetect32    proc near

+ENDIF

+

+	push	ebx

+

+	pushfd                  ; push original EFLAGS

+	pop     eax             ; get original EFLAGS

+	mov     ecx, eax        ; save original EFLAGS

+	xor     eax, 40000h     ; flip AC bit in EFLAGS

+	push    eax             ; save new EFLAGS value on stack

+	popfd                   ; replace current EFLAGS value

+	pushfd                  ; get new EFLAGS

+	pop     eax             ; store new EFLAGS in EAX

+	xor     eax, ecx        ; canÂ’t toggle AC bit, processor=80386

+	jz      end_cpu_is_386  ; jump if 80386 processor

+	push    ecx

+	popfd                   ; restore AC bit in EFLAGS first

+

+	pushfd

+	pushfd

+	pop     ecx

+			

+	mov     eax, ecx        ; get original EFLAGS

+	xor     eax, 200000h    ; flip ID bit in EFLAGS

+	push    eax             ; save new EFLAGS value on stack

+	popfd                   ; replace current EFLAGS value

+	pushfd                  ; get new EFLAGS

+	pop		eax	            ; store new EFLAGS in EAX

+	popfd                   ; restore original EFLAGS

+	xor		eax, ecx        ; canÂ’t toggle ID bit,

+	je		is_old_486		; processor=old

+

+	mov     eax,1

+	db      0fh,0a2h        ;CPUID   

+

+exitcpudetect:

+	pop	ebx

+	ret

+

+end_cpu_is_386:

+	mov     eax,0300h

+	jmp     exitcpudetect

+

+is_old_486:

+	mov     eax,0400h

+	jmp     exitcpudetect

+

+IFDEF NOUNDERLINE

+cpudetect32     endp

+ELSE

+_cpudetect32    endp

+ENDIF

+

+

+

+

+MAX_MATCH       equ     258

+MIN_MATCH       equ     3

+MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)

+MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)

+

+

+;;; stack frame offsets

+

+chainlenwmask	equ  esp + 0	; high word: current chain len

+					; low word: s->wmask

+window		equ  esp + 4	; local copy of s->window

+windowbestlen	equ  esp + 8	; s->window + bestlen

+scanstart	equ  esp + 16	; first two bytes of string

+scanend		equ  esp + 12	; last two bytes of string

+scanalign	equ  esp + 20	; dword-misalignment of string

+nicematch	equ  esp + 24	; a good enough match size

+bestlen		equ  esp + 28	; size of best match so far

+scan		equ  esp + 32	; ptr to string wanting match

+

+LocalVarsSize	equ 36

+;	saved ebx	byte esp + 36

+;	saved edi	byte esp + 40

+;	saved esi	byte esp + 44

+;	saved ebp	byte esp + 48

+;	return address	byte esp + 52

+deflatestate	equ  esp + 56	; the function arguments

+curmatch	equ  esp + 60

+

+;;; Offsets for fields in the deflate_state structure. These numbers

+;;; are calculated from the definition of deflate_state, with the

+;;; assumption that the compiler will dword-align the fields. (Thus,

+;;; changing the definition of deflate_state could easily cause this

+;;; program to crash horribly, without so much as a warning at

+;;; compile time. Sigh.)

+

+dsWSize		equ 36

+dsWMask		equ 44

+dsWindow	equ 48

+dsPrev		equ 56

+dsMatchLen	equ 88

+dsPrevMatch	equ 92

+dsStrStart	equ 100

+dsMatchStart	equ 104

+dsLookahead	equ 108

+dsPrevLen	equ 112

+dsMaxChainLen	equ 116

+dsGoodMatch	equ 132

+dsNiceMatch	equ 136

+

+

+;;; match.asm -- Pentium-Pro-optimized version of longest_match()

+;;; Written for zlib 1.1.2

+;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>

+;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html

+;;;

+;;; This is free software; you can redistribute it and/or modify it

+;;; under the terms of the GNU General Public License.

+

+;GLOBAL	_longest_match, _match_init

+

+

+;SECTION	.text

+

+;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)

+

+;_longest_match:

+IFDEF NOUNDERLINE

+longest_match_686   proc near

+ELSE

+_longest_match_686  proc near

+ENDIF

+

+

+;;; Save registers that the compiler may be using, and adjust esp to

+;;; make room for our stack frame.

+

+		push	ebp

+		push	edi

+		push	esi

+		push	ebx

+		sub	esp, LocalVarsSize

+

+;;; Retrieve the function arguments. ecx will hold cur_match

+;;; throughout the entire function. edx will hold the pointer to the

+;;; deflate_state structure during the function's setup (before

+;;; entering the main loop.

+

+		mov	edx, [deflatestate]

+		mov	ecx, [curmatch]

+

+;;; uInt wmask = s->w_mask;

+;;; unsigned chain_length = s->max_chain_length;

+;;; if (s->prev_length >= s->good_match) {

+;;;     chain_length >>= 2;

+;;; }

+

+		mov	eax, [edx + dsPrevLen]

+		mov	ebx, [edx + dsGoodMatch]

+		cmp	eax, ebx

+		mov	eax, [edx + dsWMask]

+		mov	ebx, [edx + dsMaxChainLen]

+		jl	LastMatchGood

+		shr	ebx, 2

+LastMatchGood:

+

+;;; chainlen is decremented once beforehand so that the function can

+;;; use the sign flag instead of the zero flag for the exit test.

+;;; It is then shifted into the high word, to make room for the wmask

+;;; value, which it will always accompany.

+

+		dec	ebx

+		shl	ebx, 16

+		or	ebx, eax

+		mov	[chainlenwmask], ebx

+

+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;

+

+		mov	eax, [edx + dsNiceMatch]

+		mov	ebx, [edx + dsLookahead]

+		cmp	ebx, eax

+		jl	LookaheadLess

+		mov	ebx, eax

+LookaheadLess:	mov	[nicematch], ebx

+

+;;; register Bytef *scan = s->window + s->strstart;

+

+		mov	esi, [edx + dsWindow]

+		mov	[window], esi

+		mov	ebp, [edx + dsStrStart]

+		lea	edi, [esi + ebp]

+		mov	[scan], edi

+

+;;; Determine how many bytes the scan ptr is off from being

+;;; dword-aligned.

+

+		mov	eax, edi

+		neg	eax

+		and	eax, 3

+		mov	[scanalign], eax

+

+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?

+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;

+

+		mov	eax, [edx + dsWSize]

+		sub	eax, MIN_LOOKAHEAD

+		sub	ebp, eax

+		jg	LimitPositive

+		xor	ebp, ebp

+LimitPositive:

+

+;;; int best_len = s->prev_length;

+

+		mov	eax, [edx + dsPrevLen]

+		mov	[bestlen], eax

+

+;;; Store the sum of s->window + best_len in esi locally, and in esi.

+

+		add	esi, eax

+		mov	[windowbestlen], esi

+

+;;; register ush scan_start = *(ushf*)scan;

+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);

+;;; Posf *prev = s->prev;

+

+		movzx	ebx, word ptr [edi]

+		mov	[scanstart], ebx

+		movzx	ebx, word ptr [edi + eax - 1]

+		mov	[scanend], ebx

+		mov	edi, [edx + dsPrev]

+

+;;; Jump into the main loop.

+

+		mov	edx, [chainlenwmask]

+		jmp	short LoopEntry

+

+align 4

+

+;;; do {

+;;;     match = s->window + cur_match;

+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||

+;;;         *(ushf*)match != scan_start) continue;

+;;;     [...]

+;;; } while ((cur_match = prev[cur_match & wmask]) > limit

+;;;          && --chain_length != 0);

+;;;

+;;; Here is the inner loop of the function. The function will spend the

+;;; majority of its time in this loop, and majority of that time will

+;;; be spent in the first ten instructions.

+;;;

+;;; Within this loop:

+;;; ebx = scanend

+;;; ecx = curmatch

+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)

+;;; esi = windowbestlen - i.e., (window + bestlen)

+;;; edi = prev

+;;; ebp = limit

+

+LookupLoop:

+		and	ecx, edx

+		movzx	ecx, word ptr [edi + ecx*2]

+		cmp	ecx, ebp

+		jbe	LeaveNow

+		sub	edx, 00010000h

+		js	LeaveNow

+LoopEntry:	movzx	eax, word ptr [esi + ecx - 1]

+		cmp	eax, ebx

+		jnz	LookupLoop

+		mov	eax, [window]

+		movzx	eax, word ptr [eax + ecx]

+		cmp	eax, [scanstart]

+		jnz	LookupLoop

+

+;;; Store the current value of chainlen.

+

+		mov	[chainlenwmask], edx

+

+;;; Point edi to the string under scrutiny, and esi to the string we

+;;; are hoping to match it up with. In actuality, esi and edi are

+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is

+;;; initialized to -(MAX_MATCH_8 - scanalign).

+

+		mov	esi, [window]

+		mov	edi, [scan]

+		add	esi, ecx

+		mov	eax, [scanalign]

+		mov	edx, 0fffffef8h; -(MAX_MATCH_8)

+		lea	edi, [edi + eax + 0108h] ;MAX_MATCH_8]

+		lea	esi, [esi + eax + 0108h] ;MAX_MATCH_8]

+

+;;; Test the strings for equality, 8 bytes at a time. At the end,

+;;; adjust edx so that it is offset to the exact byte that mismatched.

+;;;

+;;; We already know at this point that the first three bytes of the

+;;; strings match each other, and they can be safely passed over before

+;;; starting the compare loop. So what this code does is skip over 0-3

+;;; bytes, as much as necessary in order to dword-align the edi

+;;; pointer. (esi will still be misaligned three times out of four.)

+;;;

+;;; It should be confessed that this loop usually does not represent

+;;; much of the total running time. Replacing it with a more

+;;; straightforward "rep cmpsb" would not drastically degrade

+;;; performance.

+

+LoopCmps:

+		mov	eax, [esi + edx]

+		xor	eax, [edi + edx]

+		jnz	LeaveLoopCmps

+		mov	eax, [esi + edx + 4]

+		xor	eax, [edi + edx + 4]

+		jnz	LeaveLoopCmps4

+		add	edx, 8

+		jnz	LoopCmps

+		jmp	short LenMaximum

+LeaveLoopCmps4:	add	edx, 4

+LeaveLoopCmps:	test	eax, 0000FFFFh

+		jnz	LenLower

+		add	edx,  2

+		shr	eax, 16

+LenLower:	sub	al, 1

+		adc	edx, 0

+

+;;; Calculate the length of the match. If it is longer than MAX_MATCH,

+;;; then automatically accept it as the best possible match and leave.

+

+		lea	eax, [edi + edx]

+		mov	edi, [scan]

+		sub	eax, edi

+		cmp	eax, MAX_MATCH

+		jge	LenMaximum

+

+;;; If the length of the match is not longer than the best match we

+;;; have so far, then forget it and return to the lookup loop.

+

+		mov	edx, [deflatestate]

+		mov	ebx, [bestlen]

+		cmp	eax, ebx

+		jg	LongerMatch

+		mov	esi, [windowbestlen]

+		mov	edi, [edx + dsPrev]

+		mov	ebx, [scanend]

+		mov	edx, [chainlenwmask]

+		jmp	LookupLoop

+

+;;;         s->match_start = cur_match;

+;;;         best_len = len;

+;;;         if (len >= nice_match) break;

+;;;         scan_end = *(ushf*)(scan+best_len-1);

+

+LongerMatch:	mov	ebx, [nicematch]

+		mov	[bestlen], eax

+		mov	[edx + dsMatchStart], ecx

+		cmp	eax, ebx

+		jge	LeaveNow

+		mov	esi, [window]

+		add	esi, eax

+		mov	[windowbestlen], esi

+		movzx	ebx, word ptr [edi + eax - 1]

+		mov	edi, [edx + dsPrev]

+		mov	[scanend], ebx

+		mov	edx, [chainlenwmask]

+		jmp	LookupLoop

+

+;;; Accept the current string, with the maximum possible length.

+

+LenMaximum:	mov	edx, [deflatestate]

+		mov	dword ptr [bestlen], MAX_MATCH

+		mov	[edx + dsMatchStart], ecx

+

+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;

+;;; return s->lookahead;

+

+LeaveNow:

+		mov	edx, [deflatestate]

+		mov	ebx, [bestlen]

+		mov	eax, [edx + dsLookahead]

+		cmp	ebx, eax

+		jg	LookaheadRet

+		mov	eax, ebx

+LookaheadRet:

+

+;;; Restore the stack and return from whence we came.

+

+		add	esp, LocalVarsSize

+		pop	ebx

+		pop	esi

+		pop	edi

+		pop	ebp

+

+		ret

+; please don't remove this string !

+; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!

+        db     0dh,0ah,"asm686 with masm, code optimised assembly code from Brian Raiter, written 1998",0dh,0ah

+

+IFDEF NOUNDERLINE

+longest_match_686   endp

+ELSE

+_longest_match_686  endp

+ENDIF

+

+_TEXT   ends

+end

diff --git a/contrib/vstudio/vc70_32/gvmat32.obj b/contrib/vstudio/vc70_32/gvmat32.obj
new file mode 100644
index 0000000..5b2f856
--- /dev/null
+++ b/contrib/vstudio/vc70_32/gvmat32.obj
Binary files differ
diff --git a/contrib/vstudio/vc70_32/gvmat32c.c b/contrib/vstudio/vc70_32/gvmat32c.c
new file mode 100644
index 0000000..38be10b
--- /dev/null
+++ b/contrib/vstudio/vc70_32/gvmat32c.c
@@ -0,0 +1,209 @@
+/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86

+ * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.

+ * File written by Gilles Vollant, by modifiying the longest_match

+ *  from Jean-loup Gailly in deflate.c

+ *  it prepare all parameters and call the assembly longest_match_gvasm

+ *  longest_match execute standard C code is wmask != 0x7fff

+ *     (assembly code is faster with a fixed wmask)

+ *

+ */

+

+#include "deflate.h"

+

+#undef FAR

+//#include <windows.h>

+

+#ifdef ASMV

+#define NIL 0

+

+#define UNALIGNED_OK

+

+

+/* if your C compiler don't add underline before function name,

+        define ADD_UNDERLINE_ASMFUNC */

+#ifdef ADD_UNDERLINE_ASMFUNC

+#define longest_match_7fff _longest_match_7fff

+#define longest_match_686  _longest_match_686

+#define cpudetect32        _cpudetect32

+#endif

+

+

+

+void match_init()

+{

+}

+

+unsigned long cpudetect32();

+

+uInt longest_match_c(

+    deflate_state *s,

+    IPos cur_match);                             /* current match */

+

+

+uInt longest_match_7fff(

+    deflate_state *s,

+    IPos cur_match);                             /* current match */

+

+uInt longest_match_686(

+    deflate_state *s,

+    IPos cur_match);                             /* current match */

+

+uInt longest_match(

+    deflate_state *s,

+    IPos cur_match)                             /* current match */

+{

+    static uInt iIsPPro=2;

+

+    if ((s->w_mask == 0x7fff) && (iIsPPro==0))

+        return longest_match_7fff(s,cur_match);

+

+    if (iIsPPro==1)

+        return longest_match_686(s,cur_match);

+

+    if (iIsPPro==2)

+        iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;

+

+    return longest_match_c(s,cur_match);

+}

+

+

+

+uInt longest_match_c(s, cur_match)

+    deflate_state *s;

+    IPos cur_match;                             /* current match */

+{

+    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;

+

+#ifdef UNALIGNED_OK

+    /* 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 ush scan_start = *(ushf*)scan;

+    register ush scan_end   = *(ushf*)(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];

+#endif

+

+    /* 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:

+         */

+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)

+        /* This code assumes sizeof(unsigned short) == 2. Do not use

+         * UNALIGNED_OK if your compiler uses a different size.

+         */

+        if (*(ushf*)(match+best_len-1) != scan_end ||

+            *(ushf*)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 (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&

+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&

+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&

+                 *(ushf*)(scan+=2) == *(ushf*)(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;

+

+#endif /* UNALIGNED_OK */

+

+        if (len > best_len) {

+            s->match_start = cur_match;

+            best_len = len;

+            if (len >= nice_match) break;

+#ifdef UNALIGNED_OK

+            scan_end = *(ushf*)(scan+best_len-1);

+#else

+            scan_end1  = scan[best_len-1];

+            scan_end   = scan[best_len];

+#endif

+        }

+    } while ((cur_match = prev[cur_match & wmask]) > limit

+             && --chain_length != 0);

+

+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;

+    return s->lookahead;

+}

+

+#endif /* ASMV */

diff --git a/contrib/vstudio/vc70_32/inffastAsm.asm b/contrib/vstudio/vc70_32/inffastAsm.asm
new file mode 100644
index 0000000..f4b6a56
--- /dev/null
+++ b/contrib/vstudio/vc70_32/inffastAsm.asm
@@ -0,0 +1,1020 @@
+; 75 "inffast.S"

+;FILE "inffast.S"

+

+;;;GLOBAL _inflate_fast

+

+;;;SECTION .text

+

+

+

+    .586p

+    .mmx

+

+    name    inflate_fast_x86

+    .MODEL  FLAT

+

+_DATA                   segment

+inflate_fast_use_mmx: 

+dd    1

+

+

+_TEXT                   segment

+PUBLIC _inflate_fast

+

+ALIGN 4

+_inflate_fast: 

+        jmp inflate_fast_entry

+

+

+

+ALIGN 4

+        db     'Fast decoding Code from Chris Anderson'

+        db      0

+

+ALIGN 4

+invalid_literal_length_code_msg: 

+        db      'invalid literal/length code'

+        db      0

+

+ALIGN 4

+invalid_distance_code_msg: 

+        db      'invalid distance code'

+        db      0

+

+ALIGN 4

+invalid_distance_too_far_msg: 

+        db      'invalid distance too far back'

+        db      0

+

+

+ALIGN 4

+inflate_fast_mask: 

+dd    0

+dd    1

+dd    3

+dd    7

+dd    15

+dd    31

+dd    63

+dd    127

+dd    255

+dd    511

+dd    1023

+dd    2047

+dd    4095

+dd    8191

+dd    16383

+dd    32767

+dd    65535

+dd    131071

+dd    262143

+dd    524287

+dd    1048575

+dd    2097151

+dd    4194303

+dd    8388607

+dd    16777215

+dd    33554431

+dd    67108863

+dd    134217727

+dd    268435455

+dd    536870911

+dd    1073741823

+dd    2147483647

+dd    4294967295

+

+

+;;SECTION .text

+; 205 "inffast.S"

+;GLOBAL inflate_fast_use_mmx

+

+;SECTION .data

+

+

+; GLOBAL inflate_fast_use_mmx:object

+;.size inflate_fast_use_mmx, 4

+; 226 "inffast.S"

+;SECTION .text

+

+ALIGN 4 

+inflate_fast_entry: 

+        push  edi

+        push  esi

+        push  ebp

+        push  ebx

+        pushfd

+        sub  esp,64

+        cld

+

+

+

+

+        mov  esi, [esp+88]

+        mov  edi, [esi+28]

+

+

+

+

+

+

+

+        mov  edx, [esi+4]

+        mov  eax, [esi+0]

+

+        add  edx,eax

+        sub  edx,11

+

+        mov  [esp+44],eax

+        mov  [esp+20],edx

+

+        mov  ebp, [esp+92]

+        mov  ecx, [esi+16]

+        mov  ebx, [esi+12]

+

+        sub  ebp,ecx

+        neg  ebp

+        add  ebp,ebx

+

+        sub  ecx,257

+        add  ecx,ebx

+

+        mov  [esp+60],ebx

+        mov  [esp+40],ebp

+        mov  [esp+16],ecx

+; 285 "inffast.S"

+        mov  eax, [edi+64]

+        mov  ecx, [edi+68]

+

+        mov  [esp+8],eax

+        mov  [esp+12],ecx

+

+        mov  eax,1

+        mov  ecx, [edi+72]

+        shl  eax,cl

+        dec  eax

+        mov  [esp+0],eax

+

+        mov  eax,1

+        mov  ecx, [edi+76]

+        shl  eax,cl

+        dec  eax

+        mov  [esp+4],eax

+

+        mov  eax, [edi+32]

+        mov  ecx, [edi+36]

+        mov  edx, [edi+40]

+

+        mov  [esp+52],eax

+        mov  [esp+48],ecx

+        mov  [esp+56],edx

+

+        mov  ebp, [edi+44]

+        mov  ebx, [edi+48]

+; 321 "inffast.S"

+        mov  esi, [esp+44]

+        mov  ecx, [esp+20]

+        cmp  ecx,esi

+        ja   L_align_long

+

+        add  ecx,11

+        sub  ecx,esi

+        mov  eax,12

+        sub  eax,ecx

+        lea  edi, [esp+28]

+        rep movsb

+        mov  ecx,eax

+        xor  eax,eax

+        rep stosb

+        lea  esi, [esp+28]

+        mov  [esp+20],esi

+        jmp  L_is_aligned

+

+

+L_align_long: 

+        test  esi,3

+        jz   L_is_aligned

+        xor  eax,eax

+        mov  al, [esi]

+        inc  esi

+        mov  ecx,ebx

+        add  ebx,8

+        shl  eax,cl

+        or  ebp,eax

+        jmp L_align_long

+

+L_is_aligned: 

+        mov  edi, [esp+60]

+; 366 "inffast.S"

+L_check_mmx: 

+        cmp  dword ptr [inflate_fast_use_mmx],2

+        je   L_init_mmx

+        ja   L_do_loop

+

+        push  eax

+        push  ebx

+        push  ecx

+        push  edx

+        pushfd

+        mov  eax, [esp]

+        xor  dword ptr [esp],0200000h

+

+

+

+

+        popfd

+        pushfd

+        pop  edx

+        xor  edx,eax

+        jz   L_dont_use_mmx

+        xor  eax,eax

+        cpuid

+        cmp  ebx,0756e6547h

+        jne  L_dont_use_mmx

+        cmp  ecx,06c65746eh

+        jne  L_dont_use_mmx

+        cmp  edx,049656e69h

+        jne  L_dont_use_mmx

+        mov  eax,1

+        cpuid

+        shr  eax,8

+        and  eax,15

+        cmp  eax,6

+        jne  L_dont_use_mmx

+        test  edx,0800000h

+        jnz  L_use_mmx

+        jmp  L_dont_use_mmx

+L_use_mmx: 

+        mov  dword ptr [inflate_fast_use_mmx],2

+        jmp  L_check_mmx_pop

+L_dont_use_mmx: 

+        mov  dword ptr [inflate_fast_use_mmx],3

+L_check_mmx_pop: 

+        pop  edx

+        pop  ecx

+        pop  ebx

+        pop  eax

+        jmp  L_check_mmx

+; 426 "inffast.S"

+ALIGN 4

+L_do_loop: 

+; 437 "inffast.S"

+        cmp  bl,15

+        ja   L_get_length_code

+

+        xor  eax,eax

+        lodsw

+        mov  cl,bl

+        add  bl,16

+        shl  eax,cl

+        or  ebp,eax

+

+L_get_length_code: 

+        mov  edx, [esp+0]

+        mov  ecx, [esp+8]

+        and  edx,ebp

+        mov  eax, [ecx+edx*4]

+

+L_dolen: 

+

+

+

+

+

+

+        mov  cl,ah

+        sub  bl,ah

+        shr  ebp,cl

+

+

+

+

+

+

+        test  al,al

+        jnz   L_test_for_length_base

+

+        shr  eax,16

+        stosb

+

+L_while_test: 

+

+

+        cmp  [esp+16],edi

+        jbe  L_break_loop

+

+        cmp  [esp+20],esi

+        ja   L_do_loop

+        jmp  L_break_loop

+

+L_test_for_length_base: 

+; 502 "inffast.S"

+        mov  edx,eax

+        shr  edx,16

+        mov  cl,al

+

+        test  al,16

+        jz   L_test_for_second_level_length

+        and  cl,15

+        jz   L_save_len

+        cmp  bl,cl

+        jae  L_add_bits_to_len

+

+        mov  ch,cl

+        xor  eax,eax

+        lodsw

+        mov  cl,bl

+        add  bl,16

+        shl  eax,cl

+        or  ebp,eax

+        mov  cl,ch

+

+L_add_bits_to_len: 

+        mov  eax,1

+        shl  eax,cl

+        dec  eax

+        sub  bl,cl

+        and  eax,ebp

+        shr  ebp,cl

+        add  edx,eax

+

+L_save_len: 

+        mov  [esp+24],edx

+

+

+L_decode_distance: 

+; 549 "inffast.S"

+        cmp  bl,15

+        ja   L_get_distance_code

+

+        xor  eax,eax

+        lodsw

+        mov  cl,bl

+        add  bl,16

+        shl  eax,cl

+        or  ebp,eax

+

+L_get_distance_code: 

+        mov  edx, [esp+4]

+        mov  ecx, [esp+12]

+        and  edx,ebp

+        mov  eax, [ecx+edx*4]

+

+

+L_dodist: 

+        mov  edx,eax

+        shr  edx,16

+        mov  cl,ah

+        sub  bl,ah

+        shr  ebp,cl

+; 584 "inffast.S"

+        mov  cl,al

+

+        test  al,16

+        jz  L_test_for_second_level_dist

+        and  cl,15

+        jz  L_check_dist_one

+        cmp  bl,cl

+        jae  L_add_bits_to_dist

+

+        mov  ch,cl

+        xor  eax,eax

+        lodsw

+        mov  cl,bl

+        add  bl,16

+        shl  eax,cl

+        or  ebp,eax

+        mov  cl,ch

+

+L_add_bits_to_dist: 

+        mov  eax,1

+        shl  eax,cl

+        dec  eax

+        sub  bl,cl

+        and  eax,ebp

+        shr  ebp,cl

+        add  edx,eax

+        jmp  L_check_window

+

+L_check_window: 

+; 625 "inffast.S"

+        mov  [esp+44],esi

+        mov  eax,edi

+        sub  eax, [esp+40]

+

+        cmp  eax,edx

+        jb   L_clip_window

+

+        mov  ecx, [esp+24]

+        mov  esi,edi

+        sub  esi,edx

+

+        sub  ecx,3

+        mov  al, [esi]

+        mov  [edi],al

+        mov  al, [esi+1]

+        mov  dl, [esi+2]

+        add  esi,3

+        mov  [edi+1],al

+        mov  [edi+2],dl

+        add  edi,3

+        rep movsb

+

+        mov  esi, [esp+44]

+        jmp  L_while_test

+

+ALIGN 4

+L_check_dist_one: 

+        cmp  edx,1

+        jne  L_check_window

+        cmp  [esp+40],edi

+        je  L_check_window

+

+        dec  edi

+        mov  ecx, [esp+24]

+        mov  al, [edi]

+        sub  ecx,3

+

+        mov  [edi+1],al

+        mov  [edi+2],al

+        mov  [edi+3],al

+        add  edi,4

+        rep stosb

+

+        jmp  L_while_test

+

+ALIGN 4

+L_test_for_second_level_length: 

+

+

+

+

+        test  al,64

+        jnz   L_test_for_end_of_block

+

+        mov  eax,1

+        shl  eax,cl

+        dec  eax

+        and  eax,ebp

+        add  eax,edx

+        mov  edx, [esp+8]

+        mov  eax, [edx+eax*4]

+        jmp  L_dolen

+

+ALIGN 4

+L_test_for_second_level_dist: 

+

+

+

+

+        test  al,64

+        jnz   L_invalid_distance_code

+

+        mov  eax,1

+        shl  eax,cl

+        dec  eax

+        and  eax,ebp

+        add  eax,edx

+        mov  edx, [esp+12]

+        mov  eax, [edx+eax*4]

+        jmp  L_dodist

+

+ALIGN 4 

+L_clip_window: 

+; 721 "inffast.S"

+        mov  ecx,eax

+        mov  eax, [esp+52]

+        neg  ecx

+        mov  esi, [esp+56]

+

+        cmp  eax,edx

+        jb   L_invalid_distance_too_far

+

+        add  ecx,edx

+        cmp  dword ptr [esp+48],0

+        jne  L_wrap_around_window

+

+        sub  eax,ecx

+        add  esi,eax

+; 749 "inffast.S"

+        mov  eax, [esp+24]

+        cmp  eax,ecx

+        jbe  L_do_copy1

+

+        sub  eax,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,edx

+        jmp  L_do_copy1

+

+        cmp  eax,ecx

+        jbe  L_do_copy1

+

+        sub  eax,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,edx

+        jmp  L_do_copy1

+

+L_wrap_around_window: 

+; 793 "inffast.S"

+        mov  eax, [esp+48]

+        cmp  ecx,eax

+        jbe  L_contiguous_in_window

+

+        add  esi, [esp+52]

+        add  esi,eax

+        sub  esi,ecx

+        sub  ecx,eax

+

+

+        mov  eax, [esp+24]

+        cmp  eax,ecx

+        jbe  L_do_copy1

+

+        sub  eax,ecx

+        rep movsb

+        mov  esi, [esp+56]

+        mov  ecx, [esp+48]

+        cmp  eax,ecx

+        jbe  L_do_copy1

+

+        sub  eax,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,edx

+        jmp  L_do_copy1

+

+L_contiguous_in_window: 

+; 836 "inffast.S"

+        add  esi,eax

+        sub  esi,ecx

+

+

+        mov  eax, [esp+24]

+        cmp  eax,ecx

+        jbe  L_do_copy1

+

+        sub  eax,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,edx

+

+L_do_copy1: 

+; 862 "inffast.S"

+        mov  ecx,eax

+        rep movsb

+

+        mov  esi, [esp+44]

+        jmp  L_while_test

+; 878 "inffast.S"

+ALIGN 4

+L_init_mmx: 

+        emms

+

+

+

+

+

+        movd mm0,ebp

+        mov  ebp,ebx

+; 896 "inffast.S"

+        movd mm4,[esp+0]

+        movq mm3,mm4

+        movd mm5,[esp+4]

+        movq mm2,mm5

+        pxor mm1,mm1

+        mov  ebx, [esp+8]

+        jmp  L_do_loop_mmx

+

+ALIGN 4

+L_do_loop_mmx: 

+        psrlq mm0,mm1

+

+        cmp  ebp,32

+        ja  L_get_length_code_mmx

+

+        movd mm6,ebp

+        movd mm7,[esi]

+        add  esi,4

+        psllq mm7,mm6

+        add  ebp,32

+        por mm0,mm7

+

+L_get_length_code_mmx: 

+        pand mm4,mm0

+        movd eax,mm4

+        movq mm4,mm3

+        mov  eax, [ebx+eax*4]

+

+L_dolen_mmx: 

+        movzx  ecx,ah

+        movd mm1,ecx

+        sub  ebp,ecx

+

+        test  al,al

+        jnz L_test_for_length_base_mmx

+

+        shr  eax,16

+        stosb

+

+L_while_test_mmx: 

+

+

+        cmp  [esp+16],edi

+        jbe L_break_loop

+

+        cmp  [esp+20],esi

+        ja L_do_loop_mmx

+        jmp L_break_loop

+

+L_test_for_length_base_mmx: 

+

+        mov  edx,eax

+        shr  edx,16

+

+        test  al,16

+        jz  L_test_for_second_level_length_mmx

+        and  eax,15

+        jz L_decode_distance_mmx

+

+        psrlq mm0,mm1

+        movd mm1,eax

+        movd ecx,mm0

+        sub  ebp,eax

+        and  ecx, [inflate_fast_mask+eax*4]

+        add  edx,ecx

+

+L_decode_distance_mmx: 

+        psrlq mm0,mm1

+

+        cmp  ebp,32

+        ja L_get_dist_code_mmx

+

+        movd mm6,ebp

+        movd mm7,[esi]

+        add  esi,4

+        psllq mm7,mm6

+        add  ebp,32

+        por mm0,mm7

+

+L_get_dist_code_mmx: 

+        mov  ebx, [esp+12]

+        pand mm5,mm0

+        movd eax,mm5

+        movq mm5,mm2

+        mov  eax, [ebx+eax*4]

+

+L_dodist_mmx: 

+

+        movzx  ecx,ah

+        mov  ebx,eax

+        shr  ebx,16

+        sub  ebp,ecx

+        movd mm1,ecx

+

+        test  al,16

+        jz L_test_for_second_level_dist_mmx

+        and  eax,15

+        jz L_check_dist_one_mmx

+

+L_add_bits_to_dist_mmx: 

+        psrlq mm0,mm1

+        movd mm1,eax

+        movd ecx,mm0

+        sub  ebp,eax

+        and  ecx, [inflate_fast_mask+eax*4]

+        add  ebx,ecx

+

+L_check_window_mmx: 

+        mov  [esp+44],esi

+        mov  eax,edi

+        sub  eax, [esp+40]

+

+        cmp  eax,ebx

+        jb L_clip_window_mmx

+

+        mov  ecx,edx

+        mov  esi,edi

+        sub  esi,ebx

+

+        sub  ecx,3

+        mov  al, [esi]

+        mov  [edi],al

+        mov  al, [esi+1]

+        mov  dl, [esi+2]

+        add  esi,3

+        mov  [edi+1],al

+        mov  [edi+2],dl

+        add  edi,3

+        rep movsb

+

+        mov  esi, [esp+44]

+        mov  ebx, [esp+8]

+        jmp  L_while_test_mmx

+

+ALIGN 4

+L_check_dist_one_mmx: 

+        cmp  ebx,1

+        jne  L_check_window_mmx

+        cmp  [esp+40],edi

+        je   L_check_window_mmx

+

+        dec  edi

+        mov  ecx,edx

+        mov  al, [edi]

+        sub  ecx,3

+

+        mov  [edi+1],al

+        mov  [edi+2],al

+        mov  [edi+3],al

+        add  edi,4

+        rep stosb

+

+        mov  ebx, [esp+8]

+        jmp  L_while_test_mmx

+

+ALIGN 4

+L_test_for_second_level_length_mmx: 

+        test  al,64

+        jnz L_test_for_end_of_block

+

+        and  eax,15

+        psrlq mm0,mm1

+        movd ecx,mm0

+        and  ecx, [inflate_fast_mask+eax*4]

+        add  ecx,edx

+        mov  eax, [ebx+ecx*4]

+        jmp L_dolen_mmx

+

+ALIGN 4

+L_test_for_second_level_dist_mmx: 

+        test  al,64

+        jnz L_invalid_distance_code

+

+        and  eax,15

+        psrlq mm0,mm1

+        movd ecx,mm0

+        and  ecx, [inflate_fast_mask+eax*4]

+        mov  eax, [esp+12]

+        add  ecx,ebx

+        mov  eax, [eax+ecx*4]

+        jmp  L_dodist_mmx

+

+ALIGN 4

+L_clip_window_mmx: 

+

+        mov  ecx,eax

+        mov  eax, [esp+52]

+        neg  ecx

+        mov  esi, [esp+56]

+

+        cmp  eax,ebx

+        jb  L_invalid_distance_too_far

+

+        add  ecx,ebx

+        cmp  dword ptr [esp+48],0

+        jne  L_wrap_around_window_mmx

+

+        sub  eax,ecx

+        add  esi,eax

+

+        cmp  edx,ecx

+        jbe  L_do_copy1_mmx

+

+        sub  edx,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,ebx

+        jmp  L_do_copy1_mmx

+

+        cmp  edx,ecx

+        jbe  L_do_copy1_mmx

+

+        sub  edx,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,ebx

+        jmp  L_do_copy1_mmx

+

+L_wrap_around_window_mmx: 

+

+        mov  eax, [esp+48]

+        cmp  ecx,eax

+        jbe  L_contiguous_in_window_mmx

+

+        add  esi, [esp+52]

+        add  esi,eax

+        sub  esi,ecx

+        sub  ecx,eax

+

+

+        cmp  edx,ecx

+        jbe  L_do_copy1_mmx

+

+        sub  edx,ecx

+        rep movsb

+        mov  esi, [esp+56]

+        mov  ecx, [esp+48]

+        cmp  edx,ecx

+        jbe  L_do_copy1_mmx

+

+        sub  edx,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,ebx

+        jmp  L_do_copy1_mmx

+

+L_contiguous_in_window_mmx: 

+

+        add  esi,eax

+        sub  esi,ecx

+

+

+        cmp  edx,ecx

+        jbe  L_do_copy1_mmx

+

+        sub  edx,ecx

+        rep movsb

+        mov  esi,edi

+        sub  esi,ebx

+

+L_do_copy1_mmx: 

+

+

+        mov  ecx,edx

+        rep movsb

+

+        mov  esi, [esp+44]

+        mov  ebx, [esp+8]

+        jmp  L_while_test_mmx

+; 1174 "inffast.S"

+L_invalid_distance_code: 

+

+

+

+

+

+        mov  ecx, invalid_distance_code_msg

+        mov  edx,26

+        jmp  L_update_stream_state

+

+L_test_for_end_of_block: 

+

+

+

+

+

+        test  al,32

+        jz  L_invalid_literal_length_code

+

+        mov  ecx,0

+        mov  edx,11

+        jmp  L_update_stream_state

+

+L_invalid_literal_length_code: 

+

+

+

+

+

+        mov  ecx, invalid_literal_length_code_msg

+        mov  edx,26

+        jmp  L_update_stream_state

+

+L_invalid_distance_too_far: 

+

+

+

+        mov  esi, [esp+44]

+        mov  ecx, invalid_distance_too_far_msg

+        mov  edx,26

+        jmp  L_update_stream_state

+

+L_update_stream_state: 

+

+        mov  eax, [esp+88]

+        test  ecx,ecx

+        jz  L_skip_msg

+        mov  [eax+24],ecx

+L_skip_msg: 

+        mov  eax, [eax+28]

+        mov  [eax+0],edx

+        jmp  L_break_loop

+

+ALIGN 4

+L_break_loop: 

+; 1243 "inffast.S"

+        cmp  dword ptr [inflate_fast_use_mmx],2

+        jne  L_update_next_in

+

+

+

+        mov  ebx,ebp

+

+L_update_next_in: 

+; 1266 "inffast.S"

+        mov  eax, [esp+88]

+        mov  ecx,ebx

+        mov  edx, [eax+28]

+        shr  ecx,3

+        sub  esi,ecx

+        shl  ecx,3

+        sub  ebx,ecx

+        mov  [eax+12],edi

+        mov  [edx+48],ebx

+        mov  ecx,ebx

+

+        lea  ebx, [esp+28]

+        cmp  [esp+20],ebx

+        jne  L_buf_not_used

+

+        sub  esi,ebx

+        mov  ebx, [eax+0]

+        mov  [esp+20],ebx

+        add  esi,ebx

+        mov  ebx, [eax+4]

+        sub  ebx,11

+        add  [esp+20],ebx

+

+L_buf_not_used: 

+        mov  [eax+0],esi

+

+        mov  ebx,1

+        shl  ebx,cl

+        dec  ebx

+

+

+

+

+

+        cmp  dword ptr [inflate_fast_use_mmx],2

+        jne  L_update_hold

+

+

+

+        psrlq mm0,mm1

+        movd ebp,mm0

+

+        emms

+

+L_update_hold: 

+

+

+

+        and  ebp,ebx

+        mov  [edx+44],ebp

+

+

+

+

+        mov  ebx, [esp+20]

+        cmp  ebx,esi

+        jbe  L_last_is_smaller

+

+        sub  ebx,esi

+        add  ebx,11

+        mov  [eax+4],ebx

+        jmp  L_fixup_out

+L_last_is_smaller: 

+        sub  esi,ebx

+        neg  esi

+        add  esi,11

+        mov  [eax+4],esi

+

+

+

+

+L_fixup_out: 

+

+        mov  ebx, [esp+16]

+        cmp  ebx,edi

+        jbe  L_end_is_smaller

+

+        sub  ebx,edi

+        add  ebx,257

+        mov  [eax+16],ebx

+        jmp  L_done

+L_end_is_smaller: 

+        sub  edi,ebx

+        neg  edi

+        add  edi,257

+        mov  [eax+16],edi

+

+

+

+

+

+L_done: 

+        add  esp,64

+        popfd

+        pop  ebx

+        pop  ebp

+        pop  esi

+        pop  edi

+        ret

+

+

+

+

+_TEXT   ends

+end

diff --git a/contrib/vstudio/vc70_32/inffastAsm.obj b/contrib/vstudio/vc70_32/inffastAsm.obj
new file mode 100644
index 0000000..3855400
--- /dev/null
+++ b/contrib/vstudio/vc70_32/inffastAsm.obj
Binary files differ
diff --git a/contrib/vstudio/vc70_32/miniunz.vcproj b/contrib/vstudio/vc70_32/miniunz.vcproj
new file mode 100644
index 0000000..56f0da3
--- /dev/null
+++ b/contrib/vstudio/vc70_32/miniunz.vcproj
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding = "Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.00"

+	Name="miniunz"

+	ProjectGUID="{C52F9E7B-498A-42BE-8DB4-85A15694382A}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/miniunz.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/miniunz.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="2"

+				InlineFunctionExpansion="1"

+				OmitFramePointers="TRUE"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				StringPooling="TRUE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/miniunz.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				OptimizeForWindows98="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+	</Configurations>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">

+			<File

+				RelativePath="miniunz.c">

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc">

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">

+		</Filter>

+		<File

+			RelativePath="zlib.lib">

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/contrib/vstudio/vc70_32/minizip.vcproj b/contrib/vstudio/vc70_32/minizip.vcproj
new file mode 100644
index 0000000..2cc5aca
--- /dev/null
+++ b/contrib/vstudio/vc70_32/minizip.vcproj
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding = "Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.00"

+	Name="minizip"

+	ProjectGUID="{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="5"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/minizip.exe"

+				LinkIncremental="2"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="$(OutDir)/minizip.pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="1"

+			CharacterSet="2">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="2"

+				InlineFunctionExpansion="1"

+				OmitFramePointers="TRUE"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				StringPooling="TRUE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				UsePrecompiledHeader="0"

+				WarningLevel="3"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				OutputFile="$(OutDir)/minizip.exe"

+				LinkIncremental="1"

+				GenerateDebugInformation="TRUE"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				OptimizeForWindows98="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+	</Configurations>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">

+			<File

+				RelativePath="minizip.c">

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc">

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">

+		</Filter>

+		<File

+			RelativePath="zlib.lib">

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/contrib/vstudio/vc70_32/mkgvmt32.bat b/contrib/vstudio/vc70_32/mkgvmt32.bat
new file mode 100644
index 0000000..9c54db7
--- /dev/null
+++ b/contrib/vstudio/vc70_32/mkgvmt32.bat
@@ -0,0 +1,2 @@
+c:\masm611\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm

+c:\masm611\bin\ml /coff /Zi /c /FlinffastAsm.lst inffastAsm.asm

diff --git a/contrib/vstudio/vc70_32/zlib.rc b/contrib/vstudio/vc70_32/zlib.rc
new file mode 100644
index 0000000..5d86e03
--- /dev/null
+++ b/contrib/vstudio/vc70_32/zlib.rc
@@ -0,0 +1,32 @@
+#include <windows.h>

+

+#define IDR_VERSION1  1

+IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE

+  FILEVERSION	 1,2,0,0

+  PRODUCTVERSION 1,2,0,0

+  FILEFLAGSMASK	VS_FFI_FILEFLAGSMASK

+  FILEFLAGS	0

+  FILEOS	VOS_DOS_WINDOWS32

+  FILETYPE	VFT_DLL

+  FILESUBTYPE	0	// not used

+BEGIN

+  BLOCK "StringFileInfo"

+  BEGIN

+    BLOCK "040904E4"

+    //language ID = U.S. English, char set = Windows, Multilingual

+

+    BEGIN

+      VALUE "FileDescription", "zlib data compression library\0"

+      VALUE "FileVersion",	"1.2.0.0\0"

+      VALUE "InternalName",	"zlib\0"

+      VALUE "OriginalFilename",	"zlib.dll\0"

+      VALUE "ProductName",	"ZLib.DLL\0"

+      VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"

+      VALUE "LegalCopyright", "(C) 1995-2003 Jean-loup Gailly & Mark Adler\0"

+    END

+  END

+  BLOCK "VarFileInfo"

+  BEGIN

+    VALUE "Translation", 0x0409, 1252

+  END

+END

diff --git a/contrib/vstudio/vc70_32/zlibstat.vcproj b/contrib/vstudio/vc70_32/zlibstat.vcproj
new file mode 100644
index 0000000..94d4a63
--- /dev/null
+++ b/contrib/vstudio/vc70_32/zlibstat.vcproj
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding = "Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.00"

+	Name="zlibstat"

+	SccProjectName=""

+	SccLocalPath="">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory=".\zlibstatDebug"

+			IntermediateDirectory=".\zlibstatDebug"

+			ConfigurationType="4"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="5"

+				PrecompiledHeaderFile=".\zlibstatDebug/zlibstat.pch"

+				AssemblerListingLocation=".\zlibstatDebug/"

+				ObjectFile=".\zlibstatDebug/"

+				ProgramDataBaseFileName=".\zlibstatDebug/"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"

+				DebugInformationFormat="1"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				AdditionalOptions="/NODEFAULTLIB "

+				OutputFile=".\zlibstatDebug\zlibstat.lib"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="ReleaseAxp|Win32"

+			OutputDirectory=".\zlibsta0"

+			IntermediateDirectory=".\zlibsta0"

+			ConfigurationType="4"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibsta0/zlibstat.pch"

+				AssemblerListingLocation=".\zlibsta0/"

+				ObjectFile=".\zlibsta0/"

+				ProgramDataBaseFileName=".\zlibsta0/"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				AdditionalOptions="/NODEFAULTLIB "

+				OutputFile=".\zlibsta0\zlibstat.lib"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory=".\zlibstat"

+			IntermediateDirectory=".\zlibstat"

+			ConfigurationType="4"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32,ASMV"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"

+				AssemblerListingLocation=".\zlibstat/"

+				ObjectFile=".\zlibstat/"

+				ProgramDataBaseFileName=".\zlibstat/"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				AdditionalOptions="gvmat32.obj  inffastAsm.obj /NODEFAULTLIB "

+				OutputFile=".\zlibstat\zlibstat.lib"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="ReleaseWithoutAsm|Win32"

+			OutputDirectory="zlibstatWithoutAsm"

+			IntermediateDirectory="zlibstatWithoutAsm"

+			ConfigurationType="4"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="4"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibstat/zlibstat.pch"

+				AssemblerListingLocation=".\zlibstatWithoutAsm/"

+				ObjectFile=".\zlibstatWithoutAsm/"

+				ProgramDataBaseFileName=".\zlibstatWithoutAsm/"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLibrarianTool"

+				AdditionalOptions=" /NODEFAULTLIB "

+				OutputFile=".\zlibstatWithoutAsm\zlibstat.lib"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="">

+			<File

+				RelativePath=".\adler32.c">

+			</File>

+			<File

+				RelativePath=".\compress.c">

+			</File>

+			<File

+				RelativePath=".\crc32.c">

+			</File>

+			<File

+				RelativePath=".\deflate.c">

+			</File>

+			<File

+				RelativePath=".\gvmat32c.c">

+			</File>

+			<File

+				RelativePath=".\gzio.c">

+			</File>

+			<File

+				RelativePath=".\infback.c">

+			</File>

+			<File

+				RelativePath=".\inffast.c">

+				<FileConfiguration

+					Name="Release|Win32"

+					ExcludedFromBuild="TRUE">

+					<Tool

+						Name="VCCLCompilerTool"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="ReleaseWithoutAsm|Win32">

+					<Tool

+						Name="VCCLCompilerTool"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\inflate.c">

+			</File>

+			<File

+				RelativePath=".\inftrees.c">

+			</File>

+			<File

+				RelativePath=".\ioapi.c">

+			</File>

+			<File

+				RelativePath=".\trees.c">

+			</File>

+			<File

+				RelativePath=".\uncompr.c">

+			</File>

+			<File

+				RelativePath=".\unzip.c">

+			</File>

+			<File

+				RelativePath=".\zip.c">

+			</File>

+			<File

+				RelativePath=".\zlib.rc">

+			</File>

+			<File

+				RelativePath=".\zlibvc.def">

+			</File>

+			<File

+				RelativePath=".\zutil.c">

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/contrib/vstudio/vc70_32/zlibvc.def b/contrib/vstudio/vc70_32/zlibvc.def
new file mode 100644
index 0000000..90109d6
--- /dev/null
+++ b/contrib/vstudio/vc70_32/zlibvc.def
@@ -0,0 +1,88 @@
+LIBRARY		"zlib"

+

+VERSION		1.20

+

+HEAPSIZE	1048576,8192

+

+EXPORTS

+        adler32                                  @1

+        compress                                 @2

+        crc32                                    @3

+        deflate                                  @4

+        deflateCopy                              @5

+        deflateEnd                               @6

+        deflateInit2_                            @7

+        deflateInit_                             @8

+        deflateParams                            @9

+        deflateReset                             @10

+        deflateSetDictionary                     @11

+        gzclose                                  @12

+        gzdopen                                  @13

+        gzerror                                  @14

+        gzflush                                  @15

+        gzopen                                   @16

+        gzread                                   @17

+        gzwrite                                  @18

+        inflate                                  @19

+        inflateEnd                               @20

+        inflateInit2_                            @21

+        inflateInit_                             @22

+        inflateReset                             @23

+        inflateSetDictionary                     @24

+        inflateSync                              @25

+        uncompress                               @26

+        zlibVersion                              @27

+        gzprintf                                 @28

+        gzputc                                   @29

+        gzgetc                                   @30

+        gzseek                                   @31

+        gzrewind                                 @32

+        gztell                                   @33

+        gzeof                                    @34

+        gzsetparams                              @35

+        zError                                   @36

+        inflateSyncPoint                         @37

+        get_crc_table                            @38

+        compress2                                @39

+        gzputs                                   @40

+        gzgets                                   @41

+        inflateCopy                              @42

+        inflateBackInit_                         @43

+        inflateBack                              @44

+        inflateBackEnd                           @45

+        compressBound                            @46

+

+        unzOpen                                  @61

+        unzClose                                 @62

+        unzGetGlobalInfo                         @63

+        unzGetCurrentFileInfo                    @64

+        unzGoToFirstFile                         @65

+        unzGoToNextFile                          @66

+        unzOpenCurrentFile                       @67

+        unzReadCurrentFile                       @68

+        unzOpenCurrentFile3                      @69

+        unztell                                  @70

+        unzeof                                   @71

+        unzCloseCurrentFile                      @72

+        unzGetGlobalComment                      @73

+        unzStringFileNameCompare                 @74

+        unzLocateFile                            @75

+        unzGetLocalExtrafield                    @76

+        unzOpen2                                 @77

+        unzOpenCurrentFile2                      @78

+        unzOpenCurrentFilePassword               @79

+

+        zipOpen                                  @80

+        zipOpenNewFileInZip                      @81

+        zipWriteInFileInZip                      @82

+        zipCloseFileInZip                        @83

+        zipClose                                 @84

+        zipOpenNewFileInZip2                     @86

+        zipCloseFileInZipRaw                     @87

+        zipOpen2                                 @88

+        zipOpenNewFileInZip3                     @89

+

+        unzGetFilePos                            @100

+        unzGoToFilePos                           @101

+

+        fill_win32_filefunc                      @110

diff --git a/contrib/vstudio/vc70_32/zlibvc.sln b/contrib/vstudio/vc70_32/zlibvc.sln
new file mode 100644
index 0000000..5a007ff
--- /dev/null
+++ b/contrib/vstudio/vc70_32/zlibvc.sln
@@ -0,0 +1,66 @@
+Microsoft Visual Studio Solution File, Format Version 7.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}"

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		ConfigName.0 = Debug

+		ConfigName.1 = Release

+		ConfigName.2 = ReleaseAxp

+		ConfigName.3 = ReleaseWithoutAsm

+		ConfigName.4 = ReleaseWithoutCrtdll

+	EndGlobalSection

+	GlobalSection(ProjectDependencies) = postSolution

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.ActiveCfg = Debug|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug.Build.0 = Debug|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.ActiveCfg = Release|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release.Build.0 = Release|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseAxp.Build.0 = ReleaseAxp|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseAxp|Win32

+		{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutCrtdll.Build.0 = ReleaseAxp|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.ActiveCfg = Debug|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug.Build.0 = Debug|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.ActiveCfg = Release|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release.Build.0 = Release|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.ActiveCfg = ReleaseAxp|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseAxp.Build.0 = ReleaseAxp|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.ActiveCfg = ReleaseWithoutAsm|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm.Build.0 = ReleaseWithoutAsm|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.ActiveCfg = ReleaseWithoutCrtdll|Win32

+		{8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutCrtdll.Build.0 = ReleaseWithoutCrtdll|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.ActiveCfg = Debug|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug.Build.0 = Debug|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.ActiveCfg = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release.Build.0 = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.ActiveCfg = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAxp.Build.0 = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.ActiveCfg = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm.Build.0 = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32

+		{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutCrtdll.Build.0 = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.ActiveCfg = Debug|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug.Build.0 = Debug|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.ActiveCfg = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release.Build.0 = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.ActiveCfg = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseAxp.Build.0 = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.ActiveCfg = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm.Build.0 = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.ActiveCfg = Release|Win32

+		{C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutCrtdll.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/contrib/vstudio/vc70_32/zlibvc.vcproj b/contrib/vstudio/vc70_32/zlibvc.vcproj
new file mode 100644
index 0000000..fcf9892
--- /dev/null
+++ b/contrib/vstudio/vc70_32/zlibvc.vcproj
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding = "Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.00"

+	Name="zlibvc"

+	SccProjectName=""

+	SccLocalPath="">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory=".\DebugDll"

+			IntermediateDirectory=".\DebugDll"

+			ConfigurationType="2"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				PreprocessorDefinitions="WIN32,ASMV"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="1"

+				PrecompiledHeaderFile=".\DebugDll/zlibvc.pch"

+				AssemblerListingLocation=".\DebugDll/"

+				ObjectFile=".\DebugDll/"

+				ProgramDataBaseFileName=".\DebugDll/"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions="/MACHINE:I386"

+				AdditionalDependencies="gvmat32.obj "

+				OutputFile=".\DebugDll\zlib.dll"

+				LinkIncremental="2"

+				SuppressStartupBanner="TRUE"

+				ModuleDefinitionFile=".\zlibvc.def"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile=".\DebugDll/zlib.pdb"

+				SubSystem="2"

+				ImportLibrary=".\DebugDll/zlib.lib"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_DEBUG"

+				MkTypLibCompatible="TRUE"

+				SuppressStartupBanner="TRUE"

+				TargetEnvironment="1"

+				TypeLibraryName=".\DebugDll/zlibvc.tlb"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_DEBUG"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="ReleaseWithoutAsm|Win32"

+			OutputDirectory=".\zlibDllWithoutAsm"

+			IntermediateDirectory=".\zlibDllWithoutAsm"

+			ConfigurationType="2"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="0"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibDllWithoutAsm/zlibvc.pch"

+				AssemblerOutput="2"

+				AssemblerListingLocation=".\zlibDllWithoutAsm/"

+				ObjectFile=".\zlibDllWithoutAsm/"

+				ProgramDataBaseFileName=".\zlibDllWithoutAsm/"

+				BrowseInformation="1"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions="/MACHINE:I386"

+				AdditionalDependencies="crtdll.lib"

+				OutputFile=".\zlibDllWithoutAsm\zlib.dll"

+				LinkIncremental="1"

+				SuppressStartupBanner="TRUE"

+				IgnoreAllDefaultLibraries="TRUE"

+				ModuleDefinitionFile=".\zlibvc.def"

+				ProgramDatabaseFile=".\zlibDllWithoutAsm/zlib.pdb"

+				GenerateMapFile="TRUE"

+				MapFileName=".\zlibDllWithoutAsm/zlib.map"

+				SubSystem="2"

+				OptimizeForWindows98="1"

+				ImportLibrary=".\zlibDllWithoutAsm/zlib.lib"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="TRUE"

+				SuppressStartupBanner="TRUE"

+				TargetEnvironment="1"

+				TypeLibraryName=".\zlibDllWithoutAsm/zlibvc.tlb"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="ReleaseWithoutCrtdll|Win32"

+			OutputDirectory=".\zlibDllWithoutCrtDll"

+			IntermediateDirectory=".\zlibDllWithoutCrtDll"

+			ConfigurationType="2"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32,ASMV"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="0"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibDllWithoutCrtDll/zlibvc.pch"

+				AssemblerOutput="2"

+				AssemblerListingLocation=".\zlibDllWithoutCrtDll/"

+				ObjectFile=".\zlibDllWithoutCrtDll/"

+				ProgramDataBaseFileName=".\zlibDllWithoutCrtDll/"

+				BrowseInformation="1"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions="/MACHINE:I386"

+				AdditionalDependencies="gvmat32.obj inffastAsm.obj "

+				OutputFile=".\zlibDllWithoutCrtDll\zlib.dll"

+				LinkIncremental="1"

+				SuppressStartupBanner="TRUE"

+				IgnoreAllDefaultLibraries="FALSE"

+				ModuleDefinitionFile=".\zlibvc.def"

+				ProgramDatabaseFile=".\zlibDllWithoutCrtDll/zlib.pdb"

+				GenerateMapFile="TRUE"

+				MapFileName=".\zlibDllWithoutCrtDll/zlib.map"

+				SubSystem="2"

+				OptimizeForWindows98="1"

+				ImportLibrary=".\zlibDllWithoutCrtDll/zlib.lib"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="TRUE"

+				SuppressStartupBanner="TRUE"

+				TargetEnvironment="1"

+				TypeLibraryName=".\zlibDllWithoutCrtDll/zlibvc.tlb"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="ReleaseAxp|Win32"

+			OutputDirectory=".\zlibvc__"

+			IntermediateDirectory=".\zlibvc__"

+			ConfigurationType="2"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="0"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\zlibvc__/zlibvc.pch"

+				AssemblerOutput="2"

+				AssemblerListingLocation=".\zlibvc__/"

+				ObjectFile=".\zlibvc__/"

+				ProgramDataBaseFileName=".\zlibvc__/"

+				BrowseInformation="1"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="crtdll.lib"

+				OutputFile="zlibvc__\zlib.dll"

+				LinkIncremental="1"

+				SuppressStartupBanner="TRUE"

+				IgnoreAllDefaultLibraries="TRUE"

+				ModuleDefinitionFile=".\zlibvc.def"

+				ProgramDatabaseFile=".\zlibvc__/zlib.pdb"

+				GenerateMapFile="TRUE"

+				MapFileName=".\zlibvc__/zlib.map"

+				SubSystem="2"

+				ImportLibrary=".\zlibvc__/zlib.lib"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="TRUE"

+				SuppressStartupBanner="TRUE"

+				TargetEnvironment="1"

+				TypeLibraryName=".\zlibvc__/zlibvc.tlb"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory=".\ReleaseDll"

+			IntermediateDirectory=".\ReleaseDll"

+			ConfigurationType="2"

+			UseOfMFC="0"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE">

+			<Tool

+				Name="VCCLCompilerTool"

+				InlineFunctionExpansion="1"

+				PreprocessorDefinitions="WIN32,ASMV"

+				StringPooling="TRUE"

+				ExceptionHandling="FALSE"

+				RuntimeLibrary="0"

+				EnableFunctionLevelLinking="TRUE"

+				PrecompiledHeaderFile=".\ReleaseDll/zlibvc.pch"

+				AssemblerOutput="2"

+				AssemblerListingLocation=".\ReleaseDll/"

+				ObjectFile=".\ReleaseDll/"

+				ProgramDataBaseFileName=".\ReleaseDll/"

+				BrowseInformation="1"

+				WarningLevel="3"

+				SuppressStartupBanner="TRUE"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalOptions="/MACHINE:I386"

+				AdditionalDependencies="gvmat32.obj inffastAsm.obj crtdll.lib"

+				OutputFile=".\ReleaseDll\zlib.dll"

+				LinkIncremental="1"

+				SuppressStartupBanner="TRUE"

+				IgnoreAllDefaultLibraries="TRUE"

+				ModuleDefinitionFile=".\zlibvc.def"

+				ProgramDatabaseFile=".\ReleaseDll/zlib.pdb"

+				GenerateMapFile="TRUE"

+				MapFileName=".\ReleaseDll/zlib.map"

+				SubSystem="2"

+				OptimizeForWindows98="1"

+				ImportLibrary=".\ReleaseDll/zlib.lib"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="TRUE"

+				SuppressStartupBanner="TRUE"

+				TargetEnvironment="1"

+				TypeLibraryName=".\Release/zlibvc.tlb"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1036"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+		</Configuration>

+	</Configurations>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90">

+			<File

+				RelativePath=".\adler32.c">

+			</File>

+			<File

+				RelativePath=".\compress.c">

+			</File>

+			<File

+				RelativePath=".\crc32.c">

+			</File>

+			<File

+				RelativePath=".\deflate.c">

+			</File>

+			<File

+				RelativePath=".\gvmat32c.c">

+				<FileConfiguration

+					Name="ReleaseWithoutAsm|Win32"

+					ExcludedFromBuild="TRUE">

+					<Tool

+						Name="VCCLCompilerTool"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\gzio.c">

+			</File>

+			<File

+				RelativePath=".\infback.c">

+			</File>

+			<File

+				RelativePath=".\inffast.c">

+				<FileConfiguration

+					Name="ReleaseWithoutCrtdll|Win32"

+					ExcludedFromBuild="TRUE">

+					<Tool

+						Name="VCCLCompilerTool"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32"

+					ExcludedFromBuild="TRUE">

+					<Tool

+						Name="VCCLCompilerTool"/>

+				</FileConfiguration>

+			</File>

+			<File

+				RelativePath=".\inflate.c">

+			</File>

+			<File

+				RelativePath=".\inftrees.c">

+			</File>

+			<File

+				RelativePath=".\ioapi.c">

+			</File>

+			<File

+				RelativePath=".\iowin32.c">

+			</File>

+			<File

+				RelativePath=".\trees.c">

+			</File>

+			<File

+				RelativePath=".\uncompr.c">

+			</File>

+			<File

+				RelativePath=".\unzip.c">

+			</File>

+			<File

+				RelativePath=".\zip.c">

+			</File>

+			<File

+				RelativePath=".\zlib.rc">

+			</File>

+			<File

+				RelativePath=".\zlibvc.def">

+			</File>

+			<File

+				RelativePath=".\zutil.c">

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;fi;fd">

+			<File

+				RelativePath=".\deflate.h">

+			</File>

+			<File

+				RelativePath=".\infblock.h">

+			</File>

+			<File

+				RelativePath=".\infcodes.h">

+			</File>

+			<File

+				RelativePath=".\inffast.h">

+			</File>

+			<File

+				RelativePath=".\inftrees.h">

+			</File>

+			<File

+				RelativePath=".\infutil.h">

+			</File>

+			<File

+				RelativePath=".\zconf.h">

+			</File>

+			<File

+				RelativePath=".\zlib.h">

+			</File>

+			<File

+				RelativePath=".\zutil.h">

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/deflate.c b/deflate.c
index d13627e..97a080c 100644
--- a/deflate.c
+++ b/deflate.c
@@ -1,6 +1,6 @@
 /* deflate.c -- compress data using the deflation algorithm
  * Copyright (C) 1995-2003 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /*
@@ -52,7 +52,7 @@
 #include "deflate.h"
 
 const char deflate_copyright[] =
-   " deflate 1.2.0 Copyright 1995-2003 Jean-loup Gailly ";
+   " deflate 1.2.0.1 Copyright 1995-2003 Jean-loup Gailly ";
 /*
   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
@@ -76,17 +76,22 @@
 local void fill_window    OF((deflate_state *s));
 local block_state deflate_stored OF((deflate_state *s, int flush));
 local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
 local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
 local void lm_init        OF((deflate_state *s));
 local void putShortMSB    OF((deflate_state *s, uInt b));
 local void flush_pending  OF((z_streamp strm));
 local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
 #ifdef ASMV
       void match_init OF((void)); /* asm code initialization */
       uInt longest_match  OF((deflate_state *s, IPos cur_match));
 #else
 local uInt longest_match  OF((deflate_state *s, IPos cur_match));
 #endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
 
 #ifdef DEBUG
 local  void check_match OF((deflate_state *s, IPos start, IPos match,
@@ -123,6 +128,12 @@
    compress_func func;
 } config;
 
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* maximum speed, no lazy matches */
+#else
 local const config configuration_table[10] = {
 /*      good lazy nice chain */
 /* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
@@ -136,6 +147,7 @@
 /* 7 */ {8,   32, 128, 256, deflate_slow},
 /* 8 */ {32, 128, 258, 1024, deflate_slow},
 /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+#endif
 
 /* 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
@@ -194,13 +206,13 @@
     int stream_size;
 {
     return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
-			 Z_DEFAULT_STRATEGY, version, stream_size);
+                         Z_DEFAULT_STRATEGY, version, stream_size);
     /* To do: ignore strm->next_in if we use it as window */
 }
 
 /* ========================================================================= */
 int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
-		  version, stream_size)
+                  version, stream_size)
     z_streamp strm;
     int  level;
     int  method;
@@ -221,20 +233,21 @@
 
     if (version == Z_NULL || version[0] != my_version[0] ||
         stream_size != sizeof(z_stream)) {
-	return Z_VERSION_ERROR;
+        return Z_VERSION_ERROR;
     }
     if (strm == Z_NULL) return Z_STREAM_ERROR;
 
     strm->msg = Z_NULL;
     if (strm->zalloc == Z_NULL) {
-	strm->zalloc = zcalloc;
-	strm->opaque = (voidpf)0;
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
     }
     if (strm->zfree == Z_NULL) strm->zfree = zcfree;
 
-    if (level == Z_DEFAULT_COMPRESSION) level = 6;
 #ifdef FASTEST
-    level = 1;
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
 #endif
 
     if (windowBits < 0) { /* undocumented feature: suppress zlib header */
@@ -243,7 +256,7 @@
     }
     if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
         windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
-	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+        strategy < 0 || strategy > Z_RLE) {
         return Z_STREAM_ERROR;
     }
     s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
@@ -309,9 +322,9 @@
 
     if (length < MIN_MATCH) return Z_OK;
     if (length > MAX_DIST(s)) {
-	length = MAX_DIST(s);
+        length = MAX_DIST(s);
 #ifndef USE_DICT_HEAD
-	dictionary += dictLength - length; /* use the tail of the dictionary */
+        dictionary += dictLength - length; /* use the tail of the dictionary */
 #endif
     }
     zmemcpy(s->window, dictionary, length);
@@ -325,7 +338,7 @@
     s->ins_h = s->window[0];
     UPDATE_HASH(s, s->ins_h, s->window[1]);
     for (n = 0; n <= length - MIN_MATCH; n++) {
-	INSERT_STRING(s, n, hash_head);
+        INSERT_STRING(s, n, hash_head);
     }
     if (hash_head) hash_head = 0;  /* to make compiler happy */
     return Z_OK;
@@ -336,7 +349,7 @@
     z_streamp strm;
 {
     deflate_state *s;
-    
+
     if (strm == Z_NULL || strm->state == Z_NULL ||
         strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
 
@@ -374,24 +387,26 @@
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
     s = strm->state;
 
-    if (level == Z_DEFAULT_COMPRESSION) {
-	level = 6;
-    }
-    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
-	return Z_STREAM_ERROR;
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) {
+        return Z_STREAM_ERROR;
     }
     func = configuration_table[s->level].func;
 
     if (func != configuration_table[level].func && strm->total_in != 0) {
-	/* Flush the last buffer: */
-	err = deflate(strm, Z_PARTIAL_FLUSH);
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_PARTIAL_FLUSH);
     }
     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->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;
@@ -449,7 +464,7 @@
 {
     put_byte(s, (Byte)(b >> 8));
     put_byte(s, (Byte)(b & 0xff));
-}   
+}
 
 /* =========================================================================
  * Flush as much pending output as possible. All deflate() output goes
@@ -485,14 +500,14 @@
     deflate_state *s;
 
     if (strm == Z_NULL || strm->state == Z_NULL ||
-	flush > Z_FINISH || flush < 0) {
+        flush > Z_FINISH || flush < 0) {
         return Z_STREAM_ERROR;
     }
     s = strm->state;
 
     if (strm->next_out == Z_NULL ||
         (strm->next_in == Z_NULL && strm->avail_in != 0) ||
-	(s->status == FINISH_STATE && flush != Z_FINISH)) {
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
         ERR_RETURN(strm, Z_STREAM_ERROR);
     }
     if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
@@ -509,40 +524,40 @@
 
         if (level_flags > 3) level_flags = 3;
         header |= (level_flags << 6);
-	if (s->strstart != 0) header |= PRESET_DICT;
+        if (s->strstart != 0) header |= PRESET_DICT;
         header += 31 - (header % 31);
 
         s->status = BUSY_STATE;
         putShortMSB(s, header);
 
-	/* Save the adler32 of the preset dictionary: */
-	if (s->strstart != 0) {
-	    putShortMSB(s, (uInt)(strm->adler >> 16));
-	    putShortMSB(s, (uInt)(strm->adler & 0xffff));
-	}
-	strm->adler = 1L;
+        /* Save the adler32 of the preset dictionary: */
+        if (s->strstart != 0) {
+            putShortMSB(s, (uInt)(strm->adler >> 16));
+            putShortMSB(s, (uInt)(strm->adler & 0xffff));
+        }
+        strm->adler = 1L;
     }
 
     /* Flush as much pending output as possible */
     if (s->pending != 0) {
         flush_pending(strm);
         if (strm->avail_out == 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:
+            /* 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:
              */
-	    s->last_flush = -1;
-	    return Z_OK;
-	}
+            s->last_flush = -1;
+            return Z_OK;
+        }
 
     /* 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_BUFF_ERROR.
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
      */
     } else if (strm->avail_in == 0 && flush <= old_flush &&
-	       flush != Z_FINISH) {
+               flush != Z_FINISH) {
         ERR_RETURN(strm, Z_BUF_ERROR);
     }
 
@@ -557,24 +572,24 @@
         (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
         block_state bstate;
 
-	bstate = (*(configuration_table[s->level].func))(s, flush);
+        bstate = (*(configuration_table[s->level].func))(s, flush);
 
         if (bstate == finish_started || bstate == finish_done) {
             s->status = FINISH_STATE;
         }
         if (bstate == need_more || bstate == finish_started) {
-	    if (strm->avail_out == 0) {
-	        s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
-	    }
-	    return Z_OK;
-	    /* 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.
-	     */
-	}
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* 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.
+             */
+        }
         if (bstate == block_done) {
             if (flush == Z_PARTIAL_FLUSH) {
                 _tr_align(s);
@@ -588,10 +603,10 @@
                 }
             }
             flush_pending(strm);
-	    if (strm->avail_out == 0) {
-	      s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
-	      return Z_OK;
-	    }
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
         }
     }
     Assert(strm->avail_out > 0, "bug2");
@@ -620,7 +635,7 @@
 
     status = strm->state->status;
     if (status != INIT_STATE && status != BUSY_STATE &&
-	status != FINISH_STATE) {
+        status != FINISH_STATE) {
       return Z_STREAM_ERROR;
     }
 
@@ -693,7 +708,7 @@
     ds->bl_desc.dyn_tree = ds->bl_tree;
 
     return Z_OK;
-#endif
+#endif /* MAXSEG_64K */
 }
 
 /* ===========================================================================
@@ -753,6 +768,7 @@
 #endif
 }
 
+#ifndef FASTEST
 /* ===========================================================================
  * 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,
@@ -766,7 +782,6 @@
 /* For 80x86 and 680x0, an optimized version will be provided in match.asm or
  * match.S. The code will be functionally equivalent.
  */
-#ifndef FASTEST
 local uInt longest_match(s, cur_match)
     deflate_state *s;
     IPos cur_match;                             /* current match */
@@ -904,12 +919,13 @@
     if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
     return s->lookahead;
 }
+#endif /* ASMV */
+#endif /* FASTEST */
 
-#else /* FASTEST */
 /* ---------------------------------------------------------------------------
- * Optimized version for level == 1 only
+ * Optimized version for level == 1 or strategy == Z_RLE only
  */
-local uInt longest_match(s, cur_match)
+local uInt longest_match_fast(s, cur_match)
     deflate_state *s;
     IPos cur_match;                             /* current match */
 {
@@ -947,10 +963,10 @@
      */
     do {
     } while (*++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     *++scan == *++match && *++scan == *++match &&
-	     scan < strend);
+             *++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");
 
@@ -961,8 +977,6 @@
     s->match_start = cur_match;
     return len <= s->lookahead ? len : s->lookahead;
 }
-#endif /* FASTEST */
-#endif /* ASMV */
 
 #ifdef DEBUG
 /* ===========================================================================
@@ -977,10 +991,10 @@
     if (zmemcmp(s->window + match,
                 s->window + start, length) != EQUAL) {
         fprintf(stderr, " start %u, match %u, length %d\n",
-		start, match, length);
+                start, match, length);
         do {
-	    fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
-	} while (--length != 0);
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
         z_error("invalid match");
     }
     if (z_verbose > 1) {
@@ -990,7 +1004,7 @@
 }
 #else
 #  define check_match(s, start, match, length)
-#endif
+#endif /* DEBUG */
 
 /* ===========================================================================
  * Fill the window when the lookahead becomes insufficient.
@@ -1039,23 +1053,23 @@
                later. (Using level 0 permanently is not an optimal usage of
                zlib, so we don't care about this pathological case.)
              */
-	    n = s->hash_size;
-	    p = &s->head[n];
-	    do {
-		m = *--p;
-		*p = (Pos)(m >= wsize ? m-wsize : NIL);
-	    } while (--n);
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
 
-	    n = wsize;
+            n = wsize;
 #ifndef FASTEST
-	    p = &s->prev[n];
-	    do {
-		m = *--p;
-		*p = (Pos)(m >= wsize ? m-wsize : NIL);
-		/* If n is not on any hash chain, prev[n] is garbage but
-		 * its value will never be used.
-		 */
-	    } while (--n);
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
 #endif
             more += wsize;
         }
@@ -1100,8 +1114,8 @@
    _tr_flush_block(s, (s->block_start >= 0L ? \
                    (charf *)&s->window[(unsigned)s->block_start] : \
                    (charf *)Z_NULL), \
-		(ulg)((long)s->strstart - s->block_start), \
-		(eof)); \
+                (ulg)((long)s->strstart - s->block_start), \
+                (eof)); \
    s->block_start = s->strstart; \
    flush_pending(s->strm); \
    Tracev((stderr,"[FLUSH]")); \
@@ -1142,32 +1156,32 @@
         if (s->lookahead <= 1) {
 
             Assert(s->strstart < s->w_size+MAX_DIST(s) ||
-		   s->block_start >= (long)s->w_size, "slide too late");
+                   s->block_start >= (long)s->w_size, "slide too late");
 
             fill_window(s);
             if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
 
             if (s->lookahead == 0) break; /* flush the current block */
         }
-	Assert(s->block_start >= 0L, "block gone");
+        Assert(s->block_start >= 0L, "block gone");
 
-	s->strstart += s->lookahead;
-	s->lookahead = 0;
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
 
-	/* Emit a stored block if pending_buf will be full: */
- 	max_start = s->block_start + max_block_size;
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
         if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
-	    /* strstart == 0 is possible when wraparound on 16-bit machine */
-	    s->lookahead = (uInt)(s->strstart - max_start);
-	    s->strstart = (uInt)max_start;
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
             FLUSH_BLOCK(s, 0);
-	}
-	/* Flush if we may have to slide, otherwise block_start may become
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
          * negative and the data will be gone:
          */
         if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
             FLUSH_BLOCK(s, 0);
-	}
+        }
     }
     FLUSH_BLOCK(s, flush == Z_FINISH);
     return flush == Z_FINISH ? finish_done : block_done;
@@ -1196,8 +1210,8 @@
         if (s->lookahead < MIN_LOOKAHEAD) {
             fill_window(s);
             if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-	        return need_more;
-	    }
+                return need_more;
+            }
             if (s->lookahead == 0) break; /* flush the current block */
         }
 
@@ -1216,10 +1230,19 @@
              * of window index 0 (in particular we have to avoid a match
              * of the string with itself at the start of the input file).
              */
-            if (s->strategy != Z_HUFFMAN_ONLY) {
-                s->match_length = longest_match (s, hash_head);
+#ifdef FASTEST
+            if ((s->strategy < Z_HUFFMAN_ONLY) ||
+                (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+                s->match_length = longest_match_fast (s, hash_head);
             }
-            /* longest_match() sets match_start */
+#else
+            if (s->strategy < Z_HUFFMAN_ONLY) {
+                s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
+            }
+#endif
+            /* longest_match() or longest_match_fast() sets match_start */
         }
         if (s->match_length >= MIN_MATCH) {
             check_match(s, s->strstart, s->match_start, s->match_length);
@@ -1243,10 +1266,10 @@
                      * always MIN_MATCH bytes ahead.
                      */
                 } while (--s->match_length != 0);
-                s->strstart++; 
+                s->strstart++;
             } else
 #endif
-	    {
+            {
                 s->strstart += s->match_length;
                 s->match_length = 0;
                 s->ins_h = s->window[s->strstart];
@@ -1263,7 +1286,7 @@
             Tracevv((stderr,"%c", s->window[s->strstart]));
             _tr_tally_lit (s, s->window[s->strstart], bflush);
             s->lookahead--;
-            s->strstart++; 
+            s->strstart++;
         }
         if (bflush) FLUSH_BLOCK(s, 0);
     }
@@ -1271,6 +1294,7 @@
     return flush == Z_FINISH ? finish_done : block_done;
 }
 
+#ifndef FASTEST
 /* ===========================================================================
  * Same as above, but achieves better compression. We use a lazy
  * evaluation for matches: a match is finally adopted only if there is
@@ -1293,8 +1317,8 @@
         if (s->lookahead < MIN_LOOKAHEAD) {
             fill_window(s);
             if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
-	        return need_more;
-	    }
+                return need_more;
+            }
             if (s->lookahead == 0) break; /* flush the current block */
         }
 
@@ -1316,10 +1340,12 @@
              * of window index 0 (in particular we have to avoid a match
              * of the string with itself at the start of the input file).
              */
-            if (s->strategy != Z_HUFFMAN_ONLY) {
+            if (s->strategy < Z_HUFFMAN_ONLY) {
                 s->match_length = longest_match (s, hash_head);
+            } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+                s->match_length = longest_match_fast (s, hash_head);
             }
-            /* longest_match() sets match_start */
+            /* longest_match() or longest_match_fast() sets match_start */
 
             if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
                  (s->match_length == MIN_MATCH &&
@@ -1341,7 +1367,7 @@
             check_match(s, s->strstart-1, s->prev_match, s->prev_length);
 
             _tr_tally_dist(s, s->strstart -1 - s->prev_match,
-			   s->prev_length - MIN_MATCH, bflush);
+                           s->prev_length - MIN_MATCH, 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
@@ -1367,8 +1393,8 @@
              * is longer, truncate the previous match to a single literal.
              */
             Tracevv((stderr,"%c", s->window[s->strstart-1]));
-	    _tr_tally_lit(s, s->window[s->strstart-1], bflush);
-	    if (bflush) {
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
                 FLUSH_BLOCK_ONLY(s, 0);
             }
             s->strstart++;
@@ -1392,3 +1418,4 @@
     FLUSH_BLOCK(s, flush == Z_FINISH);
     return flush == Z_FINISH ? finish_done : block_done;
 }
+#endif /* FASTEST */
diff --git a/deflate.h b/deflate.h
index b99a48a..c3f8858 100644
--- a/deflate.h
+++ b/deflate.h
@@ -269,7 +269,7 @@
 void _tr_init         OF((deflate_state *s));
 int  _tr_tally        OF((deflate_state *s, unsigned dist, unsigned lc));
 void _tr_flush_block  OF((deflate_state *s, charf *buf, ulg stored_len,
-			  int eof));
+                          int eof));
 void _tr_align        OF((deflate_state *s));
 void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
                           int eof));
diff --git a/example.c b/example.c
index 8820e56..9fd13ce 100644
--- a/example.c
+++ b/example.c
@@ -1,6 +1,6 @@
 /* example.c -- usage example of the zlib compression library
  * Copyright (C) 1995-2003 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
@@ -37,22 +37,22 @@
 uLong dictId; /* Adler32 value of the dictionary */
 
 void test_compress      OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
-void test_gzio          OF((const char *out, const char *in, 
-		            Byte *uncompr, int uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
+void test_gzio          OF((const char *out, const char *in,
+                            Byte *uncompr, int uncomprLen));
 void test_deflate       OF((Byte *compr, uLong comprLen));
 void test_inflate       OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
 void test_large_deflate OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
 void test_large_inflate OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
 void test_flush         OF((Byte *compr, uLong *comprLen));
 void test_sync          OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
 void test_dict_deflate  OF((Byte *compr, uLong comprLen));
 void test_dict_inflate  OF((Byte *compr, uLong comprLen,
-		            Byte *uncompr, uLong uncomprLen));
+                            Byte *uncompr, uLong uncomprLen));
 int  main               OF((int argc, char *argv[]));
 
 /* ===========================================================================
@@ -75,7 +75,7 @@
 
     if (strcmp((char*)uncompr, hello)) {
         fprintf(stderr, "bad uncompress\n");
-	exit(1);
+        exit(1);
     } else {
         printf("uncompress(): %s\n", (char *)uncompr);
     }
@@ -103,11 +103,11 @@
     gzputc(file, 'h');
     if (gzputs(file, "ello") != 4) {
         fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
-	exit(1);
+        exit(1);
     }
     if (gzprintf(file, ", %s!", "hello") != 8) {
         fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
-	exit(1);
+        exit(1);
     }
     gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
     gzclose(file);
@@ -121,36 +121,36 @@
     uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
     if (uncomprLen != len) {
         fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
-	exit(1);
+        exit(1);
     }
     if (strcmp((char*)uncompr, hello)) {
         fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
-	exit(1);
+        exit(1);
     } else {
         printf("gzread(): %s\n", (char *)uncompr);
     }
 
     pos = gzseek(file, -8L, SEEK_CUR);
     if (pos != 6 || gztell(file) != pos) {
-	fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
-		(long)pos, (long)gztell(file));
-	exit(1);
+        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+                (long)pos, (long)gztell(file));
+        exit(1);
     }
 
     if (gzgetc(file) != ' ') {
-	fprintf(stderr, "gzgetc error\n");
-	exit(1);
+        fprintf(stderr, "gzgetc error\n");
+        exit(1);
     }
 
     gzgets(file, (char*)uncompr, uncomprLen);
     uncomprLen = strlen((char*)uncompr);
     if (uncomprLen != 6) { /* "hello!" */
         fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
-	exit(1);
+        exit(1);
     }
     if (strcmp((char*)uncompr, hello+7)) {
         fprintf(stderr, "bad gzgets after gzseek\n");
-	exit(1);
+        exit(1);
     } else {
         printf("gzgets() after gzseek: %s\n", (char *)uncompr);
     }
@@ -231,7 +231,7 @@
 
     if (strcmp((char*)uncompr, hello)) {
         fprintf(stderr, "bad inflate\n");
-	exit(1);
+        exit(1);
     } else {
         printf("inflate(): %s\n", (char *)uncompr);
     }
@@ -266,7 +266,7 @@
     CHECK_ERR(err, "deflate");
     if (c_stream.avail_in != 0) {
         fprintf(stderr, "deflate not greedy\n");
-	exit(1);
+        exit(1);
     }
 
     /* Feed in already compressed data and switch to no compression: */
@@ -286,7 +286,7 @@
     err = deflate(&c_stream, Z_FINISH);
     if (err != Z_STREAM_END) {
         fprintf(stderr, "deflate should report Z_STREAM_END\n");
-	exit(1);
+        exit(1);
     }
     err = deflateEnd(&c_stream);
     CHECK_ERR(err, "deflateEnd");
@@ -316,7 +316,7 @@
 
     for (;;) {
         d_stream.next_out = uncompr;            /* discard the output */
-	d_stream.avail_out = (uInt)uncomprLen;
+        d_stream.avail_out = (uInt)uncomprLen;
         err = inflate(&d_stream, Z_NO_FLUSH);
         if (err == Z_STREAM_END) break;
         CHECK_ERR(err, "large inflate");
@@ -327,7 +327,7 @@
 
     if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
         fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
-	exit(1);
+        exit(1);
     } else {
         printf("large_inflate(): OK\n");
     }
@@ -407,7 +407,7 @@
     if (err != Z_DATA_ERROR) {
         fprintf(stderr, "inflate should report DATA_ERROR\n");
         /* Because of incorrect adler32 */
-	exit(1);
+        exit(1);
     }
     err = inflateEnd(&d_stream);
     CHECK_ERR(err, "inflateEnd");
@@ -433,7 +433,7 @@
     CHECK_ERR(err, "deflateInit");
 
     err = deflateSetDictionary(&c_stream,
-			       (const Bytef*)dictionary, sizeof(dictionary));
+                               (const Bytef*)dictionary, sizeof(dictionary));
     CHECK_ERR(err, "deflateSetDictionary");
 
     dictId = c_stream.adler;
@@ -446,7 +446,7 @@
     err = deflate(&c_stream, Z_FINISH);
     if (err != Z_STREAM_END) {
         fprintf(stderr, "deflate should report Z_STREAM_END\n");
-	exit(1);
+        exit(1);
     }
     err = deflateEnd(&c_stream);
     CHECK_ERR(err, "deflateEnd");
@@ -480,14 +480,14 @@
     for (;;) {
         err = inflate(&d_stream, Z_NO_FLUSH);
         if (err == Z_STREAM_END) break;
-	if (err == Z_NEED_DICT) {
-	    if (d_stream.adler != dictId) {
-		fprintf(stderr, "unexpected dictionary");
-		exit(1);
-	    }
-	    err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
-				       sizeof(dictionary));
-	}
+        if (err == Z_NEED_DICT) {
+            if (d_stream.adler != dictId) {
+                fprintf(stderr, "unexpected dictionary");
+                exit(1);
+            }
+            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+                                       sizeof(dictionary));
+        }
         CHECK_ERR(err, "inflate with dict");
     }
 
@@ -496,7 +496,7 @@
 
     if (strcmp((char*)uncompr, hello)) {
         fprintf(stderr, "bad inflate with dict\n");
-	exit(1);
+        exit(1);
     } else {
         printf("inflate with dictionary: %s\n", (char *)uncompr);
     }
@@ -530,13 +530,13 @@
      */
     if (compr == Z_NULL || uncompr == Z_NULL) {
         printf("out of memory\n");
-	exit(1);
+        exit(1);
     }
     test_compress(compr, comprLen, uncompr, uncomprLen);
 
     test_gzio((argc > 1 ? argv[1] : TESTFILE),
               (argc > 2 ? argv[2] : TESTFILE),
-	      uncompr, (int)uncomprLen);
+              uncompr, (int)uncomprLen);
 
     test_deflate(compr, comprLen);
     test_inflate(compr, comprLen, uncompr, uncomprLen);
@@ -554,6 +554,5 @@
     free(compr);
     free(uncompr);
 
-    exit(0);
-    return 0; /* to avoid warning */
+    return 0;
 }
diff --git a/gzio.c b/gzio.c
index 3337353..1f561ac 100644
--- a/gzio.c
+++ b/gzio.c
@@ -117,17 +117,19 @@
         if (*p == 'r') s->mode = 'r';
         if (*p == 'w' || *p == 'a') s->mode = 'w';
         if (*p >= '0' && *p <= '9') {
-	    level = *p - '0';
-	} else if (*p == 'f') {
-	  strategy = Z_FILTERED;
-	} else if (*p == 'h') {
-	  strategy = Z_HUFFMAN_ONLY;
-	} else {
-	    *m++ = *p; /* copy the mode */
-	}
+            level = *p - '0';
+        } else if (*p == 'f') {
+          strategy = Z_FILTERED;
+        } else if (*p == 'h') {
+          strategy = Z_HUFFMAN_ONLY;
+        } else if (*p == 'R') {
+          strategy = Z_RLE;
+        } else {
+            *m++ = *p; /* copy the mode */
+        }
     } while (*p++ && m != fmode + sizeof(fmode));
     if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
-    
+
     if (s->mode == 'w') {
 #ifdef NO_DEFLATE
         err = Z_STREAM_ERROR;
@@ -168,17 +170,17 @@
          */
         fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
              Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
-	s->startpos = 10L;
-	/* We use 10L instead of ftell(s->file) to because ftell causes an
+        s->startpos = 10L;
+        /* We use 10L instead of ftell(s->file) to because ftell causes an
          * fflush on some systems. This version of the library doesn't use
          * startpos anyway in write mode, so this initialization is not
          * necessary.
          */
     } else {
-	check_header(s); /* skip the .gz header */
-	s->startpos = (ftell(s->file) - s->stream.avail_in);
+        check_header(s); /* skip the .gz header */
+        s->startpos = (ftell(s->file) - s->stream.avail_in);
     }
-    
+
     return (gzFile)s;
 }
 
@@ -223,11 +225,11 @@
     /* Make room to allow flushing */
     if (s->stream.avail_out == 0) {
 
-	s->stream.next_out = s->outbuf;
-	if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
-	    s->z_err = Z_ERRNO;
-	}
-	s->stream.avail_out = Z_BUFSIZE;
+        s->stream.next_out = s->outbuf;
+        if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+            s->z_err = Z_ERRNO;
+        }
+        s->stream.avail_out = Z_BUFSIZE;
     }
 
     return deflateParams (&(s->stream), level, strategy);
@@ -243,14 +245,14 @@
 {
     if (s->z_eof) return EOF;
     if (s->stream.avail_in == 0) {
-	errno = 0;
-	s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
-	if (s->stream.avail_in == 0) {
-	    s->z_eof = 1;
-	    if (ferror(s->file)) s->z_err = Z_ERRNO;
-	    return EOF;
-	}
-	s->stream.next_in = s->inbuf;
+        errno = 0;
+        s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+        if (s->stream.avail_in == 0) {
+            s->z_eof = 1;
+            if (ferror(s->file)) s->z_err = Z_ERRNO;
+            return EOF;
+        }
+        s->stream.next_in = s->inbuf;
     }
     s->stream.avail_in--;
     return *(s->stream.next_in)++;
@@ -292,7 +294,7 @@
 
     /* Peek ahead to check the gzip magic header */
     if (s->stream.next_in[0] != gz_magic[0] ||
-	s->stream.next_in[1] != gz_magic[1]) {
+        s->stream.next_in[1] != gz_magic[1]) {
         s->transparent = 1;
         return;
     }
@@ -303,27 +305,27 @@
     method = get_byte(s);
     flags = get_byte(s);
     if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
-	s->z_err = Z_DATA_ERROR;
-	return;
+        s->z_err = Z_DATA_ERROR;
+        return;
     }
 
     /* Discard time, xflags and OS code: */
     for (len = 0; len < 6; len++) (void)get_byte(s);
 
     if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
-	len  =  (uInt)get_byte(s);
-	len += ((uInt)get_byte(s))<<8;
-	/* len is garbage if EOF but the loop below will quit anyway */
-	while (len-- != 0 && get_byte(s) != EOF) ;
+        len  =  (uInt)get_byte(s);
+        len += ((uInt)get_byte(s))<<8;
+        /* len is garbage if EOF but the loop below will quit anyway */
+        while (len-- != 0 && get_byte(s) != EOF) ;
     }
     if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
-	while ((c = get_byte(s)) != 0 && c != EOF) ;
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
     }
     if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
-	while ((c = get_byte(s)) != 0 && c != EOF) ;
+        while ((c = get_byte(s)) != 0 && c != EOF) ;
     }
     if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
-	for (len = 0; len < 2; len++) (void)get_byte(s);
+        for (len = 0; len < 2; len++) (void)get_byte(s);
     }
     s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
 }
@@ -342,21 +344,21 @@
     TRYFREE(s->msg);
 
     if (s->stream.state != NULL) {
-	if (s->mode == 'w') {
+        if (s->mode == 'w') {
 #ifdef NO_DEFLATE
-	    err = Z_STREAM_ERROR;
+            err = Z_STREAM_ERROR;
 #else
-	    err = deflateEnd(&(s->stream));
+            err = deflateEnd(&(s->stream));
 #endif
-	} else if (s->mode == 'r') {
-	    err = inflateEnd(&(s->stream));
-	}
+        } else if (s->mode == 'r') {
+            err = inflateEnd(&(s->stream));
+        }
     }
     if (s->file != NULL && fclose(s->file)) {
 #ifdef ESPIPE
-	if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+        if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
 #endif
-	    err = Z_ERRNO;
+            err = Z_ERRNO;
     }
     if (s->z_err < 0) err = s->z_err;
 
@@ -391,69 +393,69 @@
 
     while (s->stream.avail_out != 0) {
 
-	if (s->transparent) {
-	    /* Copy first the lookahead bytes: */
-	    uInt n = s->stream.avail_in;
-	    if (n > s->stream.avail_out) n = s->stream.avail_out;
-	    if (n > 0) {
-		zmemcpy(s->stream.next_out, s->stream.next_in, n);
-		next_out += n;
-		s->stream.next_out = next_out;
-		s->stream.next_in   += n;
-		s->stream.avail_out -= n;
-		s->stream.avail_in  -= n;
-	    }
-	    if (s->stream.avail_out > 0) {
-		s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
-					     s->file);
-	    }
-	    len -= s->stream.avail_out;
-	    s->stream.total_in  += (uLong)len;
-	    s->stream.total_out += (uLong)len;
+        if (s->transparent) {
+            /* Copy first the lookahead bytes: */
+            uInt n = s->stream.avail_in;
+            if (n > s->stream.avail_out) n = s->stream.avail_out;
+            if (n > 0) {
+                zmemcpy(s->stream.next_out, s->stream.next_in, n);
+                next_out += n;
+                s->stream.next_out = next_out;
+                s->stream.next_in   += n;
+                s->stream.avail_out -= n;
+                s->stream.avail_in  -= n;
+            }
+            if (s->stream.avail_out > 0) {
+                s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+                                             s->file);
+            }
+            len -= s->stream.avail_out;
+            s->stream.total_in  += (uLong)len;
+            s->stream.total_out += (uLong)len;
             if (len == 0) s->z_eof = 1;
-	    return (int)len;
-	}
+            return (int)len;
+        }
         if (s->stream.avail_in == 0 && !s->z_eof) {
 
             errno = 0;
             s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
             if (s->stream.avail_in == 0) {
                 s->z_eof = 1;
-		if (ferror(s->file)) {
-		    s->z_err = Z_ERRNO;
-		    break;
-		}
+                if (ferror(s->file)) {
+                    s->z_err = Z_ERRNO;
+                    break;
+                }
             }
             s->stream.next_in = s->inbuf;
         }
         s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
 
-	if (s->z_err == Z_STREAM_END) {
-	    /* Check CRC and original size */
-	    s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
-	    start = s->stream.next_out;
+        if (s->z_err == Z_STREAM_END) {
+            /* Check CRC and original size */
+            s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+            start = s->stream.next_out;
 
-	    if (getLong(s) != s->crc) {
-		s->z_err = Z_DATA_ERROR;
-	    } else {
-	        (void)getLong(s);
+            if (getLong(s) != s->crc) {
+                s->z_err = Z_DATA_ERROR;
+            } else {
+                (void)getLong(s);
                 /* The uncompressed length returned by above getlong() may
                  * be different from s->stream.total_out) in case of
-		 * concatenated .gz files. Check for such files:
-		 */
-		check_header(s);
-		if (s->z_err == Z_OK) {
-		    uLong total_in = s->stream.total_in;
-		    uLong total_out = s->stream.total_out;
+                 * concatenated .gz files. Check for such files:
+                 */
+                check_header(s);
+                if (s->z_err == Z_OK) {
+                    uLong total_in = s->stream.total_in;
+                    uLong total_out = s->stream.total_out;
 
-		    inflateReset(&(s->stream));
-		    s->stream.total_in = total_in;
-		    s->stream.total_out = total_out;
-		    s->crc = crc32(0L, Z_NULL, 0);
-		}
-	    }
-	}
-	if (s->z_err != Z_OK || s->z_eof) break;
+                    inflateReset(&(s->stream));
+                    s->stream.total_in = total_in;
+                    s->stream.total_out = total_out;
+                    s->crc = crc32(0L, Z_NULL, 0);
+                }
+            }
+        }
+        if (s->z_err != Z_OK || s->z_eof) break;
     }
     s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
 
@@ -580,11 +582,11 @@
 #else /* not ANSI C */
 
 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-	               a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
     gzFile file;
     const char *format;
     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
-	a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
 {
     char buf[Z_PRINTF_BUFSIZE];
     int len;
@@ -592,25 +594,25 @@
 #ifdef NO_snprintf
 #  ifdef HAS_sprintf_void
     sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
-	    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */
     if (len <= 0) return 0;
 #  else
     len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
-	        a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     if (len <= 0 || len >= sizeof(buf))
         return 0;
 #  endif
 #else
 #  ifdef HAS_snprintf_void
     snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
-	     a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     len = strlen(buf);
     if (len <= 0)
         return 0;
 #  else
     len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
-	         a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     if (len <= 0 || len >= sizeof(buf))
         return 0;
 #  endif
@@ -677,14 +679,14 @@
         if (done) break;
         s->z_err = deflate(&(s->stream), flush);
 
-	/* Ignore the second of two consecutive flushes: */
-	if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+        /* Ignore the second of two consecutive flushes: */
+        if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
 
         /* deflate has finished flushing only when it hasn't used up
-         * all the available space in the output buffer: 
+         * all the available space in the output buffer:
          */
         done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
- 
+
         if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
     }
     return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
@@ -719,86 +721,86 @@
     gz_stream *s = (gz_stream*)file;
 
     if (s == NULL || whence == SEEK_END ||
-	s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
-	return -1L;
+        s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+        return -1L;
     }
-    
+
     if (s->mode == 'w') {
 #ifdef NO_DEFLATE
-	return -1L;
+        return -1L;
 #else
-	if (whence == SEEK_SET) {
-	    offset -= s->stream.total_in;
-	}
-	if (offset < 0) return -1L;
+        if (whence == SEEK_SET) {
+            offset -= s->stream.total_in;
+        }
+        if (offset < 0) return -1L;
 
-	/* At this point, offset is the number of zero bytes to write. */
-	if (s->inbuf == Z_NULL) {
-	    s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+        /* At this point, offset is the number of zero bytes to write. */
+        if (s->inbuf == Z_NULL) {
+            s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
             if (s->inbuf == Z_NULL) return -1L;
-	    zmemzero(s->inbuf, Z_BUFSIZE);
-	}
-	while (offset > 0)  {
-	    uInt size = Z_BUFSIZE;
-	    if (offset < Z_BUFSIZE) size = (uInt)offset;
+            zmemzero(s->inbuf, Z_BUFSIZE);
+        }
+        while (offset > 0)  {
+            uInt size = Z_BUFSIZE;
+            if (offset < Z_BUFSIZE) size = (uInt)offset;
 
-	    size = gzwrite(file, s->inbuf, size);
-	    if (size == 0) return -1L;
+            size = gzwrite(file, s->inbuf, size);
+            if (size == 0) return -1L;
 
-	    offset -= size;
-	}
-	return (z_off_t)s->stream.total_in;
+            offset -= size;
+        }
+        return (z_off_t)s->stream.total_in;
 #endif
     }
     /* Rest of function is for reading only */
 
     /* compute absolute position */
     if (whence == SEEK_CUR) {
-	offset += s->stream.total_out;
+        offset += s->stream.total_out;
     }
     if (offset < 0) return -1L;
 
     if (s->transparent) {
-	/* map to fseek */
-	s->stream.avail_in = 0;
-	s->stream.next_in = s->inbuf;
+        /* map to fseek */
+        s->stream.avail_in = 0;
+        s->stream.next_in = s->inbuf;
         if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
 
-	s->stream.total_in = s->stream.total_out = (uLong)offset;
-	return offset;
+        s->stream.total_in = s->stream.total_out = (uLong)offset;
+        return offset;
     }
 
     /* For a negative seek, rewind and use positive seek */
     if ((uLong)offset >= s->stream.total_out) {
-	offset -= s->stream.total_out;
+        offset -= s->stream.total_out;
     } else if (gzrewind(file) < 0) {
-	return -1L;
+        return -1L;
     }
     /* offset is now the number of bytes to skip. */
 
     if (offset != 0 && s->outbuf == Z_NULL) {
-	s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+        s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
         if (s->outbuf == Z_NULL) return -1L;
     }
     while (offset > 0)  {
-	int size = Z_BUFSIZE;
-	if (offset < Z_BUFSIZE) size = (int)offset;
+        int size = Z_BUFSIZE;
+        if (offset < Z_BUFSIZE) size = (int)offset;
 
-	size = gzread(file, s->outbuf, (uInt)size);
-	if (size <= 0) return -1L;
-	offset -= size;
+        size = gzread(file, s->outbuf, (uInt)size);
+        if (size <= 0) return -1L;
+        offset -= size;
     }
     return (z_off_t)s->stream.total_out;
 }
 
 /* ===========================================================================
-     Rewinds input file. 
+     Rewinds input file.
 */
 int ZEXPORT gzrewind (file)
     gzFile file;
 {
     gz_stream *s = (gz_stream*)file;
-    
+
     if (s == NULL || s->mode != 'r') return -1;
 
     s->z_err = Z_OK;
@@ -806,10 +808,10 @@
     s->stream.avail_in = 0;
     s->stream.next_in = s->inbuf;
     s->crc = crc32(0L, Z_NULL, 0);
-	
+
     if (s->startpos == 0) { /* not a compressed file */
-	rewind(s->file);
-	return 0;
+        rewind(s->file);
+        return 0;
     }
 
     (void) inflateReset(&s->stream);
@@ -835,7 +837,7 @@
     gzFile file;
 {
     gz_stream *s = (gz_stream*)file;
-    
+
     return (s == NULL || s->mode != 'r') ? 0 : s->z_eof;
 }
 
@@ -885,7 +887,7 @@
 
     if (s->mode == 'w') {
 #ifdef NO_DEFLATE
-	return Z_STREAM_ERROR;
+        return Z_STREAM_ERROR;
 #else
         err = do_flush (file, Z_FINISH);
         if (err != Z_OK) return destroy((gz_stream*)file);
diff --git a/infback.c b/infback.c
index 46090ad..fdd7d89 100644
--- a/infback.c
+++ b/infback.c
@@ -603,11 +603,8 @@
 int ZEXPORT inflateBackEnd(strm)
 z_stream FAR *strm;
 {
-    struct inflate_state FAR *state;
-
     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == Z_NULL)
         return Z_STREAM_ERROR;
-    state = (struct inflate_state FAR *)strm->state;
     ZFREE(strm, strm->state);
     strm->state = Z_NULL;
     Tracev((stderr, "inflate: end\n"));
diff --git a/inffast.c b/inffast.c
index 8d145c2..59a8af8 100644
--- a/inffast.c
+++ b/inffast.c
@@ -133,7 +133,7 @@
                     hold += (unsigned long)(PUP(in)) << bits;
                     bits += 8;
                 }
-                len += hold & ((1U << op) - 1);
+                len += (unsigned)hold & ((1U << op) - 1);
                 hold >>= op;
                 bits -= op;
             }
@@ -161,7 +161,7 @@
                         bits += 8;
                     }
                 }
-                dist += hold & ((1U << op) - 1);
+                dist += (unsigned)hold & ((1U << op) - 1);
                 hold >>= op;
                 bits -= op;
                 Tracevv((stderr, "inflate:         distance %u\n", dist));
diff --git a/inflate.c b/inflate.c
index 36fbb75..1da2776 100644
--- a/inflate.c
+++ b/inflate.c
@@ -70,14 +70,14 @@
  * - Changed many types to unsigned or unsigned short to avoid warnings
  * - Added inflateCopy() function
  *
- * 1.2.0	9 Mar 2003
+ * 1.2.0        9 Mar 2003
  * - Changed inflateBack() interface to provide separate opaque descriptors
  *   for the in() and out() functions
  * - Changed inflateBack() argument and in_func typedef to swap the length
  *   and buffer address return values for the input function
  * - Check next_in and next_out for Z_NULL on entry to inflate()
  *
- * Remainder of change history is in ChangeLog in zlib distribution.
+ * The history for versions past 1.2.0 are in ChangeLog in zlib distribution.
  */
 
 #include "zutil.h"
diff --git a/inftrees.c b/inftrees.c
index 24ca089..a4e0745 100644
--- a/inftrees.c
+++ b/inftrees.c
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.2.0 Copyright 1995-2003 Mark Adler ";
+   " inflate 1.2.0.1 Copyright 1995-2003 Mark Adler ";
 /*
   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
@@ -62,7 +62,7 @@
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 194};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 205, 64};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/minigzip.c b/minigzip.c
index 97b7c2d..3918cbc 100644
--- a/minigzip.c
+++ b/minigzip.c
@@ -1,6 +1,7 @@
 /* minigzip.c -- simulate gzip using the zlib compression library
  * Copyright (C) 1995-2002 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * Adapted for Z_RLE by Cosmin Truta, 2003.
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /*
@@ -147,7 +148,7 @@
     if (buf_len <= 0) return Z_ERRNO;
 
     /* Now do the actual mmap: */
-    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 
+    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
     if (buf == (caddr_t)(-1)) return Z_ERRNO;
 
     /* Compress the whole file at once: */
@@ -179,8 +180,8 @@
         if (len == 0) break;
 
         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
-	    error("failed fwrite");
-	}
+            error("failed fwrite");
+        }
     }
     if (fclose(out)) error("failed fclose");
 
@@ -260,10 +261,11 @@
 
 
 /* ===========================================================================
- * Usage:  minigzip [-d] [-f] [-h] [-1 to -9] [files...]
+ * Usage:  minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...]
  *   -d : decompress
  *   -f : compress with Z_FILTERED
  *   -h : compress with Z_HUFFMAN_ONLY
+ *   -r : compress with Z_RLE
  *   -1 to -9 : compression level
  */
 
@@ -282,16 +284,18 @@
 
     while (argc > 0) {
       if (strcmp(*argv, "-d") == 0)
-	uncompr = 1;
+        uncompr = 1;
       else if (strcmp(*argv, "-f") == 0)
-	outmode[3] = 'f';
+        outmode[3] = 'f';
       else if (strcmp(*argv, "-h") == 0)
-	outmode[3] = 'h';
+        outmode[3] = 'h';
+      else if (strcmp(*argv, "-r") == 0)
+        outmode[3] = 'R';
       else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
-	       (*argv)[2] == 0)
-	outmode[2] = (*argv)[1];
+               (*argv)[2] == 0)
+        outmode[2] = (*argv)[1];
       else
-	break;
+        break;
       argc--, argv++;
     }
     if (argc == 0) {
@@ -315,6 +319,5 @@
             }
         } while (argv++, --argc);
     }
-    exit(0);
-    return 0; /* to avoid warning */
+    return 0;
 }
diff --git a/msdos/Makefile.bor b/msdos/Makefile.bor
new file mode 100644
index 0000000..4ad4061
--- /dev/null
+++ b/msdos/Makefile.bor
@@ -0,0 +1,109 @@
+# Makefile for zlib
+# Borland C++
+# Updated for zlib-1.2.x by Cosmin Truta, 15-Mar-2003.
+
+# To use, do "make -fmakefile.bor"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+#    -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to the LOC macro below:
+#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C++, Borland C++ ------------
+
+#    Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+#    should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# memory model: one of s, m, c, l (small, medium, compact, large)
+MODEL=l
+
+# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version
+CC=bcc
+LD=bcc
+AR=tlib
+
+# compiler flags
+# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0
+CFLAGS=-O2 -Z -m$(MODEL) $(LOC)
+
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+clean:
+	-del *.obj
+	-del *.exe
+	-del *.lib
+	-del zlib_$(MODEL).bak
+	-del foo.gz
diff --git a/msdos/Makefile.tc b/msdos/Makefile.tc
new file mode 100644
index 0000000..d0a7864
--- /dev/null
+++ b/msdos/Makefile.tc
@@ -0,0 +1,94 @@
+# Makefile for zlib
+# Turbo C 2.01, Turbo C++ 1.01
+# Updated for zlib-1.2.x by Cosmin Truta, 15-Mar-2003.
+
+# To use, do "make -fmakefile.tc"
+# To compile in small model, set below: MODEL=s
+
+# WARNING: the small model is supported but only for small values of
+# MAX_WBITS and MAX_MEM_LEVEL. For example:
+#    -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+# If you wish to reduce the memory requirements (default 256K for big
+# objects plus a few K), you can add to CFLAGS below:
+#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
+# See zconf.h for details about the memory requirements.
+
+# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------
+MODEL=l
+CC=tcc
+LD=tcc
+AR=tlib
+# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+CFLAGS=-O2 -G -Z -m$(MODEL)
+LDFLAGS=-m$(MODEL) -f-
+
+
+# variables
+ZLIB_LIB = zlib_$(MODEL).lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d
+
+clean:
+	-del *.obj
+	-del *.exe
+	-del *.lib
+	-del zlib_$(MODEL).bak
+	-del foo.gz
diff --git a/old/msdos/Makefile.bor b/old/msdos/Makefile.bor
deleted file mode 100644
index f5651b4..0000000
--- a/old/msdos/Makefile.bor
+++ /dev/null
@@ -1,125 +0,0 @@
-# Makefile for zlib
-# Borland C++   ************ UNTESTED ***********
-
-# To use, do "make -fmakefile.bor"
-# To compile in small model, set below: MODEL=s
-
-# WARNING: the small model is supported but only for small values of
-# MAX_WBITS and MAX_MEM_LEVEL. For example:
-#    -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3
-# If you wish to reduce the memory requirements (default 256K for big
-# objects plus a few K), you can add to the LOC macro below:
-#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
-# See zconf.h for details about the memory requirements.
-
-# ------------- Turbo C++, Borland C++ -------------
-
-#    Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
-#    should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
-#    to the declaration of LOC here:
-LOC = $(LOCAL_ZLIB)
-
-# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
-CPU_TYP = 0
-
-# Memory model: one of s, m, c, l (small, medium, compact, large)
-MODEL=l
-
-CC=bcc
-#   replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version
-LD=$(CC)
-AR=tlib
-
-# compiler flags
-CFLAGS=-O2 -Z -m$(MODEL) $(LOC)
-#   replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0
-
-LDFLAGS=-m$(MODEL)
-
-O=.obj
-
-# variables
-OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \
-  trees$(O)
-OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\
-  trees$(O)
-OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \
-  infutil$(O) inffast$(O)
-OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\
-  infutil$(O)+inffast$(O)
-
-ZLIB_H = zlib.h zconf.h
-ZUTIL_H = zutil.h $(ZLIB_H)
-
-ZLIB_LIB = zlib_$(MODEL).lib
-
-all: test
-
-# individual dependencies and action rules:
-adler32.obj: adler32.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-compress.obj: compress.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-crc32.obj: crc32.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-deflate.obj: deflate.c deflate.h $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-gzio.obj: gzio.c $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h
-	$(CC) -c $(CFLAGS) $*.c
-
-infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inflate.obj: inflate.c $(ZUTIL_H) infblock.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h
-	$(CC) -c $(CFLAGS) $*.c
-
-infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h
-	$(CC) -c $(CFLAGS) $*.c
-
-trees.obj: trees.c deflate.h $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-uncompr.obj: uncompr.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-zutil.obj: zutil.c $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-example.obj: example.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-minigzip.obj: minigzip.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-# we must cut the command line to fit in the MS/DOS 128 byte limit:
-$(ZLIB_LIB): $(OBJ1) $(OBJ2)
-	del $(ZLIB_LIB)
-	$(AR) $(ZLIB_LIB) +$(OBJP1)
-	$(AR) $(ZLIB_LIB) +$(OBJP2)
-
-example.exe: example.obj $(ZLIB_LIB)
-	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
-
-minigzip.exe: minigzip.obj $(ZLIB_LIB)
-	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
-
-test: example.exe minigzip.exe
-	example
-	echo hello world | minigzip | minigzip -d 
-
-#clean:
-#	del *.obj
-#	del *.exe
diff --git a/old/msdos/Makefile.tc b/old/msdos/Makefile.tc
deleted file mode 100644
index 63e0550..0000000
--- a/old/msdos/Makefile.tc
+++ /dev/null
@@ -1,108 +0,0 @@
-# Makefile for zlib
-# TurboC 2.0
-
-# To use, do "make -fmakefile.tc"
-# To compile in small model, set below: MODEL=-ms
-
-# WARNING: the small model is supported but only for small values of
-# MAX_WBITS and MAX_MEM_LEVEL. For example:
-#    -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
-# If you wish to reduce the memory requirements (default 256K for big
-# objects plus a few K), you can add to CFLAGS below:
-#   -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14
-# See zconf.h for details about the memory requirements.
-
-# ------------- Turbo C 2.0 -------------
-MODEL=l
-# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
-CFLAGS=-O2 -G -Z -m$(MODEL)
-CC=tcc -I\tc\include
-LD=tcc -L\tc\lib
-AR=tlib
-LDFLAGS=-m$(MODEL) -f-
-O=.obj
-
-# variables
-OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \
-  trees$(O)
-OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\
-  trees$(O)
-OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \
-  infutil$(O) inffast$(O)
-OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\
-  infutil$(O)+inffast$(O)
-
-ZLIB_H = zlib.h zconf.h
-ZUTIL_H = zutil.h $(ZLIB_H)
-
-ZLIB_LIB = zlib_$(MODEL).lib
-
-all: test
-
-adler32.obj: adler32.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-compress.obj: compress.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-crc32.obj: crc32.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-deflate.obj: deflate.c deflate.h $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-gzio.obj: gzio.c $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h
-	$(CC) -c $(CFLAGS) $*.c
-
-infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inflate.obj: inflate.c $(ZUTIL_H) infblock.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h
-	$(CC) -c $(CFLAGS) $*.c
-
-infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h
-	$(CC) -c $(CFLAGS) $*.c
-
-inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h
-	$(CC) -c $(CFLAGS) $*.c
-
-trees.obj: trees.c deflate.h $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-uncompr.obj: uncompr.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-zutil.obj: zutil.c $(ZUTIL_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-example.obj: example.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-minigzip.obj: minigzip.c $(ZLIB_H)
-	$(CC) -c $(CFLAGS) $*.c
-
-# we must cut the command line to fit in the MS/DOS 128 byte limit:
-$(ZLIB_LIB): $(OBJ1) $(OBJ2)
-	del $(ZLIB_LIB)
-	$(AR) $(ZLIB_LIB) +$(OBJP1)
-	$(AR) $(ZLIB_LIB) +$(OBJP2)
-
-example.exe: example.obj $(ZLIB_LIB)
-	$(LD) $(LDFLAGS) -eexample.exe example.obj $(ZLIB_LIB)
-
-minigzip.exe: minigzip.obj $(ZLIB_LIB)
-	$(LD) $(LDFLAGS) -eminigzip.exe minigzip.obj $(ZLIB_LIB)
-
-test: example.exe minigzip.exe
-	example
-	echo hello world | minigzip | minigzip -d 
-
-#clean:
-#	del *.obj
-#	del *.exe
diff --git a/trees.c b/trees.c
index f7f4a84..5f6d4af 100644
--- a/trees.c
+++ b/trees.c
@@ -1,6 +1,6 @@
 /* trees.c -- output deflated data using Huffman coding
  * Copyright (C) 1995-2003 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /*
@@ -334,42 +334,42 @@
 
     Assert (header != NULL, "Can't open trees.h");
     fprintf(header,
-	    "/* header created automatically with -DGEN_TREES_H */\n\n");
+            "/* 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, "{{%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, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
     }
 
     fprintf(header, "const uch _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, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
     }
 
     fprintf(header, "const uch _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, "%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, "%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));
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
     }
 
     fclose(header);
@@ -930,39 +930,39 @@
     /* Build the Huffman trees unless a stored block is forced */
     if (s->level > 0) {
 
-	 /* Check if the file is ascii or binary */
-	if (s->data_type == Z_UNKNOWN) set_data_type(s);
+         /* Check if the file is ascii or binary */
+        if (s->data_type == Z_UNKNOWN) set_data_type(s);
 
-	/* Construct the literal and distance trees */
-	build_tree(s, (tree_desc *)(&(s->l_desc)));
-	Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
-		s->static_len));
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
 
-	build_tree(s, (tree_desc *)(&(s->d_desc)));
-	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_tree(s, (tree_desc *)(&(s->d_desc)));
+        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.
-	 */
-	max_blindex = build_bl_tree(s);
+        /* 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.
+         */
+        max_blindex = build_bl_tree(s);
 
         /* Determine the best encoding. Compute the block lengths in bytes. */
-	opt_lenb = (s->opt_len+3+7)>>3;
-	static_lenb = (s->static_len+3+7)>>3;
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
 
-	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));
+        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));
 
-	if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
 
     } else {
         Assert(buf != (char*)0, "lost buf");
-	opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
     }
 
 #ifdef FORCE_STORED
@@ -1199,7 +1199,7 @@
     s->last_eob_len = 8; /* enough lookahead for inflate */
 
     if (header) {
-        put_short(s, (ush)len);   
+        put_short(s, (ush)len);
         put_short(s, (ush)~len);
 #ifdef DEBUG
         s->bits_sent += 2*16;
diff --git a/win32/Makefile-dll.msc b/win32/Makefile-dll.msc
new file mode 100644
index 0000000..516f4cf
--- /dev/null
+++ b/win32/Makefile-dll.msc
@@ -0,0 +1,76 @@
+# Makefile for zlib.dll -- Microsoft (Visual) C.

+# Author: Cosmin Truta, 11-Mar-2003.

+#

+# Usage: nmake -f win32/Makefile-dll.msc

+

+CC = cl

+LD = cl

+CFLAGS = -nologo -MD -O2

+LDFLAGS = -nologo

+

+OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj \

+       inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj

+

+# targets

+all: zlib.dll zlib.lib example.exe minigzip.exe

+

+zlib.lib: $(OBJS)

+	lib -out:$@ $(OBJS)

+

+zlib.dll: $(OBJS) win32/zlib.def

+	link -release -def:win32/zlib.def -dll -out:$@ $(OBJS)

+

+zlib.lib: zlib.dll

+

+example.exe: example.obj zlib.lib

+	$(LD) $(LDFLAGS) example.obj zlib.lib

+

+minigzip.exe: minigzip.obj zlib.lib

+	$(LD) $(LDFLAGS) minigzip.obj zlib.lib

+

+.c.obj:

+	$(CC) -c $(CFLAGS) $*.c

+

+adler32.obj: adler32.c zlib.h zconf.h

+

+compress.obj: compress.c zlib.h zconf.h

+

+crc32.obj: crc32.c zlib.h zconf.h crc32.h

+

+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h

+

+gzio.obj: gzio.c zutil.h zlib.h zconf.h

+

+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h inffixed.h

+

+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h

+

+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h inffixed.h

+

+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h

+

+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h

+

+uncompr.obj: uncompr.c zlib.h zconf.h

+

+zutil.obj: zutil.c zutil.h zlib.h zconf.h

+

+example.obj: example.c zlib.h zconf.h

+

+minigzip.obj: minigzip.c zlib.h zconf.h

+

+# testing

+test: example.exe minigzip.exe

+	example

+	echo hello world | minigzip | minigzip -d 

+

+# cleanup

+clean:

+	del *.obj

+	del *.dll

+	del *.lib

+	del *.exp

+	del *.exe

diff --git a/win32/Makefile.bor b/win32/Makefile.bor
new file mode 100644
index 0000000..f1a1c46
--- /dev/null
+++ b/win32/Makefile.bor
@@ -0,0 +1,91 @@
+# Makefile for zlib
+# Borland C++ for Win32
+# Updated for zlib-1.2.x by Cosmin Truta, 11-Mar-2003.
+
+# Usage: "make -f win32/makefile.bor"
+
+# ------------ Borland C++ for Win32 ------------
+
+#    Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
+#    should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_ZLIB)
+
+CC = bcc32
+LD = bcc32
+AR = tlib
+CFLAGS = -O2 -d -k- $(LOC)
+LDFLAGS = $(LOC)
+
+
+# variables
+ZLIB_LIB = zlib.lib
+
+OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj
+OBJ2 = inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
+OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infback.obj
+OBJP2 = +inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
+
+
+# targets
+all: $(ZLIB_LIB) example.exe minigzip.exe
+
+.c.obj:
+	$(CC) -c $(CFLAGS) $*.c
+
+adler32.obj: adler32.c zlib.h zconf.h
+
+compress.obj: compress.c zlib.h zconf.h
+
+crc32.obj: crc32.c zlib.h zconf.h crc32.h
+
+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
+
+gzio.obj: gzio.c zutil.h zlib.h zconf.h
+
+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h
+
+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
+ inffast.h inffixed.h
+
+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
+
+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
+
+uncompr.obj: uncompr.c zlib.h zconf.h
+
+zutil.obj: zutil.c zutil.h zlib.h zconf.h
+
+example.obj: example.c zlib.h zconf.h
+
+minigzip.obj: minigzip.c zlib.h zconf.h
+
+
+# For the sake of the old Borland make,
+# the command line is cut to fit in the MS-DOS 128 byte limit:
+$(ZLIB_LIB): $(OBJ1) $(OBJ2)
+	-del $(ZLIB_LIB)
+	$(AR) $(ZLIB_LIB) $(OBJP1)
+	$(AR) $(ZLIB_LIB) $(OBJP2)
+
+example.exe: example.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
+
+minigzip.exe: minigzip.obj $(ZLIB_LIB)
+	$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
+
+test: example.exe minigzip.exe
+	example
+	echo hello world | minigzip | minigzip -d 
+
+clean:
+	-del *.obj
+	-del *.exe
+	-del *.lib
+	-del *.tds
+	-del zlib.bak
+	-del foo.gz
diff --git a/win32/Makefile.gcc b/win32/Makefile.gcc
new file mode 100644
index 0000000..7f9973b
--- /dev/null
+++ b/win32/Makefile.gcc
@@ -0,0 +1,105 @@
+# Makefile for zlib, derived from Makefile.dj2.
+# Modified for mingw32 by C. Spieler, 6/16/98.
+# Updated for zlib-1.2.x by Cosmin Truta, 11-Mar-2003.
+# Tested under Cygwin and MinGW.
+
+# Copyright (C) 1995-1998 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h 
+
+# To compile, or to compile and test, type:
+# 
+#   make -fmakefile.gcc;  make test -fmakefile.gcc
+# 
+# To install libz.a, zconf.h and zlib.h in the system directories, type:
+# 
+#    make install -fmakefile.gcc
+# 
+
+LIB = libz.a
+SHAREDLIB = libz.so
+VER = 1.2.0
+
+CC = gcc
+#CFLAGS = -DDEBUG -MMD -g
+CFLAGS = $(LOC) -O3 -Wall
+
+AS = $(CC)
+ASFLAGS = $(LOC) -Wall
+
+LD = $(CC)
+LDFLAGS = $(LOC) -s
+
+AR = ar
+ARFLAGS = rcs
+
+CP = cp -fp
+# If GNU install is available, replace $(CP) with install.
+INSTALL = $(CP)
+RM = rm -f
+
+prefix = /usr/local
+exec_prefix = $(prefix)
+
+OBJS = adler32.o compress.o crc32.o deflate.o gzio.o infback.o \
+       inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
+
+# to use the asm code: make OBJA=match.o
+OBJA =
+
+TEST_OBJS = example.o minigzip.o
+
+all: $(LIB) example minigzip
+
+test: all
+	./example
+	echo hello world | ./minigzip | ./minigzip -d 
+
+.c.o:
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+libz.a: $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+example: example.o $(LIB)
+	$(LD) -o $@ $< $(LIB)
+
+minigzip: minigzip.o $(LIB)
+	$(LD) -o $@ $< $(LIB)
+
+
+# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env .
+
+.PHONY : uninstall clean
+
+install: zlib.h zconf.h $(LIB)
+	-@if not exist $(INCLUDE_PATH)/nul mkdir $(INCLUDE_PATH)
+	-@if not exist $(LIBRARY_PATH)/nul mkdir $(LIBRARY_PATH)
+	$(INSTALL) zlib.h $(INCLUDE_PATH)
+	$(INSTALL) zconf.h $(INCLUDE_PATH)
+	$(INSTALL) $(LIB) $(LIBRARY_PATH)
+
+uninstall:
+	$(RM) $(INCLUDE_PATH)/zlib.h
+	$(RM) $(INCLUDE_PATH)/zconf.h
+	$(RM) $(LIBRARY_PATH)/libz.a
+
+clean:
+	$(RM) *.o
+	$(RM) *.exe
+	$(RM) libz.a
+	$(RM) foo.gz
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o:  zlib.h zconf.h 
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h  
diff --git a/win32/Makefile.msc b/win32/Makefile.msc
new file mode 100644
index 0000000..9760208
--- /dev/null
+++ b/win32/Makefile.msc
@@ -0,0 +1,69 @@
+# Makefile for (static) zlib -- Microsoft (Visual) C.

+# Author: Cosmin Truta, 11-Mar-2003.

+#

+# Usage: nmake -f win32/Makefile.msc

+

+CC = cl

+LD = cl

+CFLAGS = -nologo -MD -O2

+LDFLAGS = -nologo

+

+OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infback.obj \

+       inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj

+

+# targets

+all: zlib.lib example.exe minigzip.exe

+

+zlib.lib: $(OBJS)

+	lib -out:$@ $(OBJS)

+

+example.exe: example.obj zlib.lib

+	$(LD) $(LDFLAGS) example.obj zlib.lib

+

+minigzip.exe: minigzip.obj zlib.lib

+	$(LD) $(LDFLAGS) minigzip.obj zlib.lib

+

+.c.obj:

+	$(CC) -c $(CFLAGS) $*.c

+

+adler32.obj: adler32.c zlib.h zconf.h

+

+compress.obj: compress.c zlib.h zconf.h

+

+crc32.obj: crc32.c zlib.h zconf.h crc32.h

+

+deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h

+

+gzio.obj: gzio.c zutil.h zlib.h zconf.h

+

+infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h inffixed.h

+

+inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h

+

+inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \

+             inffast.h inffixed.h

+

+inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h

+

+trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h

+

+uncompr.obj: uncompr.c zlib.h zconf.h

+

+zutil.obj: zutil.c zutil.h zlib.h zconf.h

+

+example.obj: example.c zlib.h zconf.h

+

+minigzip.obj: minigzip.c zlib.h zconf.h

+

+# testing

+test: example.exe minigzip.exe

+	example

+	echo hello world | minigzip | minigzip -d 

+

+# cleanup

+clean:

+	del *.obj

+	del *.lib

+	del *.exe

diff --git a/contrib/minizip/zlibvc.def b/win32/zlib.def
similarity index 65%
rename from contrib/minizip/zlibvc.def
rename to win32/zlib.def
index 7e9d60d..3b4b05a 100644
--- a/contrib/minizip/zlibvc.def
+++ b/win32/zlib.def
@@ -1,12 +1,5 @@
-LIBRARY		"zlib"
-
-DESCRIPTION	'"""zlib data compression library"""'
-
-
-VERSION		1.11
-
-
-HEAPSIZE	1048576,8192
+LIBRARY		zlib.dll
+DESCRIPTION	"zlib compression library for Windows"
 
 EXPORTS
     adler32                        @1
@@ -50,25 +43,7 @@
     compress2                      @39
     gzputs                         @40
     gzgets                         @41
-
-	unzOpen                       @61
-	unzClose                      @62
-	unzGetGlobalInfo              @63
-	unzGetCurrentFileInfo         @64
-	unzGoToFirstFile              @65
-	unzGoToNextFile               @66
-	unzOpenCurrentFile            @67
-	unzReadCurrentFile            @68
-	unztell                       @70
-	unzeof                        @71
-	unzCloseCurrentFile           @72
-	unzGetGlobalComment           @73
-	unzStringFileNameCompare      @74
-	unzLocateFile                 @75
-	unzGetLocalExtrafield         @76
-
-	zipOpen                       @80
-	zipOpenNewFileInZip           @81
-	zipWriteInFileInZip           @82
-	zipCloseFileInZip             @83
-	zipClose                      @84
+; The following functions exist since zlib-1.2.0
+;   deflateBound                   @42
+;   compressBound                  @43
+; etc.
diff --git a/zconf.h b/zconf.h
index 8ef845e..f3c4430 100644
--- a/zconf.h
+++ b/zconf.h
@@ -91,7 +91,7 @@
 
 #ifndef STDC
 #  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const	/* note: need a more gentle solution here */
+#    define const       /* note: need a more gentle solution here */
 #  endif
 #endif
 
@@ -101,7 +101,10 @@
 #endif
 
 /* Old Borland C incorrectly complains about missing returns: */
-#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x460)
+#  define NEED_DUMMY_RETURN
+#endif
+#if defined(__TURBOC__) && !defined(__BORLANDC__)
 #  define NEED_DUMMY_RETURN
 #endif
 
@@ -169,17 +172,24 @@
 #  endif
 #endif
 
+#if defined(WIN32) && (!defined(ZLIB_WIN32_NODLL)) && (!defined(ZLIB_DLL))
+#  define ZLIB_DLL
+#endif
+
 /* Compile with -DZLIB_DLL for Windows DLL support */
 #if defined(ZLIB_DLL)
-#  if defined(_WINDOWS) || defined(WINDOWS)
-#    ifdef FAR
-#      undef FAR
+#  if defined(_WINDOWS) || defined(WINDOWS) || defined(WIN32)
+#    ifndef WINAPIV
+#      ifdef FAR
+#        undef FAR
+#      endif
+#      include <windows.h>
 #    endif
-#    include <windows.h>
-#    define ZEXPORT  WINAPI
 #    ifdef WIN32
+#      define ZEXPORT  WINAPI
 #      define ZEXPORTVA  WINAPIV
 #    else
+#      define ZEXPORT  WINAPI _export
 #      define ZEXPORTVA  FAR _cdecl _export
 #    endif
 #  endif
@@ -187,7 +197,7 @@
 #    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
 #      include <windows.h>
 #      define ZEXPORT __declspec(dllexport) WINAPI
-#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
+#      define ZEXPORTVA __declspec(dllexport) WINAPIV
 #    else
 #      if defined (_Windows) && defined (__DLL__)
 #        define ZEXPORT _export
@@ -246,9 +256,12 @@
    typedef Byte     *voidp;
 #endif
 
-#if 0	/* HAVE_UNISTD_H -- this line is updated by ./configure */
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
 #  include <sys/types.h> /* for off_t */
 #  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
 #  define z_off_t  off_t
 #endif
 #ifndef SEEK_SET
diff --git a/zconf.in.h b/zconf.in.h
index 8ef845e..f3c4430 100644
--- a/zconf.in.h
+++ b/zconf.in.h
@@ -91,7 +91,7 @@
 
 #ifndef STDC
 #  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-#    define const	/* note: need a more gentle solution here */
+#    define const       /* note: need a more gentle solution here */
 #  endif
 #endif
 
@@ -101,7 +101,10 @@
 #endif
 
 /* Old Borland C incorrectly complains about missing returns: */
-#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x460)
+#  define NEED_DUMMY_RETURN
+#endif
+#if defined(__TURBOC__) && !defined(__BORLANDC__)
 #  define NEED_DUMMY_RETURN
 #endif
 
@@ -169,17 +172,24 @@
 #  endif
 #endif
 
+#if defined(WIN32) && (!defined(ZLIB_WIN32_NODLL)) && (!defined(ZLIB_DLL))
+#  define ZLIB_DLL
+#endif
+
 /* Compile with -DZLIB_DLL for Windows DLL support */
 #if defined(ZLIB_DLL)
-#  if defined(_WINDOWS) || defined(WINDOWS)
-#    ifdef FAR
-#      undef FAR
+#  if defined(_WINDOWS) || defined(WINDOWS) || defined(WIN32)
+#    ifndef WINAPIV
+#      ifdef FAR
+#        undef FAR
+#      endif
+#      include <windows.h>
 #    endif
-#    include <windows.h>
-#    define ZEXPORT  WINAPI
 #    ifdef WIN32
+#      define ZEXPORT  WINAPI
 #      define ZEXPORTVA  WINAPIV
 #    else
+#      define ZEXPORT  WINAPI _export
 #      define ZEXPORTVA  FAR _cdecl _export
 #    endif
 #  endif
@@ -187,7 +197,7 @@
 #    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
 #      include <windows.h>
 #      define ZEXPORT __declspec(dllexport) WINAPI
-#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
+#      define ZEXPORTVA __declspec(dllexport) WINAPIV
 #    else
 #      if defined (_Windows) && defined (__DLL__)
 #        define ZEXPORT _export
@@ -246,9 +256,12 @@
    typedef Byte     *voidp;
 #endif
 
-#if 0	/* HAVE_UNISTD_H -- this line is updated by ./configure */
+#if 0           /* HAVE_UNISTD_H -- this line is updated by ./configure */
 #  include <sys/types.h> /* for off_t */
 #  include <unistd.h>    /* for SEEK_* and off_t */
+#  ifdef VMS
+#    include <unixio.h>   /* for off_t */
+#  endif
 #  define z_off_t  off_t
 #endif
 #ifndef SEEK_SET
diff --git a/zlib.h b/zlib.h
index c514256..2d239a2 100644
--- a/zlib.h
+++ b/zlib.h
@@ -1,5 +1,5 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.0, March 9th, 2003
+  version 1.2.0.1, March 17th, 2003
 
   Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler
 
@@ -37,7 +37,7 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.2.0"
+#define ZLIB_VERSION "1.2.0.1"
 
 /* 
      The 'zlib' compression library provides in-memory compression and
@@ -165,6 +165,7 @@
 
 #define Z_FILTERED            1
 #define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
 #define Z_DEFAULT_STRATEGY    0
 /* compression strategy; see deflateInit2() below for details */
 
@@ -461,14 +462,16 @@
 
      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), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
-   string match).  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 and Z_HUFFMAN_ONLY. The strategy parameter only affects
-   the compression ratio but not the correctness of the compressed output even
-   if it is not set appropriately.
+   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 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.
 
       deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
    memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
@@ -843,8 +846,9 @@
      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". (See the description
-   of deflateInit2 for more information about the strategy parameter.)
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
 
      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.
@@ -896,9 +900,12 @@
      Converts, formats, and writes the args to the compressed file under
    control of the format string, as in fprintf. gzprintf returns the number of
    uncompressed bytes actually written (0 in case of error).  The number of
-   uncompressed bytes written is limited to 4095.  The caller should assure
-   that this limit is not exceeded, since otherwise a buffer overflow may
-   result.
+   uncompressed bytes written is limited to 4095. The caller should assure that
+   this limit is not exceeded. If it is exceeded, then either gzprintf() will
+   return an error (0) with nothing written, or there will be a buffer overflow
+   with unpredictable consequences. The latter is possible only if zlib was
+   compiled with insecure variants of printf, i.e. sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
 */
 
 ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
diff --git a/zutil.h b/zutil.h
index d9c36ab..91083ed 100644
--- a/zutil.h
+++ b/zutil.h
@@ -150,6 +150,30 @@
 
          /* functions */
 
+#ifdef __STDC_VERSION__
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC99) && !(defined(__TURBOC__) && __TURBOC__ >= 0x550) && !defined(VSNPRINTF_DEFINED)
+#  ifdef MSDOS
+     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+        but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(__TURBOC__)
+#      define vsnprintf _vsnprintf
+#    endif
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#endif
+
 #ifdef HAVE_STRERROR
    extern char *strerror OF((int));
 #  define zstrerror(errnum) strerror(errnum)